线性表基本操作

来源:互联网 发布:数组和链表有什么区别 编辑:程序博客网 时间:2024/05/18 13:09

线性表是最简单、也是最基本的一种线性数据结构。它有两种存储方法:顺序表和链表,它一般有12种基本操作,主要基本操作是插入、删除和查找等。我这里把顺序表和单链表的这12种操作按自己的理解写了一遍,两两对照着看应该要好一点。


线性表12基本操作

准备(接下来也是这样比较,不做说明了)

顺序表(Sq —— SequenceList):

#define LIST_INIT_SIZE 100#define LISTINCREMENT 10typedef char ElemType;  //注意!typedef struct{    ElemType *elem;   //用一维数组存储数据元素    int length;       //线性表当前的长度    int listsize;     //当前分配的数组空间的最大容量(以ElemType为单位)    int incrementsize;//约定的增补空间量(以ElemType为单位)}SqList;void ErrorMassage(char *s)          //输出字符串s并退出原函数{    cout<<s<<endl;    exit(1);}/*做函数参数时&e与*e的区别:前者称为引用,使用被引用者的内存,本身无内存,相当于直接使用被引用者;                而后者是指针,指向一段内存且本身也有内存*///(SqList &L)需要对顺序表内容进行改变时加&,否则不加void ListIncrement(SqList &L)       //为顺序表扩大L.incrementsize个元素空间{    realloc(L.elem,(L.listsize+L.incrementsize)*sizeof(ElemType));    L.listsize+=L.incrementsize;    return;}

特别说明:我创建的单链表是有一个空的头结点,并不是直接取第一个结点做头结点,这点与本科书上的不相同

typedef char ElemType;typedef struct LNode{    ElemType data;    struct LNode *next;}LNode,*LinkList;void ErrorMassage(char *s)                      //输出字符串s并退出原函数{    cout<<s<<endl;    exit(1);}

一、InitList(&L):构造一个空的顺序表L

void InitList_Sq(SqList &L)         //创建一个空的顺序表L,但是已经分配了内存{    L.elem=new ElemType[LIST_INIT_SIZE];    L.length=0;    L.listsize=LIST_INIT_SIZE;    L.incrementsize=LISTINCREMENT;    return;}
void InitList_L(LinkList &L,int n)              //创建一个有头结点的单链表{    LNode *p,*q;    L=new LNode;    for(int i=0;i<n;i++)    {        q=new LNode;        q->data='A'+i;   //->是指针操作符        if(i>0)            p->next=q;        else            L->next=q;        p=q;    }    q->next=NULL;                               //令尾结点z指向空,以此作为某些函数结束条件    return;}

二、ListInsert(&L,i,e):在第i个元素前插入新元素e

void ListInsert_Sq(SqList &L,int i,ElemType e) //将元素e插入到顺序表第i个位置之前{    if(i<1||i>L.length+1) ErrorMassage("i is invalid!");    if(L.length>=L.listsize) ListIncrement(L);    ElemType *p,*q;    p=&L.elem[i-1];    for(q=&L.elem[L.length-1];q>=p;q--)        *(q+1)=*q;    *p=e;    L.length++;     //插入一个元素后L长度加1    return;}
void ListInsert_L(LinkList &L,LNode *q,LNode *s) //在q前插入新结点s{    LNode *p=L;    for(;p->next!=q&&p->next;p=p->next);    s->next=p->next;    p->next=s;    return;}

三、ListDelete(&L,i,&e):删除第i个元素,存入e中

void ListDelete_Sq(SqList &L,int i,ElemType &e)  //删除L的第i个元素,并用e返回其值{    if(i<1||i>L.length) ErrorMassage("i is invalid!");    ElemType *q;    e=L.elem[i-1];    for(q=&L.elem[i-1];q<=&L.elem[L.length-1];q++)        *q=*(q+1);    L.length--;     //删除一个元素后L长度减1    return;}
void ListDelete_L(LinkList &L,LNode *q,ElemType &e) //删除L中的q结点,并用e返回其内元素值{    LNode *p;    p=L;    for(;p->next!=q&&p->next;p=p->next);    p->next=p->next->next;    e=q->data;    delete q;    return;}

四、LocateElem(L,e):返回第1个与e相等元素的位序

int LocateElem_Sq(SqList L,ElemType e) //返回L中第1个与e相等的元素的位序,没有则返回0{    int i;    for(i=0;i<L.length;i++)        if(L.elem[i]==e) return i+1;    if(i==L.length) return 0;}
int LocateElem_L(LinkList L,ElemType e)         //返回L中第1个与e相等元素的位序,若不存在返回0{    LNode *p;    int i;    p=L->next;    for(i=1;p;i++,p=p->next)        if(p->data==e)            return i;    return 0;}

