目录
前言
01 链表数据插入之直接在链表尾插入(不是指定点)
02 尾插创建链表优化
示例代码
个人主页:@ChenPi
推荐专栏1: 《C++》✨✨✨
推荐专栏2: 《 Linux C应用编程(概念类)》✨✨✨
推荐专栏3: 《 链表 》 ✨✨✨
本篇简介 : 链表数据插入之尾插法
✨ 只有我努力了 才有机会接触成功✨
链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。链表中每个节点都分为两部分,一个数据域,一个是指针域。说到这里你应该就明白了,链表就如同车链子一样,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
作为有强大功能的链表,对他的操作当然有许多,比如:
- 链表的创建
- 链表的链表的遍历打印数据
- 链表里面的结构体数据的修改
- 链表节点的删除
- 链表插入新节点
- 链表的数据排序
- 链表的反序
- 清空链表的元素
- 求链表的长度等
在前面几章,我们学习了
- 链表的创建
- 链表的链表的遍历打印数据
- 链表里面的结构体数据的修改
- 求链表的长度等
这一章我们来学习新的知识
尾部插入新节点(不是指定点)
在上几章中
我们对链表的数据插入都是有的比较土的方法
数据节点都是这样一个一个插入
看着就挺离谱的,这一章中我们尝试优化它,我们先把红箭头的那部分先给优化了
我们定义个tailInsertLinkList函数,用于从尾部插入新的链表节点
函数类型为int类型,用于返回标志位,即1和-1,1为成功-1失败
函数参数我们接收一个struct Link的结构体指针和即将要插入数据的数据data
int tailInsertLinkList(struct Link * head,int data)
{
}
函数体大概这样了
然后我们将代码补全
代码补全后大致这样的,我们来看一下代码的意思是什么
76-79行,NULL == head,这句话的意思是,head为空指针的时候进入if循环语句,然后就是return -1了,为什么直接return了呢?因为传进来的头是空的,我们希望传进来的是空指针,所以放回-1,当然也可以修改成传入空指针也能运行链表(看个人)
80-83行,定义个结构体指针prev指向head头,
然后我们要定义节点,那我们肯定要定义一个结构体充当节点,你可以看到我们使用了malloc函数,给new在堆中开辟了空间,为啥要在堆中开辟呢?作用域的问题,可以看下下篇博文
P28 C++ 对象的生存周期(栈的作用域生存周期)-CSDN博客
定义好了节点,然后就是初始化了,将new的next = NULL;new 的data = data
第84到94行:84行就是遍历的条件了,置于为啥是NULL != prev,可以看下前面的博文,
我们要在链表的尾巴插入新数据,那我们看到要找到链表的尾才行啊,链表的尾巴是什么样的?
可以看到链表的尾部的next是指向NULL的,所以我们可以将这个特点用于查找链表的尾部
如果找到了,就将链表的尾的next指向new节点
然后返回1,因为成功了,跳出循环
93行的return -1的意思就是没找到链表的尾,出错了返回
我们将代码编译试一下
可以看到尾部插入创建链表已经没问题了
但是我们看这个代码,感觉还是有点不太合理,数据只能提前打好
那我们在优化一下
我们给tailInsertLinkList函数做个封装
int tailInsertLinkListPro(struct Link * head,const int size)
{
int *bufData = (int*)malloc(sizeof(int)*size);
for(int i = 0; i < size; i++)
{
scanf("%d", bufData+i);
tailInsertLinkList(head,bufData[i]);
}
}
大致函数体就长这样了,我们需要两参数,一个是链表头的地址,一个整形数,整形数拿来干嘛的呢?
用于创建节点数的,比如我怎么知道我要创建几个节点呢?
就是利用这个整形数size,传入几个就在键盘输入几个data
就是这样,很简单
#include
#include
#include
struct Link
{
int data;
struct Link *next;
};
/*打印链表数据*/
void PrintLink(struct Link *head)
{
struct Link *prev = head;
while (NULL != prev)
{
printf("%d ", prev->data);
prev = prev->next;
}
printf("\n");
}
/*获取链表的节点数*/
int GetLinkNum(struct Link *head)
{
struct Link *prev = head;
int count = 0;
while (prev != NULL)
{
count++;
prev = prev->next;
}
return count;
}
/* 查找链表中的数据,只能找到一个,且不知道节点数*/
int findLinkData(struct Link *head,int data)
{
struct Link *prev = head;
while (prev!= NULL)
{
if (prev->data == data)
{
return 1;
}
prev = prev->next;
}
return 0;
}
/* 在链表中查找需要的数据,如果有,打印节点号和数据*/
void FindLinkDataPro(struct Link *head,int data)
{
int count = 0; //遍历记录节点号
int NumFd =0; // Number数据的索引
int Number[32] = {0};
struct Link *prev = head;
while (prev!= NULL)
{
if(prev->data == data)
{
Number[NumFd++] = count;
}
count++;
prev = prev->next;
}
for(int i = 0; i < NumFd; i++)
{
printf("节点号:%d 查找的数据%d\n",Number[i]+1,data);
}
}
/*尾部顺序插入形成链表*/
int tailInsertLinkList(struct Link * head,int data)
{
if(NULL == head)
{
return -1;
}
struct Link *prev = head;
struct Link *new = (struct Link*)malloc(sizeof(struct Link ));
new->data = data;
new->next = NULL;
while (NULL != prev)
{
if(NULL == prev->next)
{
prev->next = new;
return 1;
}
prev = prev->next;
}
return -1;
}
int tailInsertLinkListPro(struct Link * head,const int size)
{
int *bufData = (int*)malloc(sizeof(int)*size);
for(int i = 0; i < size; i++)
{
scanf("%d", bufData+i);
tailInsertLinkList(head,bufData[i]);
}
}
int main()
{
struct Link head = {1,NULL};
int size = 0;
puts("请输入你要在链表尾部插入的数据数目");
scanf("%d",&size);
printf("请按要求输入%d个数据\n",size);
tailInsertLinkListPro(&head,size);
PrintLink(&head);
//FindLinkDataPro(&link1,2);
//int findID = 0;
//findID = findLinkData(&link1,2);
//printf("findID = %d 0为未找到数据 1则找到数据\n", findID);
//printf("%d\n", GetLinkNum(&link1));
return 0;
}