【C语言】动态链表建立以及增删节点

简介

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

实现原理

指针

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

专业大佬的指针详解

B站一个讲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;
}

  • 45
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值