初阶数据结构(三)链表

这篇具有很好参考价值的文章主要介绍了初阶数据结构(三)链表。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

💓博主csdn个人主页:小小unicorn💓
⏩专栏分类:c++
🚚代码仓库:小小unicorn的学习足迹🚚
🌹🌹🌹关注我带你学习编程知识

前面我们讲的线性表的顺序存储结构。它是有缺点的,最大的缺点就是插入和删除时需要移动大量元素,这显然就需要耗费时间,那能不能想办法解决呢?
要解决这个问题,我们就得考虑一下导致这个问题的大致原因:
为什么当插入和制除时,就要移动大量元素?仔细分析后,发现原因就在于自元素的存储位置也具有邻居关系。它们编号是1,2,3,…,n,它们在内存中的位最的是按着的,中间没有空源,当然就无法快速插入,而删除后,当中就会留出空像,自然需要弥补。问题就出在这里

A同学思路:让当中每个元素之间都留有一个空位置,这样要插入时,就不至于动,可一个空位置如何解决多个相同位置插入数据的问题呢?所以这个想法显然不行。

B同学思路:那就让当中每个元素之间都留足够多的位置,根据实际情况制定空像大小,比如10个,这样插入时,就不需要移动了。万一10个空位用完了,再考虑移动使得每个位置之间都有10个空位置。如果删除,就直接删掉,把位置留空即可。这样似乎蓄时解决了插入和删除的移动数据问题。可这对于超过10个同位置数据的插入,效率上还是存在问题。对于数据的遍历,也会因为空位置太多而造成判断时间上的浪费。而且显然这里空间复杂度还增加了,因为每个元素之间都有若干个空位置。

C同学思路:我们反正也是要让相邻元素间留有足够余地,那干脆所有的元素都不要考虑相邻位置了,哪有空位就到哪里,而只是让每个元素知道它下一个元素的位置在哪里,这样,我们可以在第一个元素时,就知道第二个元素的位置(内存地址),而找到它:在第二个元素时,再找到第三个元素的位置(内存地址)。这样所有的元素我们就都可以通过遍历而找到。
好!大棒了,这个想法非常好!

C同学,可惜生晚了几十年,不然,c同学的想法对于数据结构来讲就是划时代的意义。我们要的就是这个思路。

1.线性表的联试存储结构

1.1线性表链式存储结构定义

在解释这个思路之前,我们先来谈另一个话题。前几年,有一本书风靡了全世界,它叫《达·芬奇密码》,成为世界上最畅销的小说之一,书的内容集合了侦探、惊使和阴谋论等多种风格,很好看。这本书和绝大部分负小说一样,都是同一种处理办法。那就是,作者不会让你事先知道整个过程的全部,而是在一步一步地到这某个环节,才根据现场的信息,获得或推断出下一步是什么,也就是说,每一步除了对你侦破的信息进一步确认外(之前信息也不一定都是对的,有时是证明某个信息不正确),还有就是对下一步如何操作或行动的指引。

不过,这个例子也不完全与线性表相符合,因为案件侦破的线案可能是错综复杂的,有点像我们之后要讲到的树和图的数据结构。今天,我们要讲的是单线索,无分支的情况。即线性表的链式存储结构。

线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意 味着,这些数据元素可以存在内存未被占用的任意位置
(如下图所示)。
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

以前在顺序结构中,每个数据元素只需要存储数据 元素信息就可以了。现在链式结构中,除了要存储数据 元素信息外,还要存储它的后继元素的存储地址。

因此,为了表示每个数据元素ai与其直接后继数据 元素ai+1(i是下标)之间的逻辑关系,对数据元素ai来说,除了存储 其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称作指针。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。

n个结点(a的存储映像)链结成一个链表,即为线性表(a,ay·,a)的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表。单链表正是通过每个结点的指针域将线性表的数据元素按其逻辑次序链接在一起。
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

对于线性表来说,总得有个头有个尾,链表也不例外。我们把链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行了。之后的每一个结点,其实就是上一个的后继指针指向的位置。想象一下,最后一个结点,它的指针指向哪里?

