问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C语言动态链表建立以及增删节点详解

创作时间:
作者:
@小白创作中心

C语言动态链表建立以及增删节点详解

引用
CSDN
1.
https://blog.csdn.net/DushsK/article/details/137167674

动态链表的具体实现是有些抽象的,所以想学好需要结合图示,把实现的逻辑想明白,才能快速上手。

实现原理

指针

指针是C语言很基础的一个知识点,这里不多赘述,理解了指针才能理解链表。

节点

一个节点有若干数据,和一个指向下一个节点的指针

typedef struct//定义链表结点结构体类型 
{
    int data;
    struct node *next;
}NODE;//定义类型别名  

链表

空白的格子是数据,如上节点案例,只有一个int类型的变量
所以这里一个节点只有一个int类型的数据
第二个格子则是指向下一个节点的指针
一个节点存储着数据的同时,有一个指向下一个节点的指针
像图中那样,将每一个节点的指针(称为末节点)串起来,就形成了静态链表(无法增删节点)

动态链表

在静态链表的基础上,能增加和删除节点的
就是动态链表

增加节点
有如下面这个链表
原本第二个节点指向第三个节点
现在将第二个节点指向新加入的储存的int变量=6的新节点
然后将新节点指向原本的第三个节点
随后新节点变成第三个节点
原本的第三个节点变成第四个节点
整个链表就连起来,增加了节点

删除节点
有如下面这个链表
原本第一个节点的next指向第二个节点
现在将第一个节点的next指向第三个节点
然后将第二个节点内存释放(相当于删掉)
随后链表里就剩下三个节点
整个链表依旧连起来,且删掉了目标节点

代码解析

库函数

#include<stdio.h>
#include<stdlib.h>  

定义节点结构体

一个节点有多少个数据都可以定义
示例里只定义了一个int变量
最后定义指向下一个节点的末节点

typedef struct//定义链表结点结构体类型 
{
    int data;
    struct node *next;
}NODE;//定义类型别名  

创建并遍历链表

malloc()是一个分配内存的函数
sizeof(NODE)表示申请的这个节点的大小
在循环中,将新节点的数据录入,并指向下一个节点,直到负数结束循环,将最后一个节点指向空,即NULL,形成一个链表
然后写一个函数遍历链表,输出链表的每一个节点的存储的值

/*
    函数:创建动态链表
    输入:链表数值,直到 负数 
    输出: 无 
*/ 
NODE *create() 
{
    NODE *head,*now,*q;//now指向当前节点,q指向下一个结点 
    int t;//用于暂存输入的成绩
    head=(NODE*)malloc(sizeof(NODE)); //创建头节点 
    now=head;//指向头节点 
    while(1)
    {
        printf("请输入一个整数成绩(以负数结束):");
        scanf("%d",&t);
        if(t<0) break;
        q=malloc(sizeof(NODE));//q指向新结点 
        q->data=t;   //将t的值赋予新节点指向的数据域 
        now->next=q;  //将新结点连接到链表中 
        now=q;    
    }
    now->next=NULL;//末结点指向空 
    return head;//返回头结点 
}
/*
    函数:遍历链表 
    输入:链表节点 
    输出:链表每个节点储存的值 
*/ 
void print(NODE *head) 
{
    NODE *now;//当前节点 
    now=head->next;
    if(now==NULL)
      printf("该链表为空!\n");
    else 
    {
        printf("链表中的数据为:");
        while(now!=NULL)
        {
            printf("->%d",now->data);
            now=now->next;
        }
    }
    printf("\n");
    return;
}  

效果如图

增加节点

先通过输入一个值确定要增加的节点在链表中位置,来实现定位,姑且将新节点的上一个节点称为前节点
完成定位后,增加一个新节点,然后将前节点指向新节点,将新节点指向前节点原来指向的下一个节点,从而连接起来成为新链表,这里不太理解的可以往回看集合图示更好理解

/*
    函数:增加链表的节点 
    输入:链表头节点 
    输出:无 
*/ 
void add(NODE *head)
{
    int Target,NewTarget;//暂存两个数值 
    printf("请输入增加的节点的上一节点的值:");
    scanf("%d",&Target); 
    printf("请输入新节点的值:");
    scanf("%d",&NewTarget);
    NODE *Now,*NewNode,*Nextp;//分别表示当前节点,新节点,下一节点 
    Now=head;
    Nextp=Now->next;//指向下一节点 
    NewNode=malloc(sizeof(NODE));//申请一个NODE大小的空间给新节点 
    NewNode->data=NewTarget;//将值赋给新节点 
    while(1)
    {
        Nextp=Now->next;//将Nextp指向下一节点 
        if(Now->data==Target)//如果当前节点的值等于目标值 
        {            
            Now->next=NewNode;//将当前节点指向新节点 
            NewNode->next=Nextp;//将新节点指向下一节点完成链表连接 
            printf("节点增加成功\n");//成功反馈 
            break;//退出循环以结束函数            
        }
        else if(Now->next==NULL) 
        {
            printf("节点增加失败,未查找到上一节点的值\n");//失败反馈 
            break;//退出循环以结束函数
        }
        else Now=Now->next;//遍历下一节点来寻找要删除的值 
    }
    return;
}  