五、GetElem(L,i,&e):用e返回第i个元素的值

void GetElem_Sq(SqList L,int i,ElemType &e) //用e返回L中第i个元素的值{    if(i<1||i>L.length) ErrorMassage("i is invalid!");    e=L.elem[i-1];    return;}
void GetElem_L(LinkList L,int i,ElemType &e)    //用e返回L中第i个结点中元素的值{    if(i<1||i>ListLength_L(L))        ErrorMassage("i is invalid!");    LNode *p;    p=L->next;    for(int j=1;j!=i&&p;p=p->next,j++);    e=p->data;    return;}

六、DestroyList(&L):销毁线性表L

void DestroyList_Sq(SqList &L)      //销毁顺序表{    delete []L.elem;    L.length=0;     //顺序表销毁后长度为0,数组空间为0    L.listsize=0;    return;}
void DestroyList_L(LinkList &L)                 //销毁链表{    LNode *p,*q;    q=L->next;    while(q)    {        p=q->next;        delete q;        q=p;    }    delete L;    return;}

七、ListLength(L):返回L中元素个数

int ListLength_Sq(SqList L)         //返回顺序表L的当前长度{    return L.length;}
int ListLength_L(LinkList L)                    //返回L所指链表的长度{    LNode *q;    int l=0;    q=L->next;    while(q)    {        l++;        q=q->next;    }    return l;}

八、ListTraverse(L):依次输出L中每个元素

void ListTraverse_Sq(SqList L)      //依次输出L中的每个元素{    int i=0;    if(L.length<=0) return;    for(i=0;i<L.length-1;i++)        cout<<L.elem[i]<<"  ";    cout<<L.elem[i]<<endl;    return;}
void ListTraverse_L(LinkList L)                 //依次输出链表中的元素{    LNode *q;    q=L->next;    while(q)    {        cout<<q->data<<"  ";        q=q->next;    }    cout<<endl;    return;}

九、ClearList(&L):将L重置为空表

void ClearList_Sq(SqList &L)         //将L置为空表{    for(int i=0;i<L.length;i++)        L.elem[i]='\0';    L.length=0;     //置为空表后长度为0    return;}
void ClearList_L(LinkList &L)                   //将L置为空表,即只留下头结点{    DestroyList_L(L->next);    L->next=NULL;    return;}

十、LIstEmpty(L):若L为空表返回True,否则返回False

bool ListEmpty_Sq(SqList L)         //判断L是否为空表,若是返回true,否则返回false{    if(L.length==0) return true;    else return false;}
bool ListEmpty_L(LinkList L)                    //判断L是否为空表,除头结点以外{    int i;    LNode *p;    p=L->next;    for(i=0;p;p=p->next,i++);    if(i)        return false;    else        return true;}

十一、PriorElem(L,cur_e,&pre_e):用pre_e返回cur_e的前驱

ElemType PriorElem_Sq(SqList L,ElemType e)  //返回e的前驱元素,若e是第一个或者不是L中元素则输出提示信息{    int i=LocateElem_Sq(L,e);    if(i<=1) ErrorMassage("No priorelem!");    else return L.elem[i-2];}
LNode* PriorElem_L(LinkList L,ElemType cur_e) //返回cur_e的前驱结点,没有则输出提示信息{    LNode *p;    p=L->next;    if(LocateElem_L(L,cur_e)<=1)    //若cur_e不是L中元素或者e是L中第一个元素        ErrorMassage("No priornode!");    while(p->next->data!=cur_e)        p=p->next;    return p;}

十二、NextElem(L,cur_e,&next_e):返回后继

ElemType NextElem_Sq(SqList L,ElemType e)   //返回e的后继元素,若e是最后一个或者不是L中元素则输出提示信息{    int i=LocateElem_Sq(L,e);    if(i==0||i==L.length) ErrorMassage("No nextelem!");    else return L.elem[i];}
LNode* NextElem_L(LinkList L,ElemType cur_e)  //返回cur_e的后继结点,没有则输出提示信息{    LNode *p;    p=L->next;    int i=LocateElem_L(L,cur_e);    if(i<1||i>=ListLength_L(L))     //若cur_e不是L中元素或者是最后一个        ErrorMassage("No nextelem!");    for(;p->data!=cur_e;p=p->next);    return p->next;}
0 0