最后一个,当然就意味着直接后继不存在了,所以我们规定,线性链表的最后一个结点指针为“空”(通常用NULL或“^”符号表示,如下图所示)。
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

有时,我们为了更加方便地对链表进行操作,会在单链表的第一个结点前附设一个结点,称为头结点。头结点的数据域可以不存储任何信息,谁叫它是第一个呢,有这个特权。也可以存储如线性表的长度等附加信息,头结点的指针域存储指向第一个结点的指针,如下图所示。
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

1.2头指针与头结点的异同

头指针与头结点的异同点,如下图所示:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

1.3线性表链式存储结构代码描述

若线性表为空,则头结点的指针域为“空”,如下图所示:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

这里我们大概用图示表达了内存中单链表的存储状态。看着满图的省略号“…”,就知道是有多么不方便。而我们真正关心的它在内存中的实际位置吗?不是的。这只是它所表示的线性表中的数据元素及数据元素之间色逻辑关系。所以我们改用更方便的存储示意图来表示单链表,如下图所示:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

若带有头结点的单链表,则如下图所示:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

空链表如下图所示:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

单链表中,我们在c语言中可用结构指针来描述:

//线性表的单链表的存储结构:
typedef struct Node
{
  ElemType data;
  struct Node*next;
}Node;
typedef struct Node*LinkList;//定义linkList

从这个结构定义中,我们也就知道,结点由存放数据元素的数据域和存放后继结点地址的指针域组成。假设p是指向线性表第i个元素的指针,则该结点ai 的数据域我们可以用p->data来表示,p->data的值是一个数据元素,结点ai的指针域可以用p->next来表示,p->next的值是一个指针。p->next指向谁呢?当然是指向第i+1个元素,即指向ai+l的指针。也就是说,如果p->data等于a,那么p>next->data等于ai+1(如下图所示)。初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

2.单链表的具体实现:

2.1开辟节点

首先创建一个新项目,分为三个模块:SList.c用来实现接口函数;SList.h用来结构体创建与函数声明;test.c则用来进行测试我们的接口函数。
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

创建节点如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

2.2遍历链表以及开辟新节点

咱们首先用一个cur来存放头结点的地址;

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

那后面节点的数据怎么访问呢?咱们可以让cur->next赋给cur;

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

依次内推;当cur为空时;说明已经访问结束。 最后打印即可。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

为方便测试我们可以先写一个交互性的链表测试:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

写交互性测试的时候,会涉及到开辟新节点,这里我们可以抽离一个函数来专门进行开辟新节点。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
测试结果如下:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.接口函数的实现(增删查改)

3.1尾插

那么如何实现尾插呢?尾插我们首先得先找到尾。
那么如何找呢?

先看下面这个代码。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
如果要是这样找尾的话,就会出现一个问题。我们画图分析一下。

这个代码是不是首先有三个指针变量 plist tail newnode;

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言随着代码运行,最后taill的地址为空,假设新节点的地址为0x0012ff00,那节点newnode存放的地址也就是0x0012ff00,最后呢,又把newnode的地址给了taill,看起来没问题,但有没有想过,这三个指针变量出了作用域呢?
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
出了作用域,这三个指针变量是不是都销毁了,这不仅造成了内存泄漏还没有吧链表链接起来。基于这个问题,我们在回过来思考这个问题,如何找尾?

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
所以我们的尾用taii找的时候,条件不是null结束,而是存放null前一个的地址。

继续思考一下,我们写完了吗?那如果本身就是个空链表呢?也就是说空链表传过来的时候。第一次尾插怎么插呢?看下面这个代码。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
这个代码就会有一个明显的错误,插入不进去。为什么会这样呢?
phead=newnode这一步,这一步是把0x0012ffcc给了phead,出了作用域,phead,newnode****销毁,那么显然我们的plist的地址并没有发生任何变化,所以插入不进去。

这就是典型的形参与实参之间的区别,形参只是实参的一份临时拷贝。那么怎们样才能改变呢,那就需要传地址了。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
经过以上的不断修改,最终尾插的接口函数完整代码如下:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

测试结果如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

总结一下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.2头插

