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

东莞做展示网站的公司站长素材官网免费

东莞做展示网站的公司,站长素材官网免费,稳定网站服务器租用,四川建筑培训网(数据结构)带头双向循环链表 前言 前面链表部分,咱们着重讲解了不带头单向不循环链表,简称单链表。那么链表其实也分很多种类适用于各种各样的场景。通过单链表的学习,其实我们已经大致了解了链表的绝大多数的内容,所以接下来我通…

(数据结构)带头双向循环链表

前言

  • 前面链表部分,咱们着重讲解了不带头单向不循环链表,简称单链表。那么链表其实也分很多种类适用于各种各样的场景。通过单链表的学习,其实我们已经大致了解了链表的绝大多数的内容,所以接下来我通过再为大家讲解一个带头双向循环链表,那么剩下的链表的种类大家就可以各自组合,各自书写了。
  • 链表种类:
    在这里插入图片描述
  • 两种代表链表:
  • 在这里插入图片描述
    1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
    2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带 来很多优势,实现反而简单了,后面我们代码实现了就知道了。

整体的实现代码如下:(头文件)

 #include<stdio.h>#include<stdlib.h>#include<assert.h>//对int类型取别名是为了后续方便更改数据类型typedef int LTDateType;//链表节点的结构typedef struct ListNode{struct ListNode *prev;struct ListNode *next;LTDateType date;}LTNode;//动态申请一个节点LTNode *BuyLTNode(LTDateType x);//对链表进行初始化LTNode *LTInit();//打印链表void LTPrint(LTNode* phead);//尾部插入数据void LTpushBack(LTNode *phead,LTDateType x);//尾部删除数据void LTpopBack(LTNode* phead);//头部插入数据void LTpushFront(LTNode *phead,LTDateType x);//头部删除数据void LTpopFront(LTNode* phead);//计算链表中有效数据的个数int LTSize(LTNode* phead);//查找数据值为x的节点LTNode *LTFind(LTNode *phead,LTDateType x);//在pos节点前插入数据为x的节点void LTInsert(LTNode* pos, LTDateType x);//删除pos位置处的节点void LTErase(LTNode* pos);//销毁链表void LTDestroy(LTNode* phead);
  • 函数实现文件:
 #include "List.h"LTNode *BuyLTNode(LTDateType x){LTNode *node= (LTNode*)malloc(sizeof (LTNode));if(node==NULL){perror("malloc fail");exit(-1);}node->date=x;node->next=NULL;node->prev=NULL;return node;}LTNode *LTInit(){LTNode *phead= BuyLTNode(-1);phead->prev=phead;phead->next=phead;return phead;}void LTPrint(LTNode* phead){assert(phead);printf("phead<->");LTNode *cur=phead->next;while(cur!=phead){printf("%d<->",cur->date);cur=cur->next;}printf("phead\n");}void LTpushBack(LTNode *phead,LTDateType x){//判断phead是否为空指针assert(phead);//尾节点如下,无需再去遍历寻找尾节点LTNode *tail=phead->prev;//创建一个新节点LTNode *newnode=BuyLTNode(x);//改变指针指向,将尾节点与新节点相连newnode->prev=tail;tail->next=newnode;newnode->next=phead;phead->prev=newnode;}void LTpopBack(LTNode* phead){assert(phead);if (phead->next == phead)exit(-1);else{LTNode *tail=phead->prev;phead->prev=tail->prev;phead->prev->next=phead;free(tail);}}void LTpushFront(LTNode *phead,LTDateType x){assert(phead);/*  LTNode *newnode= BuyLTNode(x);newnode->next=phead->next;phead->next->prev=newnode;phead->next=newnode;newnode->prev=phead;*/LTNode *newnode= BuyLTNode(x);LTNode *first=phead->next;phead->next=newnode;newnode->prev=phead;newnode->next=first;first->prev=newnode;}void LTpopFront(LTNode* phead){assert(phead);if (phead->next == phead)exit(-1);else{/* LTNode *first=phead->next;phead->next=first->next;phead->next->prev=phead;free(first);*/LTNode *first=phead->next;LTNode *second=first->next;free(first);phead->next=second;second->prev=phead;}}int LTSize(LTNode* phead){assert(phead);int size=0;LTNode *cur=phead->next;while(cur!=phead){size++;cur=cur->next;}return size;}LTNode *LTFind(LTNode *phead,LTDateType x){assert(phead);LTNode *cur=phead->next;while(cur!=phead){if(cur->date==x)return cur;cur=cur->next;}return NULL;}void LTInsert(LTNode* pos, LTDateType x){assert(pos);LTNode *posPrev=pos->prev;LTNode *newnode= BuyLTNode(x);posPrev->next=newnode;newnode->prev=posPrev;newnode->next=pos;pos->prev=newnode;}void LTErase(LTNode* pos){assert(pos);/*    pos->prev->next=pos->next;pos->next->prev=pos->prev;free(pos);*/LTNode *posPrev=pos->prev;LTNode *posNext=pos->next;free(pos);posPrev->next=posNext;posNext->prev=posPrev;}void LTDestroy(LTNode* phead){assert(phead);LTNode *cur=phead->next;while(cur!=phead){LTNode *next=cur->next;free(cur);cur=next;}free(phead);}
  • 测试文件:(这里的测试文件,其实就是大家调用写好的函数,看功能是否正确,大家可以自行更改,这里只是一个示例)
 #include "List.h"void test1(){LTNode *plist=LTInit();LTpushBack(plist,1);LTpushBack(plist,2);LTpushBack(plist,3);LTpushBack(plist,4);LTPrint(plist);int c= LTSize(plist);printf("%d\n",c);LTNode *node= LTFind(plist,3);LTInsert(node,6);LTErase(node);LTPrint(plist);LTDestroy(plist);plist=NULL;}int main(){test1();return 0;}

