数据结构:单链表

目录

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

最后需要注意的是:

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

相关推荐
AC使者1 小时前
5820 丰富的周日生活
数据结构·算法
无 证明2 小时前
new 分配空间;引用
数据结构·c++
别NULL6 小时前
机试题——疯长的草
数据结构·c++·算法
ZSYP-S7 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
唐叔在学习7 小时前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA8 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
武昌库里写JAVA11 小时前
浅谈怎样系统的准备前端面试
数据结构·vue.js·spring boot·算法·课程设计
S-X-S11 小时前
代码随想录刷题-数组
数据结构·算法
l1384942745111 小时前
每日一题(4)
java·数据结构·算法
kyrie_sakura11 小时前
c++数据结构算法复习基础--13--基数算法
数据结构·c++·算法