数据结构:单链表

目录

1.1链表的概念

1.2单链表的结构

2.实现链表(不带头单向非循坏)

2.1链表结构的定义

2.2链表功能的实现

2.2.1动态申请一个结点

[2.2.2 打印单链表](#2.2.2 打印单链表)

2.2.3单链表头插

2.2.4单链表头删

2.2.5单链表查找

2.2.6单链表在pos位置之前插入

2.2.7删除pos位置

2.2.8销毁链表


1.1链表的概念

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

1.2单链表的结构

**注意:**最后一个结点的*next要等于NULL,next=NULL

2.实现链表(不带头单向非循坏)

2.1链表结构的定义
复制代码
typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType data;
	struct SListNode* next;
}SListNode;
2.2链表功能的实现
复制代码
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);

// 单链表打印
void SListPrint(SListNode* plist);

// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);

// 单链表头删
void SListPopFront(SListNode** pplist);

// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);

//在pos的前面插入
void SLTInsert(SListNode** pplist, SListNode* pos, SLTDateType x);

// 删除pos位置
void SLTErase(SListNode** pplist, SListNode* pos);
2.2.1动态申请一个结点

需要一个函数申请一个结点,方便后续的插入操作

复制代码
//动态申请一个节点
SListNode* BuySListNode(SLTDateType x)
{
	SListNode* Node = (SListNode*)malloc(sizeof(SListNode));
	if (Node == NULL)
	{
		perror("Node::malloc");
		return NULL;
	}
	Node->data = x;
	Node->next = NULL;
	return Node;
}
2.2.2 打印单链表

打印链表就是遍历链表,当print = NULL时,停止打印

复制代码
// 单链表打印
void SListPrint(SListNode* plist)
{
	SListNode* print = plist;
	while (print != NULL)
	{
		printf("%d->", print->data);
		print = print->next;
	}

	printf("NULL\n");
}
2.2.3单链表头插

单链表头插十分简单,只需要将新结点 的next指向单链表第一个结点,然后将原来单链表指向新结点即可。

复制代码
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{
	SListNode* Node = BuySListNode(x);
	Node->next = *pplist;
	*pplist = Node;
}
2.2.4单链表头删

头删也是十分简单,首先找到原链表首结点的下一个结点,然后释放掉第一个结点。

复制代码
// 单链表头删
void SListPopFront(SListNode** pplist)
{
	assert(*pplist);
	SListNode* FrontDele = *pplist;
	*pplist = FrontDele->next;
	free(FrontDele);
	FrontDele = NULL;
}
2.2.5单链表查找

找到该数据,返回该数据所在位置的地址(即结点),找不到返回NULL

复制代码
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
	assert(plist);
	SListNode* find = plist;
	while (find != NULL)
	{
		if (find->data == x)
		{
			return find;
		}
		find = find->next;
	}

	//当找不到返回NULL
	
	return NULL;
}
2.2.6单链表在pos位置之前插入
复制代码
// 在pos的前面插入
void SLTInsert(SListNode** pplist, SListNode* pos, SLTDateType x)
{
	assert(pplist);
	assert(pos);
	
	
	SListNode* Node = BuySListNode(x);
	SListNode* Insert = *pplist;
   //当Ineset的下一个结点为空,则代表链表只有一个结点,所以直接头插
	if (Insert->next == NULL)
	{
		SListPushFront(pplist, x);
	}
	else
	{
      //找到pos前面的结点的位置
		while (Insert->next != pos)
		{
			Insert = Insert->next;

		}
    //找到后将新结点的next指向pos,然后pos前面结点的位置指向新结点
		Node->next = Insert->next;
		Insert->next = Node;
	}
	
}
2.2.7删除pos位置
复制代码
// 删除pos位置
void SLTErase(SListNode** pplist, SListNode* pos)
{
	assert(pplist);
	assert(pos);
	
	SListNode* Erase = *pplist;
  //找到pos前面结点的位置
	while (Erase->next != pos)
	{
		Erase = Erase->next;
	}
	
	//然后将Erase的next指向pos下一个结点
	Erase->next = pos->next;
	free(pos);
	pos = NULL;
}
2.2.8销毁链表

链表是由一个个结点组成,每个结点都动态申请了空间,所以销毁链表需要遍历,然后一个一个释放掉

复制代码
//销毁链表
void SLTDestory(SListNode** pphead)
{
	assert(pphead);
	SListNode* cur = *pphead;
	while (cur)
	{
		SListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

最后需要注意的是:

调用链表的各个函数时需要传二级指针 ,如果传一级指针则会出现很多问题 ,因为链表功能的实现是在函数里改变了指针,这里只是形参 的改变,并没有给实参带来变化,所以想要实参变化必须使用二级指针!!!

相关推荐
阿让啊2 小时前
C语言strtol 函数使用方法
c语言·数据结构·c++·单片机·嵌入式硬件
superlls5 小时前
(算法 哈希表)【LeetCode 349】两个数组的交集 思路笔记自留
java·数据结构·算法
Ripple123126 小时前
数据结构:顺序表与链表
数据结构·链表
一个响当当的名号7 小时前
B树,B+树,B*树(无代码)
数据结构·b树
古译汉书8 小时前
嵌入式铁头山羊stm32-ADC实现定时器触发的注入序列的单通道转换-Day26
开发语言·数据结构·stm32·单片机·嵌入式硬件·算法
野犬寒鸦8 小时前
力扣hot100:相交链表与反转链表详细思路讲解(160,206)
java·数据结构·后端·算法·leetcode
GalaxyPokemon9 小时前
LeetCode - 1089. 复写零
数据结构
失散139 小时前
分布式专题——1.2 Redis7核心数据结构
java·数据结构·redis·分布式·架构
zzzsde10 小时前
【数据结构】强化训练:从基础到入门到进阶(1)
数据结构
奔跑吧 android11 小时前
【linux kernel 常用数据结构和设计模式】【数据结构 3】【模拟input子系统input_dev和input_handler之间的多对多关系】
linux·数据结构·input·kernel·input_dev·input_handler·input_handle