单链表实现

来源:互联网 发布:养生网站源码带手机站 编辑:程序博客网 时间:2024/06/08 15:01

目录

线性表是数据结构的第一章,而考研和找工作都喜欢考察这方面的内容,因此,我就用C++实现了单链表,以及一些常见的算法题。

本文的具体内容包括:

  1. 单链表的基本操作
  2. 反向输出单链表
  3. 找到两个单链表的第一个公共结点
  4. 对单链表进行排序
  5. 将两个有序的链表合在一起,使之仍然有序

单链表的基本操作

不多说,直接上代码(注意基本操作中参数L的不同):

///初始化一个单链表,申请头结点void InitList(LinkList *L){    *L = new LNode;    if(*L==NULL){        cout<<"new error"<<endl;        return;    }    (*L)->next = NULL;}///释放头结点,将其设为nullvoid DestroyList(LinkList *L){    LinkList t ;    while((*L)!=NULL){        t = (*L)->next;        delete (*L);        (*L) = t;    }}///释放除头结点以外的所有空间void ClearList(LinkList L){    LinkList t,q=L;    L = L->next;    while(L!=NULL){        t = L->next;        delete L;        L = t;    }    q->next = NULL;}///获取链表的长度int Length(LinkList L){    if(L == NULL)        return -1;     int cnt = 0;     L = L->next;     while(L!=NULL){        ++cnt;        L=L->next;     }     return cnt;}///返回链表L中第1个与e相等的元素的位置int locateElem(LinkList L,int e){    if(L==NULL)        return -1;    int index = 0;    L = L->next;    while(L!=NULL){        if(L->data==e){            return index;        }        ++index;        L = L->next;    }    return -1;}///获取链表第i个元素的值bool getElem(LinkList L,int i,LNode &e){    if(L==NULL or i<0)        return false;    int j = 0;    L = L->next;    while(L!=NULL){        if(j==i){            e.data=L->data;            e.next=L->next;            return true;        }        ++j;        L = L->next;    }    return false;}///在L中第i个位置插入结点ebool ListInsert(LinkList L,int i,LNode e){    if(L==NULL)        return false;    LinkList p;    p = L;    L = L->next;    int j = 0;    while(p!=NULL){        if(j==i){            LinkList t;            t = new LNode;            t->data = e.data;            t->next = e.next;            p->next = t;            t->next = L;            return true;        }        p = L;        L = L->next;        ++j;    }    return false;}///删除第i个元素,并返回该结点bool ListDelete(LinkList L,int i,LNode &e){    if(L==NULL)        return false;    LinkList p;    int j = 0;    p = L;    L = L->next;    while(L!=NULL){        if(i==j){            e.data = L->data;            e.next = L->next;            p->next = L->next;            delete L;            return true;        }        p = p->next;        L = L->next;        ++j;    }    return false;}///打印单链表Lvoid PrintList(LinkList L){    if(L==NULL)        return;    L = L->next;    while(L!=NULL){        cout<<L->data<<' ';        L = L->next;    }    cout<<" end"<<endl;}

测试代码:

LinkList L;    InitList(&L);    cout<<"the address of the head node is "<<L<<endl;    LNode e;    e.data = 124;    e.next = NULL;    ListInsert(L,0,e);    e.data = 132;    ListInsert(L,0,e);    e.data = 123;    ListInsert(L,0,e);    PrintList(L);    cout<<"the length of L is "<<Length(L)<<endl;    cout<<"the location of 132 is "<<locateElem(L,132)<<endl;    if(getElem(L,1,e)){        cout<<"the value of location 1 is "<<e.data<<endl;    }    if(ListDelete(L,1,e))        cout<<"the value of deleted element is "<<e.data<<endl;    else        cout<<"delete failed"<<endl;    ClearList(L);    cout<<L<<endl;    DestroyList(&L);    cout<<L<<endl;

运行结果:
这里写图片描述

反向输出单链表

///从尾到头反向输出单链表L///思路:反向输出很容易就想到栈,///然后递归的本质就是栈,因此可以用///递归来实现,先一层层递归到链表尾部,///当指针为NULL时,返回,返回时输出当前节点的值void PrintListByReverse(LinkList L){    if(L==NULL)        return;    PrintListByReverse(L->next);    cout<<L->data<<' ';}

测试代码:

LinkList L;    InitList(&L);    LNode e;    e.data = 124;    e.next = NULL;    ListInsert(L,0,e);    e.data = 132;    ListInsert(L,0,e);    e.data = 123;    ListInsert(L,0,e);    e.data = 88;    ListInsert(L,0,e);    e.data = 14;    ListInsert(L,0,e);    e.data = 26;    ListInsert(L,0,e);    cout<<"the origin linklist is:"<<endl;    PrintList(L);    cout<<"print list in reverse:"<<endl;    PrintListByReverse(L->next);    cout<<"end"<<endl;

运行结果:
这里写图片描述

求两个单链表的公共结点

