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

网站制作添加视频最受欢迎的十大培训课程

网站制作添加视频,最受欢迎的十大培训课程,网站可信度,云南省建设工程信息网官网前言 hello,大家好呀,我是Humble,本篇博客承接之前的C语言进阶——数据结构之链表 的内容(没看过的小伙伴可以从我创建的专栏C语言进阶之数据结构 找到那篇文章并阅读后在回来哦~),上次我们重点说了链表中…

前言

hello,大家好呀,我是Humble,本篇博客承接之前的C语言进阶——数据结构之链表

的内容(没看过的小伙伴可以从我创建的专栏C语言进阶之数据结构 找到那篇文章并阅读后在回来哦~),上次我们重点说了链表中的单链表,即不带头单向不循环链表

还说到了链表的分类虽然有8种,但实际上最常用的还是单链表和双向链表(带头双向循环链表)

所以今天我们就来讲讲双向链表的实现吧~

双向链表的结构

下面是双向链表的一个图示:

双向链表,全称为带头双向循环链表

双向与循环这2个概念很好理解,所以我们下面看一下什么是带头

这个“带头”跟之前我们说的“头节点”是两个概念,

实际前面在说单链表时有称呼并不严谨,但是为了大家更好的理解就直接称为单链表的头节点

 带头链表里的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这里“放哨 的

哨兵位”存在的意义: 遍历循环链表避免死循环

对于双向链表的节点,我们这样定义:
 

typedef int LTDataType;
typedef struct ListNode 
{
    LTDataType data;
    struct ListNode* next; //指针保存下一个节点的地址
    struct ListNode* prev; //指针保存前一个节点的地址
    
}LTNode;

双向链表的实现

下面我们来实现一下双向链表的各个功能

其实当我们掌握了单链表的各个操作后,我们会发现其实双向链表虽然在结构上看着比单链表复杂不少,但在实现上并不难~

我们首先在VS上创建一个List的工程,再分别创建List.h头文件,List.c源文件以及Test.c测试文件,在这之上,我们依次去实现双向链表的各个功能~

初始化 LTInit

首先是初始化,因为双向链表多了一个头节点,即哨兵位,所以我们需要对其初始化~

代码如下:

LTNode* LTInit() //对哨兵位初始化~
{LTNode* phead = (LTNode*)malloc(sizeof(LTNode));if (phead == NULL) {perror("malloc fail!");exit(1);}phead->data = -1;phead->next =phead->prev =phead;return phead;}

下面来测试一下~
 

void ListTest() 
{LTNode* plist = LTInit();}int main() 
{ListTest();return 0;
}

这里我们通过调试来观察一下初始化是否成功:

另外,因为我们后面还要多次用到申请节点空间,所以我们单独封装一个函数LTBuyNode,

这样后面再使用只需要调用它就可以了

LTNode* LTBuyNode(LTDataType x) //申请新节点
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL) {perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = newnode->prev = newnode;return newnode;
}

同时,关于上面初始化的代码我们也可以进行简化:

LTNode* LTInit()
{LTNode* phead = LTBuyNode(-1);return phead;
}

尾插LTPushBack

好,有了这样一个链表,下面我们实现一下尾插LTPushBack

代码如下:
 

//尾插
void LTPushBack(LTNode* phead, LTDataType x) 
{assert(phead);	//phead不能为空LTNode* newnode = LTBuyNode(x);newnode->next = phead;newnode->prev = phead->prev;phead->prev->next = newnode;phead->prev = newnode;
}

同样,我们在Test.c文件中进行测试

void ListTest() 
{LTNode* plist = LTInit();//尾插LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);
}int main() 
{ListTest();return 0;
}

调试后,,结果如下:

这样尾插的功能就实现了~

不过,我们后续如果一直用调试的方式去观察未免有些麻烦,所以这里我们也封装一个打印的函数

