P5 链表 尾部插入新节点(不是指定点)

目录

前言  

01 链表数据插入之直接在链表尾插入(不是指定点)

02 尾插创建链表优化

示例代码 


前言  

                           
                                

🎬 个人主页:@ChenPi

🐻推荐专栏1: 《C++》✨✨✨ 

🔥 推荐专栏2: 《 Linux C应用编程(概念类)》✨✨✨

📝推荐专栏3: ​​​​​​《 链表 》 ✨✨✨
🍉本篇简介  :  链表数据插入之尾插法

✨ 只有我努力了 才有机会接触成功✨

链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。链表中每个节点都分为两部分,一个数据域,一个是指针域。说到这里你应该就明白了,链表就如同车链子一样,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。

作为有强大功能的链表,对他的操作当然有许多,比如:

  1. 链表的创建
  2. 链表的链表的遍历打印数据
  3. 链表里面的结构体数据的修改
  4. 链表节点的删除
  5. 链表插入新节点
  6. 链表的数据排序
  7. 链表的反序
  8. 清空链表的元素
  9. 求链表的长度等

 在前面几章,我们学习了

  1. 链表的创建
  2. 链表的链表的遍历打印数据
  3. 链表里面的结构体数据的修改
  4. 求链表的长度等

这一章我们来学习新的知识

尾部插入新节点(不是指定点)

01 链表数据插入之直接在链表尾插入(不是指定点)

在上几章中

我们对链表的数据插入都是有的比较土的方法

 数据节点都是这样一个一个插入

看着就挺离谱的,这一章中我们尝试优化它,我们先把红箭头的那部分先给优化了

我们定义个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函数做个封装

02 尾插创建链表优化

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 <stdio.h>
#include <stdlib.h>
#include <string.h>

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;
}

  • 38
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@ChenPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值