///找到两个链表的第一个公共结点/**< 思路:若两个单链表有公共结点,那么他们的逻辑结构肯定是Y形而不是X形(因为节点的next域只有一个),因此,可以先计算两个链表的长度,然后先让较长的先移动d(他们的长度差)个节点这样他们就会同时到达公共结点,只需比较两个指针就可以了 */bool FindCommonNode(LinkList La,LinkList Lb,LNode &e){    if(La==NULL || Lb==NULL)        return false;    int la,lb;///La/Lb 的长度    la = Length(La);    lb = Length(Lb);    int d = la-lb;    int i = 0;    La = La->next;    Lb = Lb->next;    if(d>0){        while(La!=NULL){            if(i==d){                break;            }            ++i;            La = La->next;        }    }    else{        d=-d;        while(Lb!=NULL){            if(i==d){                break;            }            ++i;            Lb = Lb->next;        }    }    while(La!=NULL && Lb!=NULL){        if(La == Lb){            e.data = La->data;            e.next = La->next;            return true;        }        La = La->next;        Lb = Lb->next;    }    return false;}

测试代码:

LinkList L;    InitList(&L);    LNode e;    e.data = 124;    e.next = NULL;    ListInsert(L,0,e);    e.data = 132;    ListInsert(L,0,e);    LinkList myList;    InitList(&myList);    e.data = 83;    ListInsert(myList,0,e);    e.data = 19;    ListInsert(myList,0,e);    e.data = 46;    ListInsert(myList,0,e);    ConcatList(myList,L);    cout<<"list 1 is:"<<endl;    PrintList(myList);    LinkList hisList;    InitList(&hisList);    e.data = 547;    ListInsert(hisList,0,e);    e.data = 78;    ListInsert(hisList,0,e);    ConcatList(hisList,L);    cout<<"list 2 is:"<<endl;    PrintList(hisList);    if(FindCommonNode(myList,hisList,e))        cout<<"the first common node is "<<e.data<<endl;

运行结果:
这里写图片描述

单链表排序

///对单链表进行排序/**< 可使用插入排序,每次从后面选择一个结点,在前面有序的序列选择一个合适的位置插入 */void SortList(LinkList L){    if(L==NULL)        return;    LinkList q,r,s,x;    r = L;    x = L;    L=L->next;    bool flag;    while(L!=NULL){        ///在前面找到合适的位置插入        s = r;        q = r->next;        flag = false;        while(q!=NULL && q!=L){            ///找到第一个比当前结点大的结点            if(q->data > L->data){                flag = true;                x->next = L->next;                L->next = q;                s->next = L;                //PrintList(r);                break;            }            s = s->next;            q = q->next;        }        if(flag!= true)            x=x->next;        L=x->next;    }}

测试代码:

LinkList L;    InitList(&L);    LNode e;    e.data = 124;    e.next = NULL;    ListInsert(L,0,e);    e.data = 132;    ListInsert(L,0,e);    LinkList myList;    InitList(&myList);    e.data = 83;    ListInsert(myList,0,e);    e.data = 19;    ListInsert(myList,0,e);    e.data = 46;    ListInsert(myList,0,e);    ConcatList(myList,L);    cout<<"before sort:"<<endl;    PrintList(myList);    SortList(myList);    cout<<"after sort:"<<endl;    PrintList(myList);

运行结果:
这里写图片描述

合并有序单链表

///合并有序单链表La、Lb,放到La里面去,并且合并后的链表仍然有序void MergeList(LinkList La,LinkList Lb){    LinkList pa = La->next,pb = Lb->next,t;    LNode *r;    La->next  = NULL; ///La 作为结果链表的指针    t = La;    while(pa != NULL && pb != NULL){        if(pa->data > pb->data){            r = pb->next; ///r 暂存pb的后继结点            ///在La插入            pb->next = La->next;            La->next = pb;            ///恢复pb为下一个待比较结点            pb = r;            La = La->next;        }        else{            r = pa->next; ///r 暂存pb的后继结点            ///在La插入            pa->next = La->next;            La->next = pa;            ///恢复pb为下一个待比较结点            pa = r;            La = La->next;        }        //PrintList(t);    }    if(pa!=NULL)        La->next = pa;    if(pb!=NULL)        La->next = pb;    delete Lb;}

测试代码:

 LNode e;    LinkList List1;    InitList(&List1);    e.data = 24;    ListInsert(List1,0,e);    e.data = 68;    ListInsert(List1,0,e);    e.data = 35;    ListInsert(List1,0,e);    e.data = 123;    ListInsert(List1,0,e);    e.data = 77;    ListInsert(List1,0,e);    e.data = 15;    ListInsert(List1,0,e);    SortList(List1);    LinkList List2;    InitList(&List2);    e.data = 23;    ListInsert(List2,0,e);    e.data = 46;    ListInsert(List2,0,e);    e.data = 98;    ListInsert(List2,0,e);    e.data = 143;    ListInsert(List2,0,e);    e.data = 18;    ListInsert(List2,0,e);    e.data = 85;    ListInsert(List2,0,e);    SortList(List2);    cout<<"list 1 is :"<<endl;    PrintList(List1);    cout<<"list 2 is :"<<endl;    PrintList(List2);    MergeList(List1,List2);    cout<<"after merge:"<<endl;    PrintList(List1);

运行结果:
这里写图片描述

总结

虽然说单链表逻辑比较简单,但是涉及指针操作,很容易出错,我建议在纸上画图来编写代码,这样思路比较清晰。

原创粉丝点击