首页 > 代码库 > 线性表

线性表

1.线性表相关定义:

线性表为a1,…,ai-1,ai,ai+1,…,an,则ai-1为ai的直接前驱元素,ai+1为ai的直接后驱元素。当i=1,2…,n-1时,ai有且仅有一个直接后驱;当i=2,3,…,n时,ai有且仅有一个直接前驱。即元素是有顺序的,第一个元素无前驱,最后一个元素无后驱,其他每个元素有且仅有一个前驱和后驱。

线性表元素个数定义线性表长度,n=0时称为空表。

 

2.顺序存储结构:

用一段地址连续的存储单元依次存储线性表的数据元素。

属性:起始位置、最大存储容量(数组长度)、线性表当前长度

注:线性表长度应小于等于数组长度

一个有趣的例子:图书馆占位。占了10个位置(数组长度),但来的人可以<=10,不可以>10。

1)读取第i个数据

直接返回数组下标为i-1的元素

2)在第i个位置插入新元素e

从最后一个元素遍历到第i个元素,分别将它们向后移动一个位置。然后将新元素e插入到第i个位置

3)删除第i个元素

从删除元素位置开始遍历到最后一个元素,分别讲它们向前移动一个位置

时间复杂度:

最好的情况,i=n,则不需移动其他元素,时间复杂度为O(1)

最坏的情况,i=1,则所有元素都需移动,时间复杂度为O(n)

 

#include <iostream>
using namespace std;
//顺序存储 
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20
typedef int elemtype;
typedef struct{
    elemtype data[MAXSIZE];
    int length;
}sqlist;
typedef int status;
//读取 
status getelem(sqlist L,int i,elemtype *e){
    if(L.length==0||i<1||i>L.length)
        return ERROR;
    *e=L.data[i-1];
    return OK;
} 
//插入
status linsert(sqlist *L,int i,elemtype e){
    int k;
    if (L->length==MAXSIZE)//当前线性表长度不能超过数组长度,否则不能插入 
        return ERROR;
    if(i<1||i>L->length)
        return ERROR;
    if(i<L->length)
    {
        for(k=L->length-1;k>=i-1;k--)
            L.data[k+1]=L.data[k];
    }
    L.data[i-1]=e;
    L->length++;
    return OK;
} 
//删除 
status ldelete(sqlist *L,int i,elemtype *e){
    if(L->length==0)//当前线性表不能为空,否则不能删除 
        return ERROR;
    if(i<1||i>L->length)
        return ERROR;
    *e=L->data[i-1];
    if(i<L->length){
        for(k=i;k<=L->length-1;k++)
            L->data[k-1]=L->data[k];
    }
    L->length--;
    return OK;
}


int main(int argc, char** argv) {
    return 0;
}

 

 

 

 

3.链式存储结构:

对数据元素ai,除存储其本身信息外,还需存储一个指示其直接后继的信息。数据域与指针域组成数据元素ai的存储映像,称为结点node。

n个结点链结成一个链表,由于每个结点中只包含一个指针域,称为单链表。

第一个结点的存储位置为头指针,之后的每一个结点就是上一个的后继指针指向的位置。规定最后一个结点指针为空(用NULL或^表示)

有时,会在一个结点前加一个头结点,数据域可以不存储信息。

1)读取第i个数据

声明一个指针指向链表第1个结点,遍历链表,让指针向后移动不断指向下一节点,直到第i个结点。

2)第i个数据插入结点s

先找到第i个数据,s->next=p->next;p->next=s;

3)第i个数据删除结点s

先找到第i个数据,s=p->next;p->next=s-next;即p->next=p->next->next

 

#include <iostream>
using namespace std;