有了尾插的思想,头插就简单了。
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
实质也就是修改plist,所以还是传值还是用二级指针。

完整代码如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

测试结果如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.3尾删

如果是空链表,我们可以直接使用断言。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

一个节点直接释放掉plist.两个节点以上就首先需要找尾,先看下面这个代码。(**pphead就是plist)

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

上面这个代码找到尾后,直接把taill置空,肯定不行

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

free(taill)的本质是把tail指向的节点给free了,再把taill置空。出了作用域,taill销毁,那他前一个还是空。所以还需要找到taill的前一个。

以下两种解决办法都可以。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
最终完整代码如下:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

测试结果如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

删除6个。
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.4头删

同理,头删与尾删大同小异,头删实现更简单。
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

测试结果如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.5查找

查找实质还是遍历链表:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.6在pos位置之前插入x

pos是任意一个节点,防止为空呢,我们先检查一下:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

那他还有什么特殊情况呢,头插,尾插就是其中两种,其次处理pos在中间位置。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

完整代码如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

测试结果如下:在给定数字前面插它的十倍

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.7在pos位置以后插入x

要是后插就会便捷很多。因为他不可能实现头插,所以就会很简单。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

如果是第一个代码:测试结果如下:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
进入了死循环。

修改后完整代码如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

测试结果如下:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.8删除pos位置

删除部分就简单了。分情况,头删首先需要单独处理,其次尾删是不需要单独处理的,因为正常删就已经包含尾删情况了。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

完整代码如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

测试结果如下:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

3.9删除pos的后一个位置

删后一个考虑的就是要找到前一个,处理好这个就简单了。其次有个坑,它删不了头。

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

完整代码:
初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言

4.单链表结构与顺序存储结构的优缺点

简单地对单链表结构和顺序存储结构做对比:

初阶数据结构(三)链表,c++,c语言,数据结构,链表,c语言
通过上面的对比,我们可以得出一些经验性的结论:

1.若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。若需要频繁插入和删除时,宜采用单链表结构。比如说游戏开发中,对于用户注册的个人信息,除了注册时插入数据外,绝大多数情况都是读取,所以应该考虑用顺序存储结构。而游戏中的玩家的武器或者装备列表,随着玩家的游戏过程中,可能会随时增加或删除,此时再用顺序存储就不太合适了,单链表结构就可以大展拳脚。当然,这只是简单的类比,现实中的软件开发,要考虑的问题会复杂得多。

2.当线性表中的元素个数变化较大或者根本不知道有多大时,最好用单链表给构。这样可以不需要考虑存储空间的大小问题。而如果事先知道线性表的大致长度,比如一年12个月,一周就是星期一至星期日共七天,这种用顺序存储结构效率会高很多。

总之,线性表的顺序存储结构和单链表结构各有其优缺点,不能简单地说哪个好,哪个不好,需要根据实际情况,来综合平衡采用哪种数据结构更能满足和达到需求和性能。文章来源地址https://www.toymoban.com/news/detail-704917.html

5.链表完整代码:

5.1 SList.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

void SLTPrint(SLTNode* phead);
SLTNode* BuySListNode(SLTDataType x);

//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//尾删
void SLTPopBack(SLTNode** pphead);
//头删
void SLTPopFront(SLTNode** pphead);
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
//在pos位置之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在pos位置以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos);
//删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos);

5.2 SList.c

#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"

//打印函数
void SLTPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	//while (cur != NULL)
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

//开辟新节点
SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

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

	return newnode;
}


//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuySListNode(x);
	if (*pphead == NULL)
	{
		//改变的结构体的指针
		*pphead = newnode;
	}
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}

		//改变的结构体
		tail->next = newnode;
	}
}


//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

//尾删
void SLTPopBack(SLTNode** pphead)
{

	//空
	assert(*pphead);
	//一个节点
	//一个以上节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next->next)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;


		/*SLTNode* tailprev = NULL;
		SLTNode* tail = *pphead;
		while (tail->next)
		{
			tailprev = tail;
			tail = tail->next;
		}

		free(tail);
		tail = NULL;
		tailprev->next = NULL;*/
	}
}

