数据结构:单链表

目录

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;
}

最后需要注意的是:

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

相关推荐
ゞ 正在缓冲99%…25 分钟前
leetcode152.乘积最大子数组
数据结构·算法·leetcode
闯闯爱编程1 小时前
数组与特殊压缩矩阵
数据结构·算法·矩阵
laimaxgg2 小时前
数据结构B树的实现
开发语言·数据结构·c++·b树·算法
灋✘逞_兇4 小时前
链表的操作-反转链表
数据结构·链表
双叶8368 小时前
(C语言)虚数运算(结构体教程)(指针解法)(C语言教程)
c语言·开发语言·数据结构·c++·算法·microsoft
快来卷java10 小时前
MySQL篇(一):慢查询定位及索引、B树相关知识详解
java·数据结构·b树·mysql·adb
想睡hhh11 小时前
c语言数据结构——八大排序算法实现
c语言·数据结构·排序算法
月亮被咬碎成星星13 小时前
LeetCode[15]三数之和
数据结构·算法·leetcode
JCBP_13 小时前
数据结构3
服务器·c语言·数据结构·vscode
半盏茶香14 小时前
启幕数据结构算法雅航新章,穿梭C++梦幻领域的探索之旅——堆的应用之堆排、Top-K问题
java·开发语言·数据结构·c++·python·算法·链表