当前位置: 首页 > news >正文

广州网站建设360元中国新闻网

广州网站建设360元,中国新闻网,网站seo诊断工具,婚庆类的模板网站全文目录引言链表链表的定义与结构链表的分类单链表的实现及对数据的操作单链表的创建与销毁创建销毁单链表的打印单链表的头插与头删头插头删单链表的尾插与尾删尾插尾删单链表的查找单链表在pos位置后插入/删除插入删除单链表在pos位置插入/删除插入删除总结引言 在上一篇文…

全文目录

  • 引言
  • 链表
    • 链表的定义与结构
    • 链表的分类
  • 单链表的实现及对数据的操作
    • 单链表的创建与销毁
      • 创建
      • 销毁
    • 单链表的打印
    • 单链表的头插与头删
      • 头插
      • 头删
    • 单链表的尾插与尾删
      • 尾插
      • 尾删
    • 单链表的查找
    • 单链表在pos位置后插入/删除
      • 插入
      • 删除
    • 单链表在pos位置插入/删除
      • 插入
      • 删除
  • 总结

引言

在上一篇文章中,我们了解了顺序表的相关知识,并且实现了用顺序表管理数据。

但在这过程中,我们发现了使用顺序表管理数据时,其实是存在一些不方便的:
比如当存储空间已经被扩容的时候,删除了许多的数据,就会导致大片的内存浪费;
比如当我们需要扩容时,可能会异地扩容,这个过程会比较影响效率;
再比如当我们需要在顺序表前面插入数据时,过程会比较麻烦。

相对于顺序表,同属线性表的链表在这些方面就有着比较好的表现。

链表也有许多不同的种类:单向或双向链表、带头或不带头的链表、循环或非循环的链表等。在接下来的几篇篇文章中就会详细介绍链表的相关知识:

链表

链表的定义与结构

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

也就是说,链表是逻辑上连续,但存储结构上不连续的线性结构。我们可以通过指针访问到链表中的下一个元素。所以,在一个链表的结点中,应该至少包含两个元素:当前结点的数据与指向下一个结点的指针。

这就需要我们用到结构体的知识:我们在学习结构体时介绍过结构体的自引用,即结构体中的一个成员类型是结构体指针。即,我们可以将链表结点的类型定义为(当然,这是最简单的形式,只能依次访问链表的元素):

typedef int SLTDateType;typedef struct SListNode
{SLTDateType data;struct SListNode* next;
}SListNode;

链表的分类

链表有许多的类型:带头与不带头、循环与非循环、单向与双向:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当然,这些种类之间有许多的组合方式,根据需要,可以定义各种各样的链表。

其中,最为简单的就是无头单向非循环链表,这也是此篇文章介绍的重点:

单链表的实现及对数据的操作

对于单链表结点的结构,与上面我们介绍的栗子相同,就是最为简单的类型:
包括当前结点的数据与指向下一个节点的结构体指针:

typedef int SLTDateType;typedef struct SListNode
{SLTDateType data;struct SListNode* next;
}SListNode;

与学习顺序表时类似,我们可以实现一下用单链表来管理数据。同样的,这些功能的实现都将封装为函数:

在这之前,我们首先需要定义一个结构体指针plist,用于访问单链表的第一个结点。这个指针被初始化为NULL:

SListNode* plist = NULL;

单链表的创建与销毁

创建

在开辟顺序表的空间时,我们可以直接动态申请一块连续的空间来存放一些数据。但是对于单链表而言,它在物理空间上不是连续的。所以当我们为单链表开辟空间时,就需要一个结点一个结点分别开辟空间。

首先我们需要一块大小为结构体大小的空间,这块空间可以动态开辟:

SListNode* plist = (SListNode*)malloc(sizeof(SListNode));

在开辟某一个空间后,我们需要将这块空间初始化:将该结点的data成员初始化为想要存储的数据(这个数据可以作为参数传给函数),然后将这个结点的next成员初始化为NULL。

最后,返回已经成功创建的结点的结构体指针:

// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x)
{SListNode* plist = (SListNode*)malloc(sizeof(SListNode));if (plist == NULL){perror("malloc");return NULL;}plist->data = x;plist->next = NULL;return plist;
}

单链表的结点是动态开辟的,当然需要将这些空间依次释放掉,以免出现内存泄漏的问题。

销毁

当依次销毁单链表的每一个节点时,我们需要两个指针变量cur与aftercur。通过这两个指针变量,aftercur可以在cur被销毁前记录cur->next的值,从而实现在销毁cur指向的空间后,可以通过aftercur访问到下一个空间而继续进行销毁操作。
依次循环,当cur为NULL时终止,实现销毁每一个结点:
在这里插入图片描述

