数据结构--线性结构<单链表>

链表的概念及结构

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
在这里插入图片描述
注意:

  1. 从上图可看出,链式结构在逻辑上是连续的,但是在物理上不- -定连续
  2. 现实中的结点一般都是从堆上申请出来的
  3. 从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续

假设在32位系统.上,结点中值域为int类型,则-一个节点的大小为8个字节,则也可能有下述链表:

在这里插入图片描述

链表的分类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

  1. 双向或者单向
    在这里插入图片描述

  2. 带头或者不带头
    在这里插入图片描述

  3. 循环或者不循环
    在这里插入图片描述

虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:

无头不循环单向链表:
在这里插入图片描述
带头循环双向链表:

在这里插入图片描述

  1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
  2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向
    循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而
    简单了,后面我们代码实现了就知道了。

单链表的实现

// 1、无头+单向+非循环链表增删查改实现
typedef int SLTDateType;
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入?
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置?
void SListEraseAfter(SListNode* pos);

接口实现:

新节点申请:

// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x) {
	SListNode* newnode =(SListNode*)malloc(sizeof(SListNode));
	if (newnode == NULL) {
		cout << "malloc file" << endl;
		exit(-1);

	}
	newnode->data = x;
	newnode->next = NULL;

	return newnode;


}

单链表打印

// 单链表打印
void SListPrint(SListNode* plist) {
	assert(plist);
	SListNode* cur = plist;
	while (cur!=NULL) {
		cout << cur->data << " ->";
		cur = cur->next;
	}
	cout << "NULL" << endl;
}

单链表的头尾插

/ 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x) {
	if (*pplist == NULL) {//空链表		
		SListNode* newnode = BuySListNode(x);
		*pplist = newnode;

	}
	else {
		SListNode* cur = *pplist;
		while (cur->next != NULL) {

			cur = cur->next;
		}
		SListNode* newnode = BuySListNode(x);
		cur->next =newnode;
	}

}
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x) {
	if (*pplist == NULL) {//空链表		
		SListNode* newnode = BuySListNode(x);
		*pplist = newnode;

	}
	else {
		
		SListNode* newnode = BuySListNode(x);
		newnode->next = *pplist;
		*pplist=newnode;
		
	
	}
}

单链表的头尾删

// 单链表的尾删
void SListPopBack(SListNode** pplist) {
	assert(pplist);//值是否传错了
	assert(*pplist);//是否还在调用该函数
	if ((*pplist)->next == NULL) {//只有一个节点的链表	
		free((*pplist));
		(*pplist)->next = NULL;
	}
	else {
		SListNode* cur = *pplist;
		while (cur->next->next) {

			cur = cur->next;
		}

		free(cur->next);
		cur->next = NULL;
	}

}
// 单链表头删
void SListPopFront(SListNode** pplist) {
	//plist一定有地址,所以pplist一定不能为空;
	assert(pplist);//值是否传错了,是否有地址
	assert(*pplist);//是否还在调用该函数
	if ((*pplist)->next == NULL) {//只有一个节点的链表	
		free((*pplist));
		(*pplist)->next = NULL;
	}
	else
	{
		SListNode* node = (*pplist)->next;
		free(*pplist);
		*pplist = node;
	}

}
// 单链

单链表的查找

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

单链表随机插入与删除

//pos前边插入
void SListInsertAfter(SListNode** pplist, SListNode* pos, SLTDateType x) {
	assert(pplist);
	//头插
	if (*pplist == pos) {
		SListPushFront(pplist, x);
	}
	else {
		SListNode* node = *pplist;
		while (node->next!=pos) {
			node = node->next;

		}
		SListNode* newnode = BuySListNode(x);
		newnode->next = pos;
		node->next = newnode;
	}
}
//删除pos节点
void SListErase(SListNode** pplist, SListNode* pos) {

	assert(pplist);
	assert(*pplist);
	assert(pos);
	if (*pplist == pos) {
		free(*pplist);
		(*pplist)->next = NULL;
	}
	else {
		SListNode* node = *pplist;
		while (node->next!= pos) {
			node = node->next;

		}
		SListNode* newnode = pos->next;
		node->next = newnode;
		free(pos);
		pos = NULL;
		

	}

}
//删除pos之后的
void SListEraseAfter(SListNode** pplist, SListNode* pos) {
	assert(pplist);
	assert(*pplist);
	assert(pos);
	
	
		SListNode* node = *pplist;
		while (node != pos) {
			node = node->next;

		}
		SListNode* newnode = pos->next->next;
		SListNode* node1 = pos->next;
		free(node1);
		node1 = NULL;
		pos->next =newnode;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自首的小偷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值