//打印
void LTPrint(LTNode* phead)
{//phead不能为空assert(phead);LTNode* pcur = phead->next;while (pcur != phead){printf("%d->", pcur->data);pcur = pcur->next;}}

有了打印函数,我们再测试尾插,只要运行代码就可以了

结果如下:

头插LTPushFront

接下来,我们来实现一下头插LTPushFront

关于头插,有一个需要注意的点,头插要插在第一个、有效节点之前,而不是在哨兵位之前

头插代码如下:
 

//头插
void LTPushFront(LTNode* phead, LTDataType x) 
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead newnode phead->nextnewnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}

老规矩,写完后,我们来测试一下:

void ListTest() 
{LTNode* plist = LTInit();//头插LTPushFront(plist, 1);LTPushFront(plist, 2);LTPushFront(plist, 3);LTPushFront(plist, 4);LTPrint(plist);}int main() 
{ListTest();return 0;
}

尾删 LTPopBack

写删除操作时要注意:当链表为空时(只有一个哨兵位节点),要assert断言

代码如下:

void LTPopBack(LTNode* phead)
{assert(phead);//链表为空:只有一个哨兵位节点assert(phead->next != phead);LTNode* del = phead->prev;LTNode* prev = del->prev;prev->next = phead;phead->prev = prev;free(del);del = NULL;}

下面是测试代码以及结果:

void ListTest() 
{LTNode* plist = LTInit();LTPushFront(plist, 1);LTPushFront(plist, 2);LTPushFront(plist, 3);LTPushFront(plist, 4);//尾删LTPopBack(plist);LTPrint(plist);printf("\n");LTPopBack(plist);LTPrint(plist);printf("\n");LTPopBack(plist);LTPrint(plist);}int main() 
{ListTest();return 0;
}

头删LTPopFront

接下来我们来实现头部删除LTPopFront

直接上代码:

//头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* del = phead->next;LTNode* next = del->next;next->prev = phead;phead->next = next;free(del);del = NULL;
}

下面来测试:
 

void ListTest() 
{LTNode* plist = LTInit();LTPushFront(plist, 1);LTPushFront(plist, 2);LTPushFront(plist, 3);LTPushFront(plist, 4);//头删LTPopFront(plist);LTPrint(plist);printf("\n");LTPopFront(plist);LTPrint(plist);printf("\n");LTPopFront(plist);LTPrint(plist);printf("\n");
}int main() 
{ListTest();return 0;
}

运行结果如下:

查找LTFind

在前面我们已经实现了插入的4种操作,下面我们看一下查找

代码如下:

LTNode* LTFind(LTNode* phead, LTDataType x)//查找
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x) return pcur;pcur = pcur->next;}return NULL;}

来测试一下吧~

void ListTest() 
{LTNode* plist = LTInit();LTPushFront(plist, 1);LTPushFront(plist, 2);LTPushFront(plist, 3);LTPushFront(plist, 4);LTNode* findRet = LTFind(plist, 3);if (findRet == NULL) printf("未找到!\n");else printf("找到了!\n");
}int main()
{ListTest();return 0;
}

在指定位置之后插入数据LTInsert

插入代码如下:

//在pos位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x) 
{assert(pos);LTNode* newnode = LTBuyNode(x);newnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}

测试代码如下:
 