//头删
void SLTPopFront(SLTNode** pphead)
{

	//空
	assert(*pphead);

	//非空
	SLTNode* newnode = (*pphead)->next;
	free(*pphead);
	*pphead = newnode;
}

//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;

}


//在pos位置之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);

	if (pos == *pphead)
	{
		SLTPushFront(pphead, x);

	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}

		SLTNode* newnode = BuySListNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}

//在pos位置以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);

	SLTNode* newnode = BuySListNode(x);
	/*pos->next = newnode;*/
	newnode->next = pos->next;
	pos->next = newnode;
}

//删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);

	if (pos == *pphead)
	{
		SLTPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		//pos = NULL;
	}
}

//删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos);

	//检查Pos是否为尾节点
	assert(pos->next);

	SLTNode* posNext = pos->next;

	pos->next = posNext = posNext->next;

	free(posNext);

	posNext = NULL;
}

5.3 Test.c

#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"

//交互链表测试
void TestSList1()
{
	int n;
	printf("请输入链表的长度:\n");
	scanf("%d", &n);
	printf("请依次输入每个节点的值:\n");
	SLTNode* plist = NULL;
	for (size_t i = 0; i < n; i++)
	{
		int val;
		scanf("%d", &val);
		SLTNode* newnode = BuySListNode(val);

		//头插
		newnode->next = plist;
		plist = newnode;
	}
	SLTPrint(plist);

}



//测试尾插头插
void TestSList2()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);


	SLTPushFront(&plist, 10);
	SLTPushFront(&plist, 20);
	SLTPushFront(&plist, 30);
	SLTPushFront(&plist, 40);
	SLTPrint(plist);

}

//测试尾删
void TestSList3()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);

	SLTPopBack(&plist);
	SLTPrint(plist);


	SLTPopBack(&plist);
	SLTPrint(plist);


	SLTPopBack(&plist);
	SLTPrint(plist);

	SLTPopBack(&plist);
	SLTPrint(plist);

	SLTPopBack(&plist);
	SLTPrint(plist);

	/*SLTPopBack(&plist);
	SLTPrint(plist);*/

}

//测试头删
void TestSList4()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);


	SLTPopFront(&plist);
	SLTPrint(plist);

	SLTPopFront(&plist);
	SLTPrint(plist);

	SLTPopFront(&plist);
	SLTPrint(plist);

	SLTPopFront(&plist);
	SLTPrint(plist);

	SLTPopFront(&plist);
	SLTPrint(plist);

	/*SLTPopFromt(&plist);
	SLTPrint(plist);*/
}

void TestSList5()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);


	SLTNode* pos = SLTFind(plist, 40);
	if (pos)
	{
		pos->data *= 10;
	}
	SLTPrint(plist);

	int x;
	scanf("%d", &x);
	pos = SLTFind(plist, x);
	if (pos)
	{
		SLTInsert(&plist, pos, x * 10);

	}
	SLTPrint(plist);

}


void TestSList6()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);

	int x;
	scanf("%d", &x);
	SLTNode* pos = SLTFind(plist, x);
	if (pos)
	{
		SLTErase(&plist, pos);
	}
	SLTPrint(plist);
}



void TestSList7()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);

	int x;
	scanf("%d", &x);
	SLTNode* pos = SLTFind(plist, x);
	if (pos)
	{
		SLTEraseAfter(pos);
		pos = NULL;
	}
	SLTPrint(plist);


	//SLTPopFront(&plist);
	//SLTPrint(plist);


	//SLTPopFront(&plist);
	//SLTPrint(plist);


	//SLTPopFront(&plist);
	//SLTPrint(plist);

	//SLTPopFront(&plist);
	//SLTPrint(plist);

}

int main()
{

	TestSList7();
}

