1. 程式人生 > >線性表基本操作

線性表基本操作

線性表是最簡單、也是最基本的一種線性資料結構。它有兩種儲存方法:順序表和連結串列,它一般有12種基本操作,主要基本操作是插入、刪除和查詢等。我這裡把順序表和單鏈表的這12種操作按自己的理解寫了一遍,兩兩對照著看應該要好一點。

線性表12基本操作

準備(接下來也是這樣比較,不做說明了)

順序表(Sq —— SequenceList):

#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10

typedef 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;
}