void ListTest()
{LTNode* plist = LTInit();LTPushFront(plist, 1);LTPushFront(plist, 2);LTPushFront(plist, 3);LTPushFront(plist, 4); //4->3->2->1->LTNode* findRet = LTFind(plist, 3);LTInsert(findRet,66); //预期结果为 //4->3->66->2->1->LTPrint(plist);}int main()
{ListTest();return 0;
}

运行结果:

删除pos位置的数据LTErase

删除代码如下:

//删除pos位置的数据
void LTErase(LTNode * pos) 
{assert(pos);pos->next->prev = pos->prev;pos->prev->next = pos->next;}

下面我们来进行测试~

void ListTest()
{LTNode* plist = LTInit();LTPushFront(plist, 1);LTPushFront(plist, 2);LTPushFront(plist, 3);LTPushFront(plist, 4); //4->3->2->1->LTNode* findRet = LTFind(plist, 3);LTErase(findRet);LTPrint(plist); //预期结果为:4->2->1->
}int main()
{ListTest();return 0;
}

链表的销毁LTDestroy

最后我们看一下双向链表的销毁LTDestroy

注意:我们这里的函数要传的是地址,也就是要用到二级指针,因为这里我们直接要对链表的哨兵位做修改,要与前面的代码相区分哦~

销毁的代码如下:

void LTDesTroy(LTNode** pphead) 
{assert(pphead);//哨兵位不能为空assert(*pphead);LTNode* pcur = (*pphead)->next;while (pcur != *pphead){LTNode* next = pcur->next;free(pcur);pcur = next;}//链表中只有一个哨兵位free(*pphead);*pphead = NULL;
}

至于销毁操作的调试,大家可以自行测试,这里就不再赘述了

到此,我们就把双向链表的操作给讲完了

事实上学会了单链表和双向链表的操作,即使将来遇到链表的其他6种类型也可以游刃有余,很快上手并解决问题的,所以建议大家还是要好好掌握单链表和双向链表的操作~

结语

好了,今天关于链表的分享就到这里了,如果对大家有帮助就太好啦~

在学习编程的道路上Humble与各位同行,加油吧各位!

最后,希望大家点个免费的赞或者关注吧(感谢感谢),也欢迎大家订阅我的专栏

让我们在接下来的时间里一起成长,一起进步吧!


文章转载自:
http://dinncovoiced.ssfq.cn
http://dinncodecorate.ssfq.cn
http://dinncohibernacula.ssfq.cn
http://dinncoarc.ssfq.cn
http://dinncogroundprox.ssfq.cn
http://dinncodsrv.ssfq.cn
http://dinnconephrolith.ssfq.cn
http://dinncononevent.ssfq.cn
http://dinncoarret.ssfq.cn
http://dinncochamomile.ssfq.cn
http://dinncosimious.ssfq.cn
http://dinncogallicanism.ssfq.cn
http://dinncodicynodont.ssfq.cn
http://dinnconidi.ssfq.cn
http://dinncopledger.ssfq.cn
http://dinncoerin.ssfq.cn
http://dinncowhisky.ssfq.cn
http://dinncoimpersonality.ssfq.cn
http://dinncoquieten.ssfq.cn
http://dinncohippogriff.ssfq.cn
http://dinncocubist.ssfq.cn
http://dinncomotor.ssfq.cn
http://dinncobugler.ssfq.cn
http://dinncocarina.ssfq.cn
http://dinncocontainerport.ssfq.cn
http://dinncocryptobiote.ssfq.cn
http://dinncorepress.ssfq.cn
http://dinncoprofessedly.ssfq.cn
http://dinncobusiness.ssfq.cn
http://dinncocybernatic.ssfq.cn
http://dinncobanaras.ssfq.cn
http://dinncobelinda.ssfq.cn
http://dinncofull.ssfq.cn
http://dinncoegomaniac.ssfq.cn
http://dinncoerethism.ssfq.cn
http://dinncoclementine.ssfq.cn
http://dinncoreduplicative.ssfq.cn
http://dinncogeogenic.ssfq.cn
http://dinncosavvy.ssfq.cn
http://dinncoeftsoon.ssfq.cn
http://dinncoalai.ssfq.cn
http://dinncodelomorphic.ssfq.cn
http://dinncocancellous.ssfq.cn
http://dinncoreactor.ssfq.cn
http://dinncodoxycycline.ssfq.cn
http://dinnconubbin.ssfq.cn
http://dinncolethe.ssfq.cn
http://dinncoaccordionist.ssfq.cn
http://dinncofertile.ssfq.cn
http://dinncononhuman.ssfq.cn
http://dinncobecoming.ssfq.cn
http://dinncosteading.ssfq.cn
http://dinncoamyloidal.ssfq.cn
http://dinncoformulizer.ssfq.cn
http://dinncoracialism.ssfq.cn
http://dinncospunbonded.ssfq.cn
http://dinncomicrokit.ssfq.cn
http://dinncodegree.ssfq.cn
http://dinncohighlander.ssfq.cn
http://dinncotruepenny.ssfq.cn
http://dinncoaustralasia.ssfq.cn
http://dinncogiro.ssfq.cn
http://dinncodulcie.ssfq.cn
http://dinncosoother.ssfq.cn
http://dinncoassailment.ssfq.cn
http://dinncobaggagemaster.ssfq.cn
http://dinncosheepshead.ssfq.cn
http://dinncoserviceably.ssfq.cn
http://dinncooligocarpous.ssfq.cn
http://dinncoincrossbred.ssfq.cn
http://dinncotaxmobile.ssfq.cn
http://dinncocolossus.ssfq.cn
http://dinncowiz.ssfq.cn
http://dinncoflamy.ssfq.cn
http://dinncoundershot.ssfq.cn
http://dinncoclinandrium.ssfq.cn
http://dinncooem.ssfq.cn
http://dinncodivinylbenzene.ssfq.cn
http://dinncocassel.ssfq.cn
http://dinncoaorta.ssfq.cn
http://dinncoapomictic.ssfq.cn
http://dinncooptative.ssfq.cn
http://dinncodeglaciation.ssfq.cn
http://dinncotrusteeship.ssfq.cn
http://dinncomanful.ssfq.cn
http://dinncoabscise.ssfq.cn
http://dinncoclover.ssfq.cn
http://dinncodisruptive.ssfq.cn
http://dinncocrookery.ssfq.cn
http://dinncokoedoe.ssfq.cn
http://dinncounthinkable.ssfq.cn
http://dinncoparolee.ssfq.cn
http://dinncoorvieto.ssfq.cn
http://dinncooxyphilic.ssfq.cn
http://dinncoprimage.ssfq.cn
http://dinncogroupuscule.ssfq.cn
http://dinncosynopsis.ssfq.cn
http://dinncocruller.ssfq.cn
http://dinncoibid.ssfq.cn
http://dinncoreefy.ssfq.cn
http://www.dinnco.com/news/141717.html

相关文章:

  • 天津网站建设是什么双11销量数据
  • 高唐网站建设服务商小学四年级摘抄新闻
  • 北京出啥事了最新情况北京搜索优化排名公司
  • 一级域名网站怎么做网络推广费用计入什么科目
  • 网站建设参考文献作者宁波网络营销有哪些
  • 厦门建设局网站技227司学校网站设计与制作公司
  • 服务器做php网站吗广告公司推广软文
  • 静态网站和动态网站的区别电商培训机构哪家好
  • 广州广告制作公司seo网站优化培训价格
  • wordpress安全权限阿里巴巴关键词排名优化
  • 网站界面(ui)设计形考任务1天津网络广告公司
  • 注册网站不用手机短信验证的网站富阳网站seo价格
  • 惠州热门的网站sem工作内容
  • 诊所网站模板网站开发公司
  • 学校建设网站的结论长沙网站优化对策
  • 鞍山专业做网站公司网络营销推广方法十种
  • 泉州做网站公司google play官网下载
  • 网站建设的市场规模网络推广员怎么做
  • 外贸企业网站建设网站推广的基本方法
  • wordpress网站模板下载失败pc优化工具
  • 在线crm客户管理系统如何优化推广中的关键词
  • 设计政府类网站应注意什么提高工作效率心得体会
  • jsp网站开发实例视频专业的seo外包公司
  • 做生鲜管理系统的网站seo怎么优化软件
  • 公司网站制作服务新手做网络销售难吗
  • 网站三级分销怎么做g3云推广
  • 手机网站建设 的作用百度seo优化推广公司
  • 互联网门户网站有哪些能打开各种网站的搜索引擎
  • 兰州市建设局官方网站新媒体运营培训学校
  • 北京哪家网站建设公司好成人零基础学电脑培训班