链表(C语言版)

         在学习之前,可以温故一下结构体的知识,明白结构体变量和结构体指针,可以看我的一篇博客:https://blog.youkuaiyun.com/a1130683021/article/details/134595804?spm=1001.2014.3001.5501

链表的概念

        链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的

        剖析概念,我们得到几个关键词:非连续非顺序指针链接次序。通过了解链表的结构,我们很快就能明白这些关键词的含义

链表的结构

        链表由一个又一个节点,通过指针进行连接。每个节点中会存在两个域,一个是数据域,另一个是指针域。数据域用来存储数据,指针域用来链接节点。思考什么数据结构可以去胜任节点呢?当然是结构体。因此,结构体就是充当节点,每一个结构体都包括存储数据的变量,以及结构体指针——用于指向结构体变量。

        从图中我们不难发现,节点与节点之间是通过结构体指针进行链接的,而节点之间是离散的,在内存里是这里一个那里一个,并不像数组空间一样连续。

单向链表的实现

        一.节点的创建

               1. 声明结构体类型

struct Node {
	//数据域,存储数据
    int data;
    char name[10];
    //指针域,用于指向结构体变量(节点)
	struct Node* next;
};

        由于节点是结构体,并且是Node类型的结构体,因此我们需要定义Node类型的结构体指针。 

                2.节点的创建

        于是,我们可以通过Node结构体类型进行节点的创建。

struct Node node1,node2;

        二.链表逻辑以及代码

                重要引入

       头指针指向链表的头节点,一个链表需要头指针,为什么?因为我们需要用链表。类比数组的使用,我们需要知道数组的首地址,通过指针移动的方式进行访问。链表同理,我们需要知道链表的头指针,通过头指针去进行指针的移动,对链表进行操作。一般,头节点的数据域不放数据。

        我们都知道将思路转化为编程语言是一大难点,该如何去安排语句呢?思路上,我们是需要创建多个节点的,但是,假如我需要10000个节点,我总不能死板的一口气创建10000个节点吧?所以我们需要使用到循环,将创建节点的语句放入循环中。但是这样就有一个问题:当我们下一次循环再次创建节点的时候,我便失去了上一次循环创建的节点的地址(类比于循环中放入定义变量的语句,每一次循环都是重新定义变量,这会导致上一次变量数据的丢失)。因此我们需要通过一个结构体指针来存储上一个节点的地址。为了方便操作,我们也可以定义一个结构体指针来指向新的节点。

        

                代码以及图解

/*
pnew 新的节点
pend 上一个节点
head 头指针
*/
int count = 0;//表示是当前第几个节点,从0开始
struct Node* create()
{
	int cnt;//链表的长度
	printf("请输入链表长度:\n");
	scanf("%d", &cnt);
	struct Node* pnew, * pend;//定义结构体指针
	struct Node* head = NULL;//定义头指针并置于NULL
/*

malloc用于在堆中开辟空间,如下文代码中,开辟了Node大小的内存空间
并且返回了一个Node类型的结构体指针

malloc返回一个Node类型的指针给pnew,pnew指向一个节点的地址
*/
	pnew = (struct Node*)malloc(sizeof(struct Node));
	while (count <= cnt)
	{
		if (count == 0)
		{
			//见图1
			pnew->next = NULL;//将next指针置空,告诉编译器这里是当前链表终点
            //以下两步将pnew以及pend都置于头节点
            head = pnew;
			pend = pnew;
		}
		else {
			//见图2
			pnew = (struct Node*)malloc(sizeof(struct Node));//申请一个新的节点
			scanf("%s", &pnew->name);//输入数据
			scanf("%d", &pnew->data);
			pnew->next = NULL;//指针置空
			pend->next = pnew;//节点的链接
			pend = pnew;//新的节点变成了旧的节点
		}
		count++;
	}
	return head;//返回头指针
}

附图1:

附图2 

 

创建结束后的链表

由附图二我们可以看出,pend移动之后,上一个节点的地址将会丢失,当前节点变成旧节点,以便为了继续连接新的节点。因此在链表被完全创建完之后,pnew以及pend会指向最后一个节点,head依旧指向头节点,没有变过。

三.遍历链表

void Input(struct Node* head)
{
//我们要判断是否存在下一个节点,如果不存在,head->next即为NULL
//见图三
	head = head->next;
	while (head != NULL)
	{
		printf("%d\t%s\n", head->data, head->name);
		head = head->next;
	}
}

       

         通过头指针,我们可以移动指针来遍历链表。首先,我们将head指针移动到它的next位置,也就是head = head->next。如果head为NULL,则代表链表到了终点,跳出循环。


待更

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值