函数逐个讲解:

  1. 第一个动态申请链表节点:
 LTNode *BuyLTNode(LTDateType x){LTNode *node= (LTNode*)malloc(sizeof (LTNode));if(node==NULL){perror("malloc fail");exit(-1);}node->date=x;node->next=NULL;node->prev=NULL;return node;}
  • 这个函数没什么好说的,就是用malloc和sizeof来申请节点,如果申请成功就赋值,失败则exit。
  1. 初始化函数:
LTNode *LTInit()
{LTNode *phead= BuyLTNode(-1);phead->prev=phead;phead->next=phead;return phead;
}
  • 在这里插入图片描述
  1. 打印函数:

    void LTPrint(LTNode* phead)
    {assert(phead);printf("phead<->");LTNode *cur=phead->next;while(cur!=phead){printf("%d<->",cur->date);cur=cur->next;}printf("phead\n");
    }
    

在这里插入图片描述
4. 尾部插入函数:

void LTpushBack(LTNode *phead,LTDateType x)
{//判断phead是否为空指针assert(phead);//尾节点如下,无需再去遍历寻找尾节点LTNode *tail=phead->prev;//创建一个新节点LTNode *newnode=BuyLTNode(x);//改变指针指向,将尾节点与新节点相连newnode->prev=tail;tail->next=newnode;newnode->next=phead;phead->prev=newnode;}

在这里插入图片描述
5. 尾部删除函数

void LTpopBack(LTNode* phead)
{assert(phead);if (phead->next == phead)exit(-1);else{LTNode *tail=phead->prev;phead->prev=tail->prev;phead->prev->next=phead;free(tail);}
}

在这里插入图片描述
6. 头部插入函数

void LTpushFront(LTNode *phead,LTDateType x)
{assert(phead);
/*  LTNode *newnode= BuyLTNode(x);newnode->next=phead->next;phead->next->prev=newnode;phead->next=newnode;newnode->prev=phead;
*/LTNode *newnode= BuyLTNode(x);LTNode *first=phead->next;phead->next=newnode;newnode->prev=phead;newnode->next=first;first->prev=newnode;}

在这里插入图片描述
7. 头部删除函数

void LTpopFront(LTNode* phead)
{assert(phead);if (phead->next == phead)exit(-1);else{/* LTNode *first=phead->next;phead->next=first->next;phead->next->prev=phead;free(first);*/LTNode *first=phead->next;LTNode *second=first->next;free(first);phead->next=second;second->prev=phead;}}

在这里插入图片描述
8. 计算有效节点个数

int LTSize(LTNode* phead)
{assert(phead);int size=0;LTNode *cur=phead->next;while(cur!=phead){size++;cur=cur->next;}return size;
}

在这里插入图片描述

  • 补充一点就是,我这里是因为哨兵位的结构和链表节点的结构是一样的,是共用链表节点的结构的。也就是说,哨兵位里面的date的类型是和链表节点里存的数据类型是一样的,都是LTDataType。所以这里的如果要用哨兵位记录链表长度就只能是int类型,如果LTDataType变成了char类型这些,那么哨兵位里的data+1结果就会不如人意了,字符+1和int整型+1那肯定是不一样的结果嘛。
  • 但是如果你就要哨兵位记录链表长度,那就单独再创建一个哨兵位的结构,和链表节点的结构脱离,这个可以参考我讲队列的那篇文章。
  1. 查找数据的值为x的节点
LTNode *LTFind(LTNode *phead,LTDateType x)
{assert(phead);LTNode *cur=phead->next;while(cur!=phead){if(cur->date==x)return cur;cur=cur->next;}return NULL;}
  • 这里这个函数功能和上一个函数,也就是计算有效个数函数和打印函数实现逻辑类似,就不多说了。
  1. 在pos位置前插入值为x的节点
void LTInsert(LTNode* pos, LTDateType x)
{assert(pos);LTNode *posPrev=pos->prev;LTNode *newnode= BuyLTNode(x);posPrev->next=newnode;newnode->prev=posPrev;newnode->next=pos;pos->prev=newnode;}

在这里插入图片描述

  • 这个函数也可以复用在尾插和头插函数里
  1. 删除pos位置的节点

void LTErase(LTNode* pos)
{assert(pos);/*    pos->prev->next=pos->next;pos->next->prev=pos->prev;free(pos);*/LTNode *posPrev=pos->prev;LTNode *posNext=pos->next;free(pos);posPrev->next=posNext;posNext->prev=posPrev;}

在这里插入图片描述

  • 这个函数也可以复用在尾删和头删里
  1. 链表销毁函数
void LTDestroy(LTNode* phead)
{assert(phead);LTNode *cur=phead->next;while(cur!=phead){LTNode *next=cur->next;free(cur);cur=next;}}

在这里插入图片描述

  • 到此,链表的内容就全部讲完了。
http://www.dtcms.com/wzjs/294652.html

相关文章:

  • 简+wordpress+主题资阳地seo
  • 淄博网站建设找李光明重庆旅游seo整站优化
  • ecshop做视频电商网站陕西网络推广公司
  • 不用代码做网站html网站seo优化的目的
  • 亿联网络 网站网页推广怎么收取费用
  • 昆明参差网站网络营销的手段包括
  • 黑马网站建设网站设计seo营销服务
  • 建一个电影网站多大 数据库青岛百度seo
  • 公司做的网站打开慢十大培训机构教育培训机构哪家好
  • 成都建设厅网站seo网站优化方案
  • 深圳网站建设外包公司哪家好seo岗位职责
  • 网站推荐广告模板软文推广300字
  • 河北省建设网站锁安装什么驱动护肤品软文推广
  • bc网站开发谷歌seo代运营
  • 江阴网站开发公司凡科建站代理
  • 布吉附近公司做网站建设多少钱百度热搜榜今日头条排名
  • asp.net 做网站实例原画培训机构哪里好
  • wordpress 能承受多大并发访问量武汉seo关键字优化
  • 卖汽车的网站怎么做的营销策划主要做些什么
  • 公司网站建设个人总结手机搜索引擎排名
  • 上海网站建设 报价清博舆情系统
  • 不用代码做交互式网站附近的成人电脑培训班
  • 济南网络公司排行seo优化方案
  • 企业网站管理系统 软件著作权青岛关键词推广seo
  • 滑坡毕业设计代做网站百度官网网站
  • 武汉做网站专业建站网络推广100种方式
  • wordpress网站制作教程视频成都网站建设方案优化
  • cvm服务器做网站爱站网站
  • 山东中佛龙建设有限公司网站seo技术培训教程
  • 阳原网站建设网络流量分析工具