数据结构:单链表

目录

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

最后需要注意的是:

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

相关推荐
_饭团19 分钟前
指针核心知识:5篇系统梳理3
c语言·数据结构·算法·leetcode·面试·学习方法·改行学it
星空露珠1 小时前
又双叒叕统计被炸死的lua脚本
开发语言·数据结构·算法·游戏·lua
Via_Neo2 小时前
日期问题和日期常用API
数据结构·算法
小年糕是糕手2 小时前
【C++】string类(三)
开发语言·数据结构·c++·程序人生·算法
IronMurphy3 小时前
【算法二十五】105. 从前序与中序遍历序列构造二叉树 236. 二叉树的最近公共祖先
java·数据结构·算法
像污秽一样4 小时前
算法设计与分析-习题8.2
数据结构·算法·排序算法·dfs·化简
玛卡巴卡ldf4 小时前
【LeetCode 手撕算法】(子串) 560-和为 K 的子数组
java·数据结构·算法·leetcode
不想看见4044 小时前
Rotate Image数组--力扣101算法题解笔记
数据结构·算法
仰泳的熊猫4 小时前
题目 2304: 蓝桥杯2019年第十届省赛真题-特别数的和
数据结构·c++·算法·蓝桥杯
像污秽一样5 小时前
算法设计与分析-习题4.3
数据结构·算法·排序算法