//单链表
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20
typedef int elemtype;
typedef int status;
typedef struct node{
    elemtype data;
    struct node *next;
}node;
typedef struct node *linklist;//链表的构建不同于顺序结构的数组初始化
//链表的构建就是一个动态生成链表的过程。即从空表的初始状态起,依次建立各元素结点并插入链表
void createlisthead(linklist *L,int n){
    linklist p;
    int i;
    srand(time(0));
    *L=(linklist)malloc(sizeof(node));//
    (*L)->next=NULL;
    for (i=0;i<n;i++){
        p=(linklist)malloc(sizeof(node));
        p->data=http://www.mamicode.com/rand()%100+1;
        p->next=(*L)->next;
        (*L)->next=p;//典型的单链表插入操作哦 
    }
} 
//读取 
status getelem(linklist L,int i,elemtype *e){
    int j;
    linklist p;
    p=L->next;//P指向L的第1个结点 
    j=1;
    while(p&&j<i){
        p=p->next;
        ++j; 
    }  
    if(!p||j>1)
        return ERROR;
    *e=p->data;
    return OK;
} 
//插入
status linsert(linklist *L,int i,elemtype e){
    int j;
    linklist p,s;
    p=*L;
    j=1;
    while(p&&j<i){
        p=p->next;
        ++j; 
    }
    if(!p||j>1)
        return ERROR;
    s=(linklist)malloc(sizeof(node));
    s->data=http://www.mamicode.com/e;
    s->next=p->next;
    p->next=s;
    return OK;
} 
//删除
status ldelete(linklist *L,int i,elemtype e){
    int j;
    linklist p,s;
    p=*L;
    j=1;
    while(p&&j<i){
        p=p->next;
        ++j; 
    }
    if(!p||j>1)
        return ERROR;
    s=p->next;
    p->next=s->next;
    *e=s->data;
    free(s);
    return OK;
} 
//整表删除
status clearlist(linklist *L){
    linklist p,q;
    p=(*L)->next;
    while(p){
        q=p->next;
        free(p);
        p=q;
    }
    (*L)->next=NULL;
    return OK;
} 

 

 

 

 

4.链表之静态链表:

用数组描述链表:由两个数组域组成,data\cur。

将未被使用的数组元素称为备用链表。

数组的第一个元素,即下标为0的数组元素的cur存放备用链表的第一个节点的下标;数组的最后一个元素的cur存放第一个有数值的元素的下标。下一位置数据为空的数组元素,其cur为0。

1)插入

首先返回头元素的cur,即第一个空闲元素的下标,假设为p;另外还要给头元素的cur赋一个新值(即元素p的cur,下一个空闲元素的下标)

要在乙和丁之间插入丙,假设乙下标为m,丁下标为m+1。

形象的解释:先告诉乙,让其cur改为p;然后告诉丙,你只需要把你的cur改为m+1,问题就解决了。

2)删除

让数组最后元素的cur改为被删除元素的cur;

让被删除元素成为第一个优先空位(即头元素的cur改为被删除元素的下标)。

 

#include <iostream>
using namespace std;
//静态链表

#define MAXSIZE 1000
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20
typedef int elemtype;
typedef int status; 
typedef struct{
    elemtype data;
    int cur;
}component,staticlinklist[MAXSIZE];
status initlist(staticlinklist space){
    int i;
    for(i=0;i<MAXSIZE-1;i++){
        space[i].cur=i+1;
    }
    space[MAXSIZE-1].cur=0;//最后一个元素的cur为0
    return OK; 
}
//链表长度
int llength(staticlinklist space){
    int j=0;
    int i=space[MAXSIZE].cur;
    while(i){
        i=space[i].cur;
        j++;
    }
    return j;
} 
//备用链表
int malloc_sll(staticlinklist space){
    int i=space[0].cur;//第一个备用元素的下标
    if (space[0].cur)
        space[0].cur=space[i].cur;//第一个备用元素被使用后,需更新头元素的cur
    return i; 
} 
//插入
status linsert(staticlinklist L,int i,elemtype e){
    int j,k,l;
    k=MAXSIZE-1;//最后一个元素的下标
    if(i<1||i>MAXSIZE+1)
        return ERROR;
    j=malloc_sll(L);
    if (j)
    {
        L[j].data=e;
        for(l=1;l<i;l++){
            k=L[k].cur;//返回第i-1个元素的下标 
        }
        L[j].cur=L[k].cur;
        L[k].cur=j;//即第i个元素的下标为j,或者说第i-1个元素的cur指向j 
        return OK; 
    }
    return ERROR;
} 
void free_sll(staticlinklist space,int k){
    space[k].cur=space[0].cur;//将头元素的cur赋给要删除元素的cur。
    //即要删除元素称为备用链表的最优先元素,原来的最优先元素被降级为要删除元素的下一空闲元素 
    space[0].cur=k;
}
//删除
status ldelete(staticlinklist L,int i){
    int j,k;
    k=MAXSIZE-1;
    if(i<1||i>llength(L)+1)
        return ERROR;
    for (j=1;j<i;j++){
        k=L[k].cur;
    }
    j=L[k].cur;
    L[k].cur=L[j].cur;
    free_sll(L,j);
    return OK;
} 

 

线性表