// 单链表的销毁
void SListDestroy(SListNode* plist)
{SListNode* cur = plist;SListNode* aftercur = cur->next;while (cur){aftercur = cur->next;free(cur);cur = aftercur;}
}

单链表的打印

打印单链表时, 我们只需要遍历单链表,并逐个打印每个结点的data成员即可。

需要注意的是,我们在遍历时,条件必须为cur,而不是cur->next。因为当cur->next为NULL时,cur是最后一个结点。此时,最后一个结点不进入循环,该结点的数据也不会被打印:

// 单链表打印
void SListPrint(SListNode* plist)
{SListNode* cur = plist;while (cur){printf("%d ", cur->data);cur = cur->next;}
}

单链表的头插与头删

头插

在顺序表中,想要从顺序表的前面插入数据是比较麻烦的,这需要将顺序表中的元素整体向后移动一个元素,而获得存放新与元素的空间;

但是在单链表中,头插的实现就比较简单,只需要将新创建的结点接入到单链表的前面即可。我们可以通过让新结点的next成员指向原plist,plist的值指向新结点的方式来实现:
在这里插入图片描述
需要注意的是:
在头插时,是需要改变结构体指针plist的值的,所以我们在传入该结构体指针时,需要传该结构体指针的地址,即二级指针。这样,才能实现将plist的值真正的改变:

当然,当单链表中没有元素时,即plist为NULL时,只需要改变plist的值即可。

void SListPushFront(SListNode** pplist, SLTDateType x)
{SListNode* newnode = BuySListNode(x);if (*pplist == NULL){*pplist = newnode;}else{newnode->next = *pplist;*pplist = newnode;}
}

头删

在顺序表中实现从前面删除也比较麻烦,需要将顺序表中的元素整体向前移动一个数据;

而单链表中只需要使plist指针指向链表中第一个结点的next成员即可。我们可以通过用一个结构体指针cur来记录plist的值,当plist指向下一个结点后,再释放cur指向的空间,即原第一个结点的空间:
在这里插入图片描述

同样的,由于我们需要改变结构体指针plist的值,就需要传plist的地址,即二级指针。

当然,当plist为空指针时,当然是不能再删除的,所以我们可以assert断言一下。

void SListPopFront(SListNode** pplist)
{assert(*pplist);SListNode* cur = *pplist;*pplist = cur->next;free(cur);cur = NULL;
}

单链表的尾插与尾删

尾插

单链表需要在末尾插入数据时,首先需要找到单链表末尾的位置,然后将单链表最后一个结点的next成员改为新结点的地址即可。
在这里插入图片描述
在找最后一个元素时,我们可以通过cur指针向后移动,直到cur指向的结构体的next成员为NULL时,即cur指向的结点就是单链表的最后一个结点:
在这里插入图片描述
当然,当单链表中没有元素时,即plist为NULL时,只需要改变plist的值即可。
同样的,由于我们需要改变结构体指针plist的值,就需要传plist的地址,即二级指针。

// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{SListNode* newnode = BuySListNode(x);if (*pplist == NULL){*pplist = newnode;}else{SListNode* cur = *pplist;while (cur->next){cur = cur->next;}cur->next = newnode;}
}

尾删

单链表删除末尾的数据时,同样的,我们需要找到单链表末尾的位置。

然后将单链表中倒数第二个结点的next成员改为NULL,然后释放cur(最后一个结点的指针)指向的空间。
我们可以通过创建一个beforecur变量来存储cur前一个结点的地址,这样,就可以实现当cur指向最后一个元素时,beforecur为倒数第二个元素:
在这里插入图片描述
当单链表中只有一个元素时,cur->next的值本身就是NULL。此时只需要释放cur指向的空间(第一个结点),然后将plist的值改为NULL即可。

同样的,由于我们需要改变结构体指针plist的值,就需要传plist的地址,即二级指针。
当然,当plist为空指针时,当然是不能再删除的,所以我们可以assert断言一下。

// 单链表的尾删
void SListPopBack(SListNode** pplist)
{assert(*pplist);SListNode* cur = *pplist;SListNode* beforecur = NULL;while (cur->next){beforecur = cur;cur = cur->next;}if (beforecur==NULL){free(*pplist);*pplist = NULL;}else{free(beforecur->next);beforecur->next = NULL;}
}

单链表的查找

之后,我们就会想到要删除单链表中指定的结点。
在删除指定的结点之前,我们首先需要实现一个算法,通过结点中的data成员找到这个节点的位置。并返回这个节点的指针。

遍历单链表,只需要将结构体指针cur依次后移即可。当cur->data的值为x时,返回cur。

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

