從新定義線性鏈表及其基本操作


  鏈表在空間的合理利用上和插入、刪除時不需要移動等優點,因此在很多場合下,它是線性表的首先儲存結構。然而它也存在着實現某些基本操作,如求線性表的長度時不如順序儲存結構的特點。因而從新定義線性鏈表及其基本操作

頭文件:

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define MYOVERFLOW -2
typedef int Status;
typedef int Elemtype;
typedef struct LNode{//結點類型
    Elemtype data;
    LNode *next;
}*Link,*Position;
typedef struct{//鏈表類型
    Link head, tail;//分別指向線性鏈表中的頭結點和最后一個結點
    int len;//指示線性鏈表中數據元素的個數
}LinkList;
Status compare(Elemtype s1, Elemtype s2);//比較兩者的大小,相等返回TRUE,否則返回FALSE
Status visit(LinkList L);//若存在,則遍歷L返回OK,否則返回ERROR
Status Create_List(LinkList &);//創造一個鏈表
Status MakeNode(Link &p, Elemtype e);
//分配由p指向的值為e的結點,並返回OK;若分配失敗,則返回ERROR
void FreeNode(Link &p);
//釋放p所指結點
Status InitList(LinkList &L);
//構造一個空的線性鏈表L
Status DestroyList(LinkList &L);
//銷毀線性鏈表L,L不再存在
Status ClearList(LinkList &L);
//將線性鏈表L重置為空表,並釋放原鏈表的結點空間
Status InsFirst(Link h, Link s);
//已知h指向線性鏈表的頭結點,將s所指結點插入在第一個結點之前
Status DelFirst(Link h, Link &q);
//已知h指向線性鏈表的頭結點,刪除鏈表中的第一個結點並以q返回
Status Append(LinkList &L, Link s);
//將指針s所指(彼此以指針相鏈)的一串結點鏈接在線性鏈表L的最后一個結點
//之后,並改變鏈表L的尾指針指向新的尾結點
Status Remove(LinkList &L, Link &q);
//刪除線性鏈表L中的尾結點並以q返回,改變鏈表L的尾指針指向新的尾結點
Status InsBefore(LinkList &L, Link &p, Link s);
//已知p指向線性鏈表L中的一個結點,將s所指結點插入在p所指結點之前,
//並修改指針p指向新插入的結點
Status InsAfter(LinkList &L, Link &p, Link s);
//已知p指向線性鏈表L中的一個結點,將s所指結點插入在p所指結點之后,
//並修改指針p指向新插入的結點
Status SetCurElem(Link &p, Elemtype e);
//已知p指向線性鏈表中的一個結點,用e更新p所指結點中數據元素的值
Elemtype GetCurElem(Link p);
//已知p指向線性鏈表中的一個結點,返回p所指結點中數據元素的值
Status ListEmpty(LinkList L);
//若線性鏈表L為空表,則返回TRUE,否則返回FALSE
int ListLength(LinkList L);
//返回線性鏈表L中元素個數
Position GetHead(LinkList L);
//返回線性鏈表L中頭結點的位置
Position GetLast(LinkList L);
//返回線性鏈表L中最后一個結點的位置
Position PriorPos(LinkList L, Link p);
//已知p指向線性鏈表L中的一個結點,返回p所指結點的直接前驅的位置,
//若無前驅,則返回NULL
Position NextPos(LinkList L, Link p);
//已知p指向線性鏈表L中的一個結點,返回p所指結點的直接后繼的位置,
//若無后繼,則返回NULL
Status LocatePos(LinkList L,int i, Link &p);
//返回p指示線性鏈表L中第i個結點的位置並返回OK,i值不合法時返回ERROR
Position LocateElem(LinkList L, Elemtype e, Status(*P)(Elemtype, Elemtype));
//返回線性鏈表L中第一個與e滿足函數p()判定關系的元素的位置,
//若不存在這樣的元素,則返回NULL
Status ListTraverse(LinkList L, Status(*visit)(LinkList));
//依次對L的每個元素調用函數visit()。一旦visit()失敗,則操作失敗

上述操作的實現:

