系列文章目录
C语言加强篇——(1)学习笔记 之 变量、指针、关键字
C语言加强篇——(2)学习笔记 之 结构体、结构体指针、函数指针
C语言加强篇——(3)学习笔记 之 链表的增、删、改、查
文章目录
- 系列文章目录
- 一、链表
- 1、什么是链表
- 2、单链表
- (1)单链表的遍历
- (2)节点的插入
- (3)节点的删除
- (4)节点的修改
- (5)节点的查找
- 3、双链表
- 小结
一、链表
1、什么是链表
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列节点(链表中每一个元素称为节点)组成,节点可以在运行时动态生成。每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。
上面对链表的解释是百度百科上的解释,这看起来是不是比较难理解呢 ?接下来我带领大家来通过通俗易懂的例子来深入学习链表及链表的相关操作。
谍战片大家都看过吧,接下来将以谍战片里的某个身份来深入的学习链表;
以谍战片中的间谍来形象地表述链表。
2、单链表
间谍有自己下线间谍,每个间谍都知道怎么去找自己的下线间谍;而下线间谍不知道怎么去找他的上线间谍;他们单线联系;单线联系的间谍有个领导;
其中,领导就是头节点,最后一个间谍就是尾节点,知道怎么去找自己的下线就是指针,间谍传递的信息、指令就是数据。
也就是说这个节点,既有自己传递的信息(数据),又知道如何去找自己的下线间谍(指向下一个节点的指针)。如下图:
这些节点不就是我们上一篇文章中所讲述的结构体吗 !!!是的。
那么,接下来我们就可以定义一个间谍(节点)结构体:
typedef struct spy {
char name[8];
struct spy * next;
}spy, *p_spy;
定义完间谍结构体后,我们就可以来定义间谍了:
p_spy head;
spy spy1 = {"spy1", NULL};
spy spy2 = {"spy2", NULL};
spy spy3 = {"spy3", NULL};
spy spy4 = {"spy4", NULL};
head = &spy1;
spy1.next = &spy2;
spy2.next = &spy3;
spy3.next = &spy4;
spy4.next = NULL;
我们再次来看一下这个关系图:
这就是一个单链表,是不是这样理解起来简单多了呢 !!!
(1)单链表的遍历
我们把单链表定义出来了,当我们需要将这个链表里的数据全部打印出来时,就需要对链表进行遍历,下面是链表的遍历:
while(head)
{
printf("%s\r\n", head->name);
head = head->next;
}
(2)节点的插入
节点的插入我们可以分为三类 :① 在链表的头部插入节点。 ② 在链表的中间插入节点。③ 在链表的尾部插入节点;我们接下来将这三类插入节点的形式封装成一个插入节点函数,废话不多说先看图解详情,再看代码能够更直观,更清晰地了解链表的插入:
原链表图解,如下图:
链表的插入需要先在内存中申请一个节点结构体类型的空间,将需要插入的节点信息存入申请的空间中,下面是插入不同位置的图解:
① 在链表的头部插入节点图解
在链表的头部插入节点就应该,先将节点1的地址给新插入节点的 next ,再让头指针 head 指向新节点。最后返回头指针。
② 在链表的中间插入节点图解
在链表的中间插入节点应该,先找到插入位置的前一个位置,然后将他的下一个节点地址给到新节点的next,最后将新节点的地址给前一个节点的next。
③ 在链表的尾部插入节点图解
在链表的尾部插入节点 与 在链表的中间插入节点是一样的,只不过一个是将空地址给新节点的next,一个是将 地址给新节点的next;
下面是插入节点函数的代码:
p_spy insert_spy(p_spy head, int n)
{
int i;
p_spy p, pr;
p = (p_spy)malloc(sizeof(spy));
printf("输入新节点的名字:\r\n");
scanf("%s", p->name);
pr = head;
i = 1;
if(n == 1 && pr != NULL)
{
p->next = pr;
head = p;
}else
{
while(i < n-1 && pr != NULL)
{
pr = pr->next;
i++;
}
if(pr != NULL)
{
p->next = pr->next;
pr->next = p;
}else
{
printf("节点不存在\r\n");
}
}
return head;
}
(3)节点的删除
节点的删除和节点的插入类似 :① 在链表的头部删除节点。 ② 在链表的中间删除节点。③ 在链表的尾部删除节点;我们还是来先看图解,在看代码:
① 在链表的头部删除节点图解。
在链表的头部删除节点应该,将头指针 head,指向原来头节点的下一个地址,然后把原头节点所在的空间释放掉。
② 在链表的中间删除节点图解。
在链表的中间删除节点应该,先找到删除位置的节点以及删除位置之前节点的位置,然后让删除节点之前位置的 next 指向删除的节点的 next,最后把删除的节点空间释放掉。
③ 在链表的尾部删除节点
在链表的尾部删除节点 与 在链表的中间删除节点是一样的道理。
下面是删除节点函数的代码:
p_spy delete_spy(p_spy head, int n)
{
int i;
p_spy p, pr;
pr = head;
p = head;
i = 1;
if(n == 1 && p != NULL)
{
head = p->next;
free(p);
}else
{
while(i < n && p != NULL)
{
pr = p;
p = p->next;
i++;
}
if(p != NULL)
{
pr->next = p->next;
free(p);
}else
{
printf("删除的节点不存在\r\n");
}
}
return head;
}
(4)节点的修改
节点的修改只需要找到要修改节点的位置,将其的数据就行修改就行了,下面直接上代码:
void change_spy(p_spy head, int n)
{
p_spy p;
int i = 1;
while(i < n && p != NULL)
{
p = p->next;
i++;
}
if(p != NULL)
{
printf("该节点的原始值为:%s\r\n", p->name);
printf("请输入修改后的值:\r\n");
memset(p->name, '\0', sizeof(p->name));
scanf("%s", p->name);
}else
{
printf("该节点不存在\r\n");
}
}
(5)节点的查找
在学习完链表的增加、删除、修改后,节点的查找就不用再去仔细的详解了,请看上面代码。
3、双链表
对比单链表,双链表就是节点既有下一个节点的地址,又有上一个节点的地址,其双链表图解如下:
对比单链表的各种操作我们也不难写出双链表对应的函数,在这里就不详细写双链表了。
小结
本文主要写单链表的遍历以及增、删、改、查的操作。感谢大家观看
本专栏文章:
C语言加强篇——(1)学习笔记 之 变量、指针、关键字
C语言加强篇——(2)学习笔记 之 结构体、结构体指针、函数指针
C语言加强篇——(3)学习笔记 之 链表的增、删、改、查
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)