删除节点

删除节点就很好理解了,输入要删除的节点的值,然后遍历链表寻找这个值,找到之后,将被删节点的前节点,指向被删节点的后节点,这样被删节点就被孤立出来了,然后释放内存,成功将这个节点删除

/*
    函数:删除链表的节点 
    输入:链表头节点,删除的节点 
    输出:无 
*/
void dele(NODE *head)
{
    NODE *now,*nextp;
    int Target;
    printf("请输入要删除的值:");
    scanf("%d",&Target);
    now=head;
    nextp=now->next;
    while(1)
    {        
        if(nextp->data==Target)
        {
            now->next=nextp->next;
            free(nextp);
            printf("节点删除成功\n");
            break;            
        } 
        else
        {   now=nextp;
            nextp=nextp->next;
        }
        if(nextp->next==NULL) 
        {
            printf("节点删除失败,未查找到要删除的值\n");
            break; 
        }
    }
    return;    
}  

主函数

看注释即可,不多赘述

int main()
{
    NODE *h;   //定义一个节点类型的指针 
    h=create();//创建一个链表并返回头指针给h,将h设为头指针 
    print(h);  //遍历链表检查是否成功创建 
    dele(h);   //删除一个节点 
    print(h);  //遍历链表检查是否成功删除 
    add(h);    //增加一个节点
    print(h);  //遍历链表检查是否成功增加
    return 0;
}  

完整代码

#include<stdio.h>
#include<stdlib.h>
typedef struct//定义链表结点结构体类型
{
    int data;
    struct node *next;
}NODE;//定义类型别名
/*
    函数:创建动态链表
    输入:链表数值,直到 负数
    输出: 无
*/
NODE *create()
{
    NODE *head,*now,*q;//now指向当前节点,q指向下一个结点
    int t;//用于暂存输入的成绩
    head=(NODE*)malloc(sizeof(NODE)); //创建头节点
    now=head;//指向头节点
    while(1)
    {
        printf("请输入一个整数成绩(以负数结束):");
        scanf("%d",&t);
        if(t<0) break;
        q=malloc(sizeof(NODE));//q指向新结点
        q->data=t;   //将t的值赋予新节点指向的数据域
        now->next=q;  //将新结点连接到链表中
        now=q;    
    }
    now->next=NULL;//末结点指向空
    return head;//返回头结点
}
/*
    函数:遍历链表
    输入:链表节点
    输出:链表每个节点储存的值
*/
void print(NODE *head)
{
    NODE *now;//当前节点
    now=head->next;
    if(now==NULL)
      printf("该链表为空!\n");
    else
    {
        printf("链表中的数据为:");
        while(now!=NULL)
        {
            printf("->%d",now->data);
            now=now->next;
        }
    }
    printf("\n");
    return;
}
/*
    函数:增加链表的节点
    输入:链表头节点
    输出:无
*/
void add(NODE *head)
{
    int Target,NewTarget;//暂存两个数值
    printf("请输入增加的节点的上一节点的值:");
    scanf("%d",&Target);
    printf("请输入新节点的值:");
    scanf("%d",&NewTarget);
    NODE *Now,*NewNode,*Nextp;//分别表示当前节点,新节点,下一节点
    Now=head;
    Nextp=Now->next;//指向下一节点
    NewNode=malloc(sizeof(NODE));//申请一个NODE大小的空间给新节点
    NewNode->data=NewTarget;//将值赋给新节点
    while(1)
    {
        Nextp=Now->next;//将Nextp指向下一节点
        if(Now->data==Target)//如果当前节点的值等于目标值
        {            
            Now->next=NewNode;//将当前节点指向新节点
            NewNode->next=Nextp;//将新节点指向下一节点完成链表连接
            printf("节点增加成功\n");//成功反馈
            break;//退出循环以结束函数            
        }
        else if(Now->next==NULL)
        {
            printf("节点增加失败,未查找到上一节点的值\n");//失败反馈
            break;//退出循环以结束函数
        }
        else Now=Now->next;//遍历下一节点来寻找要删除的值
    }
    return;
}
/*
    函数:删除链表的节点
    输入:链表头节点,删除的节点
    输出:无
*/
void dele(NODE *head)
{
    NODE *now,*nextp;
    int Target;
    printf("请输入要删除的值:");
    scanf("%d",&Target);
    now=head;
    nextp=now->next;
    while(1)
    {        
        if(nextp->data==Target)
        {
            now->next=nextp->next;
            free(nextp);
            printf("节点删除成功\n");
            break;            
        }
        else
        {    now=nextp;
            nextp=nextp->next;
        }
        if(nextp->next==NULL)
        {
            printf("节点删除失败,未查找到要删除的值\n");
            break;
        }
    }
    return;    
}
int main()
{
    NODE *h;
    h=create();//创建一个链表并返回头指针给h,将h设为头指针
    print(h);
    dele(h);
    print(h);
    return 0;
}  
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号