单链表在pos位置后插入/删除

在获取到了pos后,我们就会想要实现在pos位置进行插入或删除:

插入

在插入时,我们很容易想到将新节点newnode->next的值改为pos->next,然后将pos->next的值改为newnode。从而实现将pos位置插入数据:
在这里插入图片描述
显然,这样的算法只能实现在pos后增加结点,想要在pos位置增加结点,这样的条件显然是不足的。

所以我们就先来实现一下在pos后增加数据:

// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x)
{SListNode* newnode = BuySListNode(x);newnode->next = pos->next;pos->next = newnode;
}

删除

在实现删除pos位置的结点时,我们会想到将pos->next的值改为pos->next->next位置的值,然后再释放pos后面的一块空间。
我们可以使用一个afterpos指针来暂存pos->next的值,以方便释放空间:
在这里插入图片描述
同样的,我们发现,这样删除只能释放pos后的一块空间。想要删除pos位置的结点,这样的条件显然是不足的。

但我们可以先实现一下这个函数:

// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos)
{SListNode* afterpos = pos->next;pos->next = afterpos->next;free(afterpos);afterpos = NULL;
}

单链表在pos位置插入/删除

要想在pos位置插入结点,或删除pos位置的结点,我们需要获取到pos结点前面的结点的指针,然后改变pos前面结点中的next成员,由此实现对pos位置数据的操作。

所以在传参的时候,我们需要将单链表第一个结点的地址传给函数,将第一个结点的地址向后遍历得到pos前一个结点的地址后,再进行操作。

我们可以定义一个beforepos指针:

在这里插入图片描述

插入

在获取到beforepos后,我们就可以重复上面的操作来实现在pos位置添加一个新结点:将新节点newnode->next的值改为beforepos->next,然后将beforepos->next的值改为newnode。从而实现在pos位置插入数据:
在这里插入图片描述
但是,在pos位置插入时是有特例的,即pos为单链表的第一个元素时,需要将plist的值改为plist,再将newnode->next的值改为pos即可:
在这里插入图片描述

// 单链表在pos位置插入x
void SListInsert(SListNode** pplist, SListNode* pos, SLTDateType x)
{SListNode* newnode = BuySListNode(x);SListNode* beforepos = *pplist;if (beforepos == pos){*pplist = newnode;newnode->next = pos;}else{while (beforepos->next){if (beforepos->next == pos){beforepos->next = newnode;newnode->next = pos;break;}beforepos = beforepos->next;}}
}

删除

当我们得到pos前的结点的地址后,就可以通过相同的方式实现删除pos位置的值:将beforepos->next的值改为beforepos->next位置的值,然后再释放pos后面的一块空间:
在这里插入图片描述

但是,有一种特例,即pos指向的是单链表的第一个元素时,我们只需要将plist的值改为pos->next;再将pos指向的空间释放即可:
在这里插入图片描述

// 单链表删除pos位置的值
void SListErase(SListNode** pplist, SListNode* pos)
{SListNode* beforepos = *pplist;if (beforepos == pos){*pplist = pos->next;free(pos);pos = NULL;}else{while (beforepos->next){if (beforepos->next == pos){beforepos->next = pos->next;free(pos);pos = NULL;break;}beforepos = beforepos->next;}}
}

总结

到此,关于单链表的相关知识就介绍完毕了。当然,单链表是最简单的一种链表类型,在后面我们还会介绍一种比较复杂的链表,即带头双向循环链表。
当然,在介绍带头双向循环链表之前,我会先用一篇文章来讲解一些单链表的题目,欢迎大家持续关注哦

如果大家认为我对某一部分没有介绍清楚或者某一部分出了问题,欢迎大家在评论区提出

如果本文对你有帮助,希望一键三连哦

希望与大家共同进步哦