到了这里,关于初阶数据结构(三)链表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 初阶数据结构:链表

    经过学习与练习,已经掌握了顺序表的相关知识并且能够自我实现。在这一过程中,通过对其结构的实现,发现顺序表的尾部插入删除数据效率很高,可是,在 头部与随机插入的场景下效率低下 而且 存在扩容消耗 等一些问题。而有这样一种数据结构可以很好的解决顺序表存

    2024年01月20日
    浏览(49)
  • 初阶数据结构(三)链表

    💓博主csdn个人主页:小小unicorn💓 ⏩专栏分类:c++ 🚚代码仓库:小小unicorn的学习足迹🚚 🌹🌹🌹关注我带你学习编程知识 前面我们讲的线性表的 顺序存储结构 。它是有缺点的,最大的缺点就是插入和删除时需要移动大量元素,这显然就需要 耗费时间 ,那能不能想办法

    2024年02月09日
    浏览(57)
  • 【数据结构初阶】链表OJ

    OJ 方案一: 题目解析: 方案二: 题目解析:把原链表遍历一遍,插入新链表 OJ 题目解析: OJ 题目解析: OJ 题目解析: OJ 题目解析: OJ 题目解析: OJ 题目解析: OJ 题目解析: 定义快慢指针,使快指针先走与慢指针同步。然后同时走看是否相交 OJ 题目解析: OJ 题目解析:

    2024年02月05日
    浏览(47)
  • 【数据结构初阶】第四节.链表详讲

    前言 一、单链表的概念 二、链表的创建 2.1链表的初始化 2.2 打印链表 2.3 获取链表的长度 2.4 判断链表是否为空 三、新增结点 3.1头插 3.2 指定下标插入 四、删除结点 4.1 头删 4.2 指定下标的删除 4.3 删除链表中的指定元素 五、单链表查找 六、附录 总代码 测试代码 总结 前

    2023年04月15日
    浏览(69)
  • 【数据结构初阶】顺序表和链表(1)

    线性表(linear list) 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上

    2024年02月08日
    浏览(194)
  • 『初阶数据结构 • C语言』① - 数据结构为何重要

    本文内容借鉴一本我非常喜欢的书——《数据结构与算法图解》。学习之余,我决定把这本书精彩的部分摘录出来与大家分享。 数组是计算机科学中最基本的数据结构之一。如果你用过数组,那么应该知道它就是一个含有 数据的列表。它有多种用途,适用于各种场景,下面

    2024年02月16日
    浏览(45)
  • C语言完整版笔记(初阶,进阶,深刨,初阶数据结构)

    1.初阶: 1.1C语言初阶易忘知识点速记 2.进阶:  1.2C语言进阶易忘点速记 3.深剖: 2.1C语言重点解剖要点速记 2.2C语言重点解剖操作符要点速记   2.3C语言重点解剖预处理要点速记 2.4C语言重点解剖指针和数组要点速记 2.5C语言重点解剖内存管理函数要点速记 4.数据结构:

    2024年02月16日
    浏览(36)
  • 数据结构初阶(用C语言实现简单数据结构)--栈和队列

    ✨✨欢迎来到T_X_Parallel的博客!!       🛰️博客主页:T_X_Parallel       🛰️专栏 : 数据结构初阶       🛰️欢迎关注:👍点赞🙌收藏✍️留言 这小猫真好看 言归正传,通过上篇有关顺序表和链表的博客,可以了解到线性表的一些大致特征,这篇博

    2024年02月08日
    浏览(40)
  • 【数据结构初阶】之堆(C语言实现)

    前言 :在二叉树基础篇我们提到了二叉树的顺序实现,今天让我们来学习一下特殊的二叉树———堆的相关知识。 📃 博客主页: 小镇敲码人 💞 热门专栏:数据结构与算法 🚀 欢迎关注:👍点赞 👂🏽留言 😍收藏 🌏 任尔江湖满血骨,我自踏雪寻梅香。 万千浮云遮碧月

    2024年04月09日
    浏览(80)
  • 『初阶数据结构 • C语言』④ - 冒泡排序

      本文内容借鉴一本我非常喜欢的书——《数据结构与算法图解》。学习之余,我决定把这本书精彩的部分摘录出来与大家分享。      本章内容 写在前面 1.冒泡排序 2.冒泡排序实战 3.冒泡排序的实现 4.冒泡排序的效率 5.二次问题 6.线性解决 7.总结     大 O记法能客观地衡量

    2024年02月16日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包