Status MakeNode(Link &p, Elemtype e)
//分配由p指向的值為e的結點,並返回OK;若分配失敗,則返回ERROR
{
    p = new LNode;//為*p分配空間
    if (p){
        p->data = e;
        return OK;
    }
    else
        return ERROR;
}
void FreeNode(Link &p)
//釋放p所指結點
{
    delete p;//刪除*p所占用的空間
}
Status InitList(LinkList &L)
//構造一個空的線性鏈表L
{
    Link p = new LNode;
    if (p){
        L.head = p;//新建一個結點,並且頭指針和尾指針都指向該結點,長度為0
        L.tail = L.head;
        L.len = 0;
        return OK;
    }
    else
        return ERROR;
    
}
Status Create_List(LinkList &L)//創造一個鏈表
{
    if (InitList(L)){//初始化鏈表
        cout << "please input the length of the linklist:" << endl;
        int len;
        cin >> len;
        L.len = len;
        cout << "please input the data of the linklist:" << endl;
        for (int i = 1; i <= len; i++){
            Link temp = new LNode;//創建結點
            cin >> temp->data;//輸入結點的數據元素
            L.tail->next = temp;//將結點插入到表的末尾
            L.tail = L.tail->next;
            }
        L.tail->next = NULL;
        return OK;
    }
    else return ERROR;
}
Status visit(LinkList L)//若存在,則遍歷L返回OK,否則返回ERROR
{
    if (L.head){
        cout << "the data of the list is:" << endl;
        L.head = L.head->next;
        for (; L.head != L.tail;){
            cout << L.head->data << " ";
            L.head = L.head->next;
        }
        cout << L.tail->data << endl;//最后輸出尾結點的數據元素
        return OK;
    }
    else return ERROR;
}
Status ListTraverse(LinkList L, Status(*visit)(LinkList))
//依次對L的每個元素調用函數visit()。一旦visit()失敗,則操作失敗
{
    if (visit(L)){
        
        return OK;}
    else
    {
        return ERROR;
    }
}
Status DestroyList(LinkList &L)
//銷毀線性鏈表L,L不再存在
{
    
    for (; L.head != L.tail; L.len--){//釋放鏈表中結點所占的內存空間
        Link pt;
        pt = L.head;
        L.head = L.head->next;
        delete pt;

    }
    delete L.head;
    if (L.len == 0){//使L的頭指針和尾指針不指向任何地方
        L.head = NULL;
        L.tail = NULL;
        LinkList *p = &L;
        delete p;
        return OK;
    }
    else
    {
        return ERROR;
    }
}
Status ClearList(LinkList &L)
//將線性鏈表L重置為空表,並釋放原鏈表的結點空間
{
    Link temp = L.head;
    L.head = L.head->next;
    for (; L.len>0; L.len--){//釋放鏈表中的結點所占的內存空間
        Link pt;
        pt = L.head;
        L.head = L.head->next;
        delete pt;
    }
    L.head = temp;
    if (L.len == 0&&L.head==L.tail){
        return OK;
    }
    else
    {
        return ERROR;
    }
}
Status InsFirst(Link h, Link s)
//已知h指向線性鏈表的頭結點,將s所指結點插入在第一個結點之前
{
    if (h){//判斷頭結點是否存在
        s->next = h->next;//將s結點插入到表中
        h->next = s;
        return OK;
    }
    else return ERROR;
}
Status DelFirst(Link h, Link &q)
//已知h指向線性鏈表的頭結點,刪除鏈表中的第一個結點並以q返回
{
    if (h->next){//判斷第一個結點是否存在
        q = h->next;//給q賦予第一個結點的值
        h->next = h->next->next;//將第一個結點從鏈表中刪除
        q->next = NULL;
        return OK;
    }
    else return ERROR;
}
Status Append(LinkList &L, Link s)
//將指針s所指(彼此以指針相鏈)的一串結點鏈接在線性鏈表L的最后一個結點
//之后,並改變鏈表L的尾指針指向新的尾結點
{
    if (s){
        Link temp = s;
        for (; s->next; s = s->next)
        {
            L.len++;
        }//讓S移動到鏈表的最后一個結點
        L.len++;
        L.tail->next = temp;
        L.tail = s;//使L.tail指向最后一個結點
        return OK;
    }
    else return ERROR;
}
Status Remove(LinkList &L, Link &q)
//刪除線性鏈表L中的尾結點並以q返回,改變鏈表L的尾指針指向新的尾結點
{
    if (L.head != L.tail){
        q = L.tail;//用q返回尾結點
        Link temp;
        temp = L.head;
        for (; temp->next != L.tail; temp = temp->next){}//使temp指向尾結點的前一個結點
        L.tail = temp;//使尾結點指向新的尾結點
        L.tail->next = NULL;
        delete temp->next;//刪除舊的尾結點
        L.len--;
        return OK;
    }
    else return ERROR;
}
Status InsBefore(LinkList &L, Link &p, Link s)
//已知p指向線性鏈表L中的一個結點,將s所指結點插入在p所指結點之前,
//並修改指針p指向新插入的結點
{
    Link temp=L.head;
    for (; temp->next != p&&temp; temp = temp->next){}
    if (temp->next == p){
        s->next = p;
        temp->next = s;
        p = s;
        L.len++;
        return OK;
    }
    else return ERROR;
}
Status InsAfter(LinkList &L, Link &p, Link s)
//已知p指向線性鏈表L中的一個結點,將s所指結點插入在p所指結點之后,
//並修改指針p指向新插入的結點
{
    Link temp = L.head;
    for (; temp != p&&temp; temp = temp->next){}
    if (temp == p){
        temp->next=s;
        s->next = p;
        p = s;
        if (temp == L.tail)
            L.tail = s;
        L.len++;
        return OK;
    }
    else return ERROR;
}
Status SetCurElem(Link &p, Elemtype e)
//已知p指向線性鏈表中的一個結點,用e更新p所指結點中數據元素的值
{
    if (p){
        p->data = e;
        return OK;
    }
    else return ERROR;
}
Elemtype GetCurElem(Link p)
//已知p指向線性鏈表中的一個結點,返回p所指結點中數據元素的值
{
    if (p){
        return p->data;
    }
    else return NULL;
}
Status ListEmpty(LinkList L)
//若線性鏈表L為空表,則返回TRUE,否則返回FALSE
{
    if (L.len == 0){
        return TRUE;
    }
    else return FALSE;
}
int ListLength(LinkList L)
//返回線性鏈表L中元素個數
{
    return L.len;
}
Position GetHead(LinkList L)
//返回線性鏈表L中頭結點的位置
{
    return L.head;
}
Position GetLast(LinkList L)
//返回線性鏈表L中最后一個結點的位置
{
    return L.tail;
}
Position PriorPos(LinkList L, Link p)
//已知p指向線性鏈表L中的一個結點,返回p所指結點的直接前驅的位置,
//若無前驅,則返回NULL
{
    Link temp = L.head;
    for (; temp->next != p&&temp; temp = temp->next){}
    if (temp->next == p){
        return temp;
    }
    else return NULL;
}
Position NextPos(LinkList L, Link p)
//已知p指向線性鏈表L中的一個結點,返回p所指結點的直接后繼的位置,
//若無后繼,則返回NULL
{
    Link temp = L.head->next;
    for (; temp != p->next&&temp; temp = temp->next){}
    if (temp == p->next){
        return temp;
    }
    else return NULL;
}
Status LocatePos(LinkList L, int i, Link &p)
//返回p指示線性鏈表L中第i個結點的位置並返回OK,i值不合法時返回ERROR
{
    for (int j = 1; L.head&&j <= i; j++, L.head = L.head->next){}
    if (L.head){
        p = L.head;
        return OK;
    }
    else return ERROR;
}
Status compare(Elemtype s1, Elemtype s2){
    if (s1 == s2)return OK;
    else return ERROR;
}
Position LocateElem(LinkList L, Elemtype e, Status(*P)(Elemtype s1, Elemtype s2))
//返回線性鏈表L中第一個與e滿足函數p()判定關系的元素的位置,
//若不存在這樣的元素,則返回NULL
{
    for (; !P(L.head->next->data, e) && L.head->next; L.head = L.head->next){}
    if (!L.head->next){
        return L.head->next;
    }
    else return NULL;
}