文章转载自:
http://umbra.rqjL.cn
http://benzal.rqjL.cn
http://sweetheart.rqjL.cn
http://tradevman.rqjL.cn
http://obeisance.rqjL.cn
http://survivor.rqjL.cn
http://panier.rqjL.cn
http://hershey.rqjL.cn
http://heteroscedasticity.rqjL.cn
http://metrazol.rqjL.cn
http://metonym.rqjL.cn
http://portfolio.rqjL.cn
http://honeyfogle.rqjL.cn
http://frascati.rqjL.cn
http://countermissile.rqjL.cn
http://demargarinated.rqjL.cn
http://insalutary.rqjL.cn
http://kroll.rqjL.cn
http://omphale.rqjL.cn
http://salpingian.rqjL.cn
http://westabout.rqjL.cn
http://bawdry.rqjL.cn
http://pyroligneous.rqjL.cn
http://astraea.rqjL.cn
http://ferret.rqjL.cn
http://cine.rqjL.cn
http://clampdown.rqjL.cn
http://kilchoanite.rqjL.cn
http://ventrodorsal.rqjL.cn
http://coachman.rqjL.cn
http://interlard.rqjL.cn
http://ruminator.rqjL.cn
http://chromatogram.rqjL.cn
http://undivorced.rqjL.cn
http://isooctane.rqjL.cn
http://falloff.rqjL.cn
http://commerce.rqjL.cn
http://televise.rqjL.cn
http://vitrification.rqjL.cn
http://demisable.rqjL.cn
http://intercommunal.rqjL.cn
http://turtlehead.rqjL.cn
http://adenitis.rqjL.cn
http://landzone.rqjL.cn
http://groan.rqjL.cn
http://applaud.rqjL.cn
http://short.rqjL.cn
http://polygamy.rqjL.cn
http://mediative.rqjL.cn
http://pommel.rqjL.cn
http://termite.rqjL.cn
http://maladept.rqjL.cn
http://rylean.rqjL.cn
http://tranquility.rqjL.cn
http://honeybunch.rqjL.cn
http://tricolored.rqjL.cn
http://trustworthily.rqjL.cn
http://thornbush.rqjL.cn
http://reluctancy.rqjL.cn
http://hypothetic.rqjL.cn
http://proteolysis.rqjL.cn
http://harebell.rqjL.cn
http://frondage.rqjL.cn
http://outwell.rqjL.cn
http://recrescence.rqjL.cn
http://privateersman.rqjL.cn
http://cinquefoil.rqjL.cn
http://putschism.rqjL.cn
http://skinful.rqjL.cn
http://freshness.rqjL.cn
http://didynamous.rqjL.cn
http://reprehensible.rqjL.cn
http://proteoglycan.rqjL.cn
http://microcamera.rqjL.cn
http://maist.rqjL.cn
http://msbc.rqjL.cn
http://cytomegalic.rqjL.cn
http://signed.rqjL.cn
http://timework.rqjL.cn
http://multifactor.rqjL.cn
http://bleat.rqjL.cn
http://affirmance.rqjL.cn
http://medication.rqjL.cn
http://vacuole.rqjL.cn
http://supergravity.rqjL.cn
http://esop.rqjL.cn
http://evilness.rqjL.cn
http://sable.rqjL.cn
http://amorphous.rqjL.cn
http://chasid.rqjL.cn
http://entocondyle.rqjL.cn
http://debouch.rqjL.cn
http://wrong.rqjL.cn
http://borsch.rqjL.cn
http://tribulation.rqjL.cn
http://ebracteate.rqjL.cn
http://horsebean.rqjL.cn
http://confidant.rqjL.cn
http://record.rqjL.cn
http://nervine.rqjL.cn
http://www.dt0577.cn/news/127050.html

相关文章:

  • wordpress怎么编辑网站快速seo关键词优化技巧
  • 直接做海报的网站seo网站推广费用
  • 互联网提供的服务主要有哪些seo顾问什么职位
  • 做网站在哪里租服务器武汉seo公司出 名
  • 网站仿站大多少钱现在疫情怎么样了最新消息
  • 网站色调代号推广普通话宣传周活动方案
  • 汽车配件响应式网站网推放单平台
  • 世界三大咨询公司seo管理系统创作
  • 小说网站怎么做推广网络营销的现状
  • 成都 网站建设阿里云域名注册入口
  • 基于webform的网站开发品牌推广百度seo
  • 用.net core 做网站赣州seo外包
  • 做的网站门户网站有哪些
  • 机械毕业论文代做网站专业网站建设公司首选
  • 哪些网站可以做行程营销型企业网站的功能
  • 做歌厅广告在哪个网站做好广州疫情最新消息今天封城了
  • 做电商网站需要的证百度联盟官网
  • 网络建设公司有哪些福州seo推广优化
  • 视频网站发展好应该怎么做百度seo正规优化
  • 网站建设沟通搜索热度和搜索人气
  • 天台网站建设免费影视软件靠什么赚钱
  • 东莞网站建设网站推广价钱google seo 优化教程
  • 基础微网站开发代理商市场调研报告模板ppt
  • 做家教去哪个网站办公软件培训
  • 西安网站建设xamokj郑州计算机培训机构哪个最好
  • 建网站网络推广优势公司网站如何seo
  • 网站源码怎么做网站seo云优化外包
  • 网站制作教程谁的好日喀则网站seo
  • 内蒙古做网站找谁杭州网站建设网页制作
  • 做返利网站能赚钱么广东省人大常委会