链表——C语言——day17

链表

链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。在用数组存放数据时,必须事先定义固定的长度(即元素个数)。链表则没有这种缺点,它根据需要开辟内存单元。

链表有一个"头指针"变量,图中以 head 表示,它存放一个地址,该地址指向一个元素。链表中每一个元素称为"结点",每个结点都应包括两个部分:用户需要用的实际数据和下一个结点的地址,也称为数据域和指针域。可以看出,head 指向第一个元素;第一个元素又指向第二个元素......直到最后一个元素,该元素不再指向其他元素,它称为"表尾",它的地址部分放一个"NULL"( 表示"空地址"),链表到此结束。

链表中各元素在内存中可以不是连续存放的。要找某一元素,必须先找到上一个元素,根据它提供的下一元素地址才能找到下一个元素。如果不提供"头指针"(head),则整个链表都无法访问。

我们可以这样设计结构体类型:

c 复制代码
struct student 
{	int num; 
	float score;
	struct student * next;
};

其中成员num和score用来存放结点中的有用数据(用户需要用到的数据),相当于上图结点中的 A,B,C,D。next 是指针类型的成员,它指向 struct student 类型数据(这就是next 所在的结构体类型)。一个指针类型的成员既可以指向其他类型的结构体数据,也可以指向自己所在的结构体类型的数据。现在,next是struct student 类型中的一个成员,它又指向struct student 类型的数据。用这种方法就可以建立链表。

建立链表

首先,链表分为有头链表和无头链表

在本文章中,我们主要研究"有头单向链表"

空链表 ------代表头节点的next指针指NULL

c 复制代码
void initList(struct Node *pHead)
{
	pHead->next = NULL;
}

链表的插入

头插法

step1:首先是创建新节点

struct Node *pNew = malloc (sizeof(struct Node));

pNew->data = 100;

step2:将新节点插入链表

struct Node *pNew= malloc(sizeof(stiuct Node));

pNew->data= 100;

(1).pNew->next = pHead->next;

(2).pHead->next = pNew;

c 复制代码
我们可以将头插法函数写成这样:
void pushFront(struct Node *pHead,int n)
{
	struct Node *pNew = malloc (sizeof(struct Node));  // 在堆上创建空间
	pNew->data= n;  //输入新节点的数据
	pNew->next = pHead->next;	//将头节点的指针域上的地址赋值给新节点指针域
	pHead->next = pNew;	//头节点的指针域上的地址指向新节点
}
尾插法

step1:首先是创建新节点

step2:定位到尾节点

c 复制代码
定位到尾节点:
while(p->next != NULL)
{
p = p->next;
}

step3:将新节点插入链表

但是,我们需要考虑如果链表本身是个空链表,怎么尾插?并且还需要判断链表是否为空?

所以,我们将尾插法可以写成这样:

c 复制代码
int isEmpty(struct Node *pHead) //判断链表是否为空链表
{
	return pHead->next == NULL;
}

void pushBack(struct Node *pHead, int n)
{
	if(isEmpty(pHead))
	{
		pushFront(pHead, n);	//空的话直接使用头插法
	}
	else
	{
		struct Node *pNew= mallcc(sizeof(struct Node));
		pNew->data=n;
		struct Node *p = pHead->next;
		while(p->next)
		{
			p = p->next;
		}
		p->next = pNew;
		pNew->next = NULL;
	}
}
链表遍历

只要p不为NULL,直接输出数据即可。

c 复制代码
void printList(struct Node *pHead)
{
	struct Node *p;
	p =pHead->next;
	while(p != NULL)
	{
		printf("&d\n", p->data);
		p = p->next;
	}
}
计算链表中有效节点的个数
c 复制代码
size_t length(struct Node *pHead)
{
	size_t ret =0;
	struct Node *p= pHead->next;
	while(p)
	{
		++ret;
		p = p->next;
	}
	return ret;
}
头删法

在删除的时候,我们首先要确定链表是否为空,若链表为空,则不能删除。

首先,头节点的地址域指针指向p->next的地址,随后释放p即可。

c 复制代码
void popFront(struct Node *pHead)
{
	if(!isEmpty(pHead))
	{
		struct Node *p= pHead->next;
		pHead->next = p->next;
		free(p);
	}
}
尾删法

我们首先要判断链表是否为空,为空的话直接结束,随后判断链表中是否至少有两个以上的有效节点,如果只有一个节点,直接转到头删法即可。

c 复制代码
void popBack(struct Node *pHead)
{
	if(!isEmpty(pHead))	//判断是否为空链表
	{
		if(length(pHead)== 1) 	//判断有几个节点
		{
			popFront(pHead);
		}
		else
		{
			struct Node *p= pHead->next;
			while(p->next->next != NULL)
			{
				p = p->next;
			}
			free(p->next);
			p->next = NULL;
		}
	}
}
链表销毁
c 复制代码
void destroyList(struct Node *pHead)
{
	while(!isEmpty(pHead))
	{
		popBack(pHead);popFront(pHead);
	}
}

以上就是链表的常见操作。

相关推荐
陌小呆^O^4 分钟前
Cmakelist.txt之win-c-udp-client
c语言·开发语言·udp
daiyang123...43 分钟前
测试岗位应该学什么
数据结构
kitesxian1 小时前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode
qystca3 小时前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法
薯条不要番茄酱3 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
盼海5 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
网易独家音乐人Mike Zhou8 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
‘’林花谢了春红‘’9 小时前
C++ list (链表)容器
c++·链表·list
搬砖的小码农_Sky11 小时前
C语言:数组
c语言·数据结构
先鱼鲨生13 小时前
数据结构——栈、队列
数据结构