用這些基本操作實現插入操作和將兩個非遞減排列合並成一個新的非遞減序列
頭文件:

Status ListInsert_L(LinkList &L, int i, Elemtype e);
//在帶頭結點的單鏈線性表L的第i個元素之前插入元素e
Status MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc, int(*compare)(Elemtype, Elemtype));
//已知單鏈線性表La和Lb的元素按值非遞減排列。
//歸並La和Lb得到新的單鏈線性表Lc,Lc的元素也按值非遞減排列
int compare1(Elemtype a, Elemtype b);//返回a-b的值

操作的實現:

Status ListInsert_L(LinkList &L, int i, Elemtype e)
//在帶頭結點的單鏈線性表L的第i個元素之前插入元素e
{ 
    Link h,s;    
    if (!MakeNode(s, e))return ERROR;
    if (i = L.len + 1){
        s->next = L.tail->next;
        L.tail->next = s;
        L.tail = L.tail->next;
    }
    else {
        if (!LocatePos(L, i - 1, h))return ERROR;
        InsFirst(h, s);    
    }
    L.len++;
    return OK;
}
int compare1(Elemtype a, Elemtype b){
    return a - b;
}
Status MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc, int(*compare)(Elemtype, Elemtype))
//已知單鏈線性表La和Lb的元素按值非遞減排列。
//歸並La和Lb得到新的單鏈線性表Lc,Lc的元素也按值非遞減排列
{
    if (!InitList(Lc))return ERROR;
    Link ha; Link hb;
    ha = GetHead(La); hb = GetHead(Lb);
    Link pa; Link pb;
    pa = NextPos(La, ha);
    pb = NextPos(Lb, hb);
    int lenLc = La.len + Lb.len;
    while (pa&&pb){
        Link q;
        Elemtype a, b;
        a = GetCurElem(pa); b = GetCurElem(pb); 
        if (compare(a, b)<=0){
            DelFirst(ha, q);
            Append(Lc, q);
            pa = NextPos(La, ha);    
        }
        else{
            DelFirst(hb, q);
            Append(Lc, q);
            pb = NextPos(Lb, hb);
        }
    }   
        if (pa)Append(Lc, pa);
        else Append(Lc, pb); 
        FreeNode(ha); FreeNode(hb);
        Lc.len = lenLc;

    return OK;
}

主函數:

int _tmain(int argc, _TCHAR* argv[])
{
    LinkList l1,l2,l3;
    Create_List(l1);
    Create_List(l2);
    MergeList_L(l1, l2, l3,compare1);
    ListTraverse(l3, visit);
    return 0;

}

最終得到的結果如下圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM