链表是 数据结构中很重要的基础 部分,下面 我通过简单的故事来将链表的内容串起来解释一下,同时也是总结一下自己的学习内容:
故事:
某一天,乐乐,丰丰,呆子,星星,领领,小韦6位小朋友带领着8个小朋友一起去山上玩耍。当玩耍过后,天下起了大雨 !!于是 14位小朋友赶紧返回,不幸的是山口处山洪暴发。如果想要 过去,14位 小朋友需要连在一起,单个过河的小朋友会被山洪冲走(因为经过试验证明了这一点,而且小韦在试验过程中被洪水冲走了) 。
我们将每位小朋友看做是一个节点。
- typedef struct Lnode
- {
- int data;
- struct Lnode *next;
- };
建立单链表:
那么要从洪水中过去的话,14位小朋友需要建立一个长队。可以想到,建立长队的方法有两种:
首先我们需要空出来一块场地用来建立我们的长队(所说的建立 一个空链表)
code:
- void InitList(LinkList*&L)
- {
- L = (LinkList *)malloc(sizeof(LinkList));
- L->next = NULL;
- }
第一种:乐乐站在第一个,星星站在乐乐 的前面,呆子站在星星的前面……依次排列,这样乐乐会最终站在队尾(这就是头插法建立单链表)。
1. 2 .3.……丰丰,呆子,星星,乐乐。
code:
- void CreateListH(LinkList *&L, int a[], int n)
- {
- LinkList *s;
- int i;
- L = (LinkList *)malloc(sizeof(LinkList));
- L->next = NULL;
- for (i = 0; i < n; i++)
- {
- s->data = a[i];
- s->next = L->next;
- L->next = s;
- }
- }
第二种:乐乐站在第一个,星星 站在乐乐的后面,呆子站在星星的后面,丰丰站在呆子的后面,……其他人依次后排(这就是尾插法建立单链表)。
乐乐,星星,呆子,丰丰……。
Code:
- void CreateListR(LinkList *&L, int a[], int n)
- {
- int i;
- LinkList *s, *r;
- L = (LinkList *)malloc(sizeof(LinkList));
- r = L;
- for (i = 0; i < n; i++)
- {
- s->data = a[i];
- r->next = s;
- r = s;
- }
- r->next = L->next;
- }
那么现在队伍建立完成了,可以过河了,小朋友们都很高兴(其实 一点都不高兴)。
这个时候小韦竟然回来了,小朋友们都很高兴他还 或活着,选举他当了队长 。由于小韦刚回来 ,对队伍的情况 不是 很了解,他想要知道队伍有多少人,于是他从队伍的头到尾进行了查数:
(单链表中数据 节点 的个数)
code:
- int ListLength(LinkList *L)
- {
- int ans = 0;
- LinkList *p = L;
- while (p->next != NULL)
- {
- ans++;
- p = p->next;
- }
- return ans;
- }
但是 悲剧的是,小韦由于智商有限,只能数到10,就不会数了。于是他想了一个方法,让队伍中的小朋友从头到尾 说出自己的名字、信息:
(输出节点存储的信息):
code:
- void CoutList(LinkList *L)
- {
- LinkList *p = L->next;
- while (p != NULL)
- {
- printf("%d", p->data);
- p = p->next;
- }
- }
由于小韦只能数到10,造成队伍中的星星的嘲笑,并给他 起了个外号:小白。站在队伍头部的小韦很是气愤,气愤中的小韦突然就知道怎么数10以后的数字了。于是他查了一下嘲笑他的小朋友的位置,给他起外号报复:
修改某个节点的数据信息 :
code:
- bool ChangeInfo(LinkList *&L, int i, int &e)
- {
- int j = 0;
- LinkList *p = L;
- while (j < i && p != NULL)
- {
- j++;
- p = p->next;
- }
- if (p == NULL)
- return false;
- else
- {
- p->data = e;
- return true;
- }
- }
由于小韦的行为,使得某个位置上的乐乐表现的很气愤。于是小韦查了乐乐的位置,并行使了队长权利将其踢出了队伍(因为 小韦知道乐乐未来会是一位IT大神,要让乐乐挂掉先)。
删除某个节点:
- bool ListDelete(LinkList *&L, int i)
- {
- int j = 0;
- LinkList *p = L, *q;
- while (j < i - 1 && p != NULL)
- {
- j++;
- p = p->next;
- }
- if (p == NULL)
- return false;
- else
- {
- q = p->next;
- if (q == NULL)
- {
- return false;
- }
- p->next = q->next;
- free(q);
- return true;
- }
- }
杂七杂八的事情终于弄完了,于是 小韦也归队。(因为他 不想再单独被冲走了)
插入数据元素:
code:
- bool ListInsert(LinkList *&L, int i, int e)
- {
- int j = 0;
- LinkList *p = L, *s;
- while (j < i - 1 && p != NULL)
- {
- j++;
- p = p->next;
- }
- if (p == NULL)
- return false;
- else
- {
- s = (LinkList *)malloc(sizeof(LinkList));
- s->data = e;
- s->next = p->next;
- p->next = s;
- return true;
- }
- }
那么 现在开始过河了,由于河水 突然猛涨,小韦学长竟然又被冲走了。小伙伴们需要抓的更紧点,于是它们退回来重新 建队。并将抓衣服的方式 更改了一下:让前一个小朋友的手抓住后一个小朋友的衣服,后一个小朋友的手抓住他前面的小朋友的衣服。即(双链表)
相应的此时建双链表的方法也有两种,与建立单链表过程相似,只需要加一个前驱结点即可:
code:
- typedef struct Lnode
- {
- int data;
- struct Lnode *prior;
- struct Lnode *next;
- }LinkList;
第一种建立方式头插法(与单链表头插法相似):
code:
- void CreateList_F(LinkList *&L, int a[], int n)
- {
- LinkList *s;
- int i;
- L = (LinkList*)malloc(sizeof(LinkList));
- L->prior = L->next = NULL;
- for (i = 0; i < n; i++)
- {
- s = (LinkList *)malloc(sizeof(LinkList));
- s->data = a[i];
- s->next = L->next;
- if (L->next != NULL)
- {
- L->next->prior = s;
- }
- L->next = s;
- s->prior = L;
- }
- }
尾插法建立 双链表:
code:
- void CreatList_R(LinkList *&L, int a[], int n)
- {
- int i;
- LinkList *s, *r;
- r = L;
- for (i = 0; i < n; i++)
- {
- s = (LinkList*)malloc(sizeof(LinkList));
- s->data = a[i];
- r->next = s;
- s->prior = r;
- }
- r->next = L->next;
- }
经过好多坎坷,终于到达的河的对岸,于是小伙伴们 手拉手围成一个圈,兴高采烈的哭了起来。
循环链表:
循环链表 只是将链表 的尾部节点的 next指向了链表 的开头L;
下面我总结下代码:
单链表:
- typedef struct Lnode
- {
- int data;
- struct Lnode *next;
- }LinkList;
-
-
- void InitList(LinkList *&L)
- {
- L = (LinkList *)malloc(sizeof(LinkList));
- L->next = NULL;
- }
-
-
- void CreateListH(LinkList *&L, int a[], int n)
- {
- LinkList *s;
- int i;
- L = (LinkList *)malloc(sizeof(LinkList)); L是 链表的头
- L->next = NULL;
- for (i = 0; i < n; i++)
- {
- s->data = a[i];
- s->next = L->next;
- L->next = s;
- }
- }
-
-
- void CreateListR(LinkList *&L, int a[], int n)
- {
- int i;
- LinkList *s, *r;
- L = (LinkList *)malloc(sizeof(LinkList));
- r = L;
- for (i = 0; i < n; i++)
- {
- s->data = a[i];
- r->next = s;
- r = s;
- }
- r->next = L->next;
- }
- </pre><pre code_snippet_id="1630697" snippet_file_name="blog_20160331_15_6131477" name="code" class="cpp">
- int ListLength(LinkList *L)
- {
- int ans = 0;
- LinkList *p = L;
- while (p->next != NULL)
- {
- ans++;
- p = p->next;
- }
- return ans;
- }
-
-
- void CoutList(LinkList *L)
- {
- LinkList *p = L->next;
- while (p != NULL)
- {
- printf("%d", p->data);
- p = p->next;
- }
- }
-
-
- bool GetElem(LinkList *&L, int i, int &e)
- {
- int j = 0;
- LinkList *p = L;
- while (j < i && p != NULL)
- {
- j++;
- p = p->next;
- }
- if (p == NULL)
- return false;
- else
- {
- p->data = e;
- return true;
- }
- }
-
- bool ListDelete(LinkList *&L, int i)
- {
- int j = 0;
- LinkList *p = L, *q;
- while (j < i - 1 && p != NULL)
- {
- j++;
- p = p->next;
- }
- if (p == NULL)
- return false;
- else
- {
- q = p->next;
- if (q == NULL)
- {
- return false;
- }
- p->next = q->next;
- free(q);
- return true;
- }
- }
-
- bool ListInsert(LinkList *&L, int i, int e)
- {
- int j = 0;
- LinkList *p = L, *s;
- while (j < i - 1 && p != NULL)
- {
- j++;
- p = p->next;
- }
- if (p == NULL)
- return false;
- else
- {
- s = (LinkList *)malloc(sizeof(LinkList));
- s->data = e;
- s->next = p->next;
- p->next = s;
- return true;
- }
- }
双链表:
- typedef struct Lnode
- {
- int data;
- struct Lnode *prior;
- struct Lnode *next;
- }LinkList;
-
-
-
-
- void CreateList_F(LinkList *&L, int a[], int n)
- {
- LinkList *s;
- int i;
- L = (LinkList*)malloc(sizeof(LinkList));
- L->prior = L->next = NULL;
- for (i = 0; i < n; i++)
- {
- s = (LinkList *)malloc(sizeof(LinkList));
- s->data = a[i];
- s->next = L->next;
- if (L->next != NULL)
- {
- L->next->prior = s;
- }
- L->next = s;
- s->prior = L;
- }
- }
-
-
-
-
- void CreatList_R(LinkList *&L, int a[], int n) 尾插法建立双链表
- {
- int i;
- LinkList *s, *r;
- r = L;
- for (i = 0; i < n; i++)
- {
- s = (LinkList*)malloc(sizeof(LinkList));
- s->data = a[i];
- r->next = s;
- s->prior = r;
- }
- r->next = L->next;
- }
循环链表 的就不写了,因为只需要 让尾节点和头结点关联上就行了,不过要注意双链表循环和单链表循环是有一定区别的。但是本质不变。
希望 这篇文章 可以 帮助你更好的理解或者复习链表操作 。
如有错,请留言。