单链表构成及其示例

在日常中出现需要存储一串数据的情况时,我们的第一反应就是想到运用数组。

 

单链表的背景及与数组的优劣势对比。

数组有其独特的优势,数组声明后便在内存中随机分配一片连续的,大小为Arry_length*sizeof (elem_type)的内存空间。单位数据占用空间小,在查找过程中,查找规则简单方便,效率高。其劣势也比较明显,若内存内没有满足条件的连续的内存空间,则无法分配内存。而计算机中的数据都是零散排放的,在出现大批量的数据的时候很难找到与其相对应的连续的内存空间,并且在做一些插入、删除等操作时需要耗费的时间复杂度略高。

我们引用链表的形式来解决这个问题。我们将数组中的元素包装成结构体,并且在结构体内添加一个指针元素,这样一个链表的节点就定义完成。

在创建链表的过程中预留一个头节点作为标志,该标志可以用于快速查看链表的其他信息,以此来减少工作量。链表中的各个节点均靠结构体中的next指针来引路,依次指向下一个节点。做一个形象的比喻,一条链表就可以比作一列绿皮火车,火车中每个车厢都是一个节点,火车头就是链表的头指针,可以存放火车中的车箱数,人数等信息。每一个车厢间的联系,均需要靠车厢中的next指针链接在一起。

链表的优势相当明显,即链表不需要像数组一样大片连续的空间,而只需要一个节点大小的空间,并且对于插入、删除等操作有极强的便利性。

总结数组与链表的优劣势:

数组:

优势:简单易学,占用空间小,数组内访问查找效率高,适合随机查找。

劣势:

空间上:空间大小固定,申请数组空间要求苛刻,不适合动态存储。

时间上:对插入删除等操作时间复杂度略高,不适合动态添加。

链表:

优势:插入删除操作效率高、内存利用率高、可拓展性强。

缺点:占用空间较大,只能通过指针顺序查找,查找效率低。

 

单链表的构成:

我们将数组内的数据同指针一起封装在一个结构体中,每个结构体就是一个链表的节点。单链表是以指针作为连接,各个节点都由next指针指向下一个节点的地址,将各个节点相互连接起来形成一个单向链表。

 

 

 

程序示例:

结构体:

structLnode {

    element_type elem;

    struct node *next;

}Lnode;

 

示例:

#include<bits/stdc++.h>

#defineelement_type int

usingnamespace std;

typedefstruct Lnode {

    element_type val;

    struct Lnode *next;

}Lnode,*LinkList;

 

intcreat_head(LinkList &L){

    L = (LinkList) malloc (sizeof (Lnode));

    if (!L) return 0;

    L->next = NULL;

    cout<<"creatsuccess!"<<endl;

}

 

voidcreat_node (LinkList &L){

    LinkList pt,q;

    pt = L;

    cout<<"inputn"<<endl;

    int n;cin>>n;

    while(n--){

        q = (LinkList) malloc (sizeof (Lnode));

        if (!q) {cout<<"mallocfail"<<endl;continue;}

        cout<<"cinval"<<endl;

        cin>>q->val;

        pt->next = q;

        pt = pt->next;

        pt->next = NULL;

    }

}

 

voidshow_List(LinkList &L){

    LinkList pt = L->next;

    while (pt != NULL){

        cout<<pt->val<<"  "<<endl;

        pt = pt->next;

    }

}

 

intmain(){

    LinkList L;

    while (1){

    int ch=0;cin>>ch;

    if (ch==1) creat_head(L);

    else if (ch==2) creat_node(L);

    else show_List(L);

    }

}

 

 

拓展:对于存储一串连续的数据时,不止可以使用单链表。单链表之外还有循环单链表、双向链表、循环双向链表等等。对于没有指针这一工具之前的程序员们,他们是无法直接使用链表这一存储结构的,但链表的思想已经存在。他们运用定长数组在模拟链表的工作。这就是数组模拟链表。

循环单链表:

循环链表是在单链表的基础上做出一些修改。链表第一个元素作为表头,不存储任何信息,表头下一个元素即L->next作为head,将最尾部的元素的指针指向head,从而形成一个循环。这种做法的好处是可以实现任意位置作为遍历的起始位置。

示例:

#include<bits/stdc++.h>

usingnamespace std;

typedefstruct node {

    int val;

    struct node *next;

}node,*LinkList;

 

 

voidCreateList(LinkList &L){

    L = (LinkList )malloc (sizeof (node));

    if (!L) cout<<"malloc fail!"<<endl;

 

    LinkList pnew,ptail,phead;

    cout<<"cin n:";

    int n;cin>>n;

    for (int i=1;i<=n;i++){

        int v;cin>>v;

        pnew = (LinkList )malloc (sizeof(node));

        pnew->val = v;

 

        if(i==1){

            L->next = pnew;

            phead = pnew;

            ptail = phead;

        }

        else {

            pnew->next = phead;

            ptail->next = pnew;

            ptail = pnew;

        }

 

    }

}

 

voidShow(LinkList &L){

    LinkList phead,pt;

    //phead = L->next;

    //pt = phead->next;

    pt = L->next;

    int cnt=10;

    while (cnt--){

        cout<<pt->val<<endl;

        pt = pt->next;

    }

}

 

 

intmain()

{

    LinkList L;

    CreateList(L);

    Show(L);

}

 

双向链表:

双向链表是在单链表的基础上添加一个prior指针,该指针总是指向当前元素的前一个元素的地址。牺牲这一部分空间所获得的好处是,双向链表可以实现前后的查询。

示例:

#include<bits/stdc++.h>

usingnamespace std;

typedefstruct node{

    int val;

    struct node *next ;

    struct node *prior;

}node,*LinkList;

 

voidCreateList (LinkList &L){

    L = (LinkList)malloc (sizeof (node));

    if (!L) cout<<"malloc fail!"<<endl;

 

    cout<<"cin n:";

    int n;cin>>n;

    LinkList rear,pnew;

    rear = L;

    int v;

    for (int i=1;i<=n;i++){

        cin>>v;

        pnew = (LinkList)malloc (sizeof(node));

        if (!pnew) continue;

        pnew->val = v;

        rear->next = pnew;

        pnew->prior = rear;

        rear = pnew;

        rear->next = NULL;

    }

}

 

voidShow1 (LinkList &L){

    LinkList pt;

    pt = L->next;

    while (pt){

        cout<<pt->val<<endl;

        pt = pt->next;

    }

    cout<<endl;

}

 

voidShow2(LinkList &L){

    LinkList pt;

    pt = L->next;

    while (pt->next){

        pt = pt->next;

    }

    while (pt!=L){

        cout<<pt->val<<endl;

        pt = pt->prior;

    }

}

 

intmain()

{

    LinkList L;

    CreateList(L);

    Show1(L);

    Show2(L);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值