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

建设培训网站群排名优化软件

建设培训网站,群排名优化软件,wordpress关注查看,做cps要做什么类型的网站目录 1、双向带头循环链表的介绍 2、双向带头循环链表的接口 3、接口实现 3.1 开辟结点 3.2 创建返回链表的头结点 3.3 判断链表是否为空 3.4 打印 3.5 双向链表查找 3.6 双向链表在pos的前面进行插入 3.6.1 头插 3.6.2 尾插 3.6.3 更新头插、尾插写法 3.7 双向链…

目录

1、双向带头循环链表的介绍

2、双向带头循环链表的接口

3、接口实现

3.1 开辟结点

3.2 创建返回链表的头结点

3.3 判断链表是否为空

3.4 打印

3.5 双向链表查找

3.6 双向链表在pos的前面进行插入

3.6.1 头插

3.6.2 尾插

3.6.3 更新头插、尾插写法

3.7 双向链表删除pos位置的节点

3.7.1 头删

3.7.2 尾删

3.7.3 更新头删、尾删写法

3.8 双向链表销毁

4、完整代码

5、功能测试


1、双向带头循环链表的介绍

我们将这个题目拆分开来可以提取三个关键字:双向,带头,循环。我们就以这三个关键字来展开介绍一下:

首先是双向:双向就说明了这个结点可以找到自己的前驱和后继,这一点与单链表存在本质的区别;

其次是带头:带头说明链表有一个头结点,这个头结点也可以称为哨兵位的头结点,此结点与其他结点是一样的,只是它的 data 域放的是随机值(有的会存放链表的长度);

最后是循环:循环说明了它的结构是一个环装,头结点的前驱结点存放着尾结点,尾结点的后继结点存放着头结点。

2、双向带头循环链表的接口

双向带头循环链表与单链表的功能是一样的,都是可以增删查改的,但是双向带头循环链表的特性让这么功能写的时候大大提高了我们的效率。

// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}ListNode;// 创建返回链表的头结点
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

3、接口实现

3.1 开辟结点

我们的链表是动态的链表,因此每次在插入的时候我们都需要 malloc 一个结点,我们将其封装成一个函数,方便后面的代码复用。

ListNode* BuyListNode(LTDataType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (NULL == newnode){perror("malloc fail:");return NULL;}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}

3.2 创建返回链表的头结点

这一步是我们给链表创建一个哨兵位的头结点。因为是双向带头循环链表,因此我们让 prev 和 next 指针都指向自己,这样就算是只有一个头结点,我们也是双向循环的结构。

ListNode* ListCreate()
{ListNode* phead = BuyListNode(-1);phead->next = phead;phead->prev = phead;return phead;
}

3.3 判断链表是否为空

这一步是我们为后面的删除时封装的一个判空功能函数,当链表存在的时候不排除链表为空的情况,因此我们封装此函数,以便后面的接口复用。

bool ListEmpty(ListNode* pHead)
{assert(pHead);return pHead->next == pHead;
}

3.4 打印

打印函数我们已经很熟悉了,但是双向带头循环链表的打印终止条件要注意,这里不再是以前的 cur == NULL,而是 cur != pHead ,当 cur 走到 pHead 时就说明我们已经遍历完整个链表了。

void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->next;printf("guard");while (cur != pHead){printf("<==>%d", cur->data);cur = cur->next;}printf("<==>\n");
}

3.5 双向链表查找

查找不难,但是这里要注意,双向带头链表的第一个结点是哨兵位结点,因此我们要从哨兵位的下一个结点开始遍历查找(cur = pHead->next),循环的终止条件依然是 cur != pHead。

ListNode* ListFind(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* cur = pHead->next;while (cur != pHead){if (cur->data == x)return cur;cur = cur->next;}return NULL;
}

3.6 双向链表在pos的前面进行插入

我们在找到pos位置后,在 pos 位置前进行插入,我们按下面的流程执行:

1、假如我们要在 data3 前插入一个 data4,我们先用定义一个结构体指针变量 prev,先将data3->prev (data2)结点保存在 prev 变量中;

2、再将 prev->next 改为 data4 ,然后将 data4->prev 改为 prev;

3、最后把 data4->next = data3,再把 data3->prev = data4。

void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* prev = pos->prev;ListNode* newnode = BuyListNode(x);prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}

3.6.1 头插

头插的话我们与在pos位置前插入一致,先将第一个结点保存起来,然后进行插入。

void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newnode = BuyListNode(x);ListNode* first = pHead->next;//多写这一个变量下面的插入语句就可以无序写pHead->next = newnode;newnode->next = first;newnode->prev = pHead;first->prev = newnode;
}

3.6.2 尾插

尾插的话先将链表的尾结点保存起来,然后进行插入,还是与在pos位置前插入一样。

void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* tail = pHead->prev;ListNode* newnode = BuyListNode(x);tail->next = newnode;newnode->prev = tail;newnode->next = pHead;pHead->prev = newnode;
}

3.6.3 更新头插、尾插写法

对比插入代码我们其实不难发现,头插、尾插与在pos位置前插入的代码逻辑是一样的,实现的功能根本上也没有变,那我们就在头插、尾插时直接复用 ListInsert 接口就可以实现。

1> 头插

void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListInsert(pHead->next, x);
}

2> 尾插

因为是 pos 位置前插入,链表是双向循环的,所以传的第一个参数就是 pHead ,哨兵位结点前一个结点就是尾结点。

void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListInsert(pHead, x);
}

3.7 双向链表删除pos位置的节点

我们在找到 pos 结点后,再将 pos 结点删除,我们按下面的流程执行:

1、定义两个结构体指针变量 posPrev与posNext,将 pos 位置前后结点分别保存在 posPrev与posNext 指针变量中;

2、将posPrev->next = posNext,再将 posNext->prev = posPrev;

3、释放掉 pos 结点,free(pos)。

void ListErase(ListNode* pos)
{assert(pos);ListNode* posPrev = pos->prev;ListNode* posNext = pos->next;posPrev->next = posNext;posNext->prev = posPrev;free(pos);
}

3.7.1 头删

头删的话我们先将 pHead->next结点与pHead->next->next结点保存下来,将哨兵位结点与头结点的下一个结点连接起来,再将头结点释放掉。

void ListPopFront(ListNode* pHead)
{assert(pHead);assert(!ListEmpty(pHead));ListNode* first = pHead->next;ListNode* second = first->next;pHead->next = second;first->prev = pHead;free(first);
}

3.7.2 尾删

尾删的话我们先将 pHead->prev结点与pHead->prev->prev结点保存下来,将哨兵位结点与尾结点的前一个结点连接起来,再将尾结点释放掉。

void ListPopBack(ListNode* pHead)
{assert(pHead);assert(!ListEmpty(pHead));ListNode* tail = pHead->prev;ListNode* tailPrev = tail->prev;tailPrev->next = pHead;pHead->prev = tailPrev;free(tail);
}

总结在头删与尾删前要判断链表是否为空。

3.7.3 更新头删、尾删写法

对比删除代码我们其实不难发现,头删、尾删与删除pos位置结点的代码逻辑是一样的,实现的功能根本上也没有变,那我们就在头删、尾删时直接复用 ListErase 接口就可以实现。

1> 头删

void ListPopFront(ListNode* pHead)
{assert(pHead);assert(!ListEmpty(pHead));ListErase(pHead->next);
}

2> 尾删

void ListPopBack(ListNode* pHead)
{assert(pHead);assert(!ListEmpty(pHead));ListErase(pHead->prev);
}

3.8 双向链表销毁

链表的销毁主要是遍历一遍链表,从 cur = pHead->next 开始,循环终止的条件为 cur != pHead,遍历完再将哨兵位结点释放掉,整个链表就被释放掉了。

void ListDestory(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->next;while (cur != pHead){ListNode* next = cur->next;free(cur);cur = next;}free(pHead);
}

4、完整代码

完整代码在代码仓库,入口:C语言: C语言学习的代码,多复习 - Gitee.com

5、功能测试

http://www.yidumall.com/news/25534.html

相关文章:

  • 国家疫情防控最新政策第十版盐城seo培训
  • wordpress 仿CSDN台州seo公司
  • 商洛 网站建设中国关键词网站
  • 青岛网站策划学会计哪个培训机构比较正规
  • 西昌网站开发公司app推广怎么做
  • 公司网站如何做的美丽dsp投放方式
  • 金川做网站公司针对百度关键词策划和seo的优化
  • 博罗东莞网站建设业务推广网站
  • 现在很多网站都是wordpress免费刷推广链接的软件
  • 做网站的ui框架沧州网站优化
  • iis 5 如何添加网站免费推广网站视频
  • 做淘宝类网站的步骤能打开任何网站浏览器
  • 织梦CMS做的网站能过等保三级吗seo是哪里
  • h5网站要多久关键词挖掘工具爱站网
  • 网站建立平台体验营销案例
  • 燕郊做网站的百度竞价推广开户价格
  • 建设专业网站运营团队发稿平台
  • 做介绍英文网站百度关键字搜索量查询
  • b2c商城开发方案网站优化公司怎么选
  • 适合年轻人开的工作室合肥百度推广优化排名
  • 做外贸网络推广网站排名seo公司哪家好
  • 做自己的网站怎么购买空间谷歌seo培训
  • 用php做网站用什么框架关键词优化技巧有哪些
  • 绵阳政府网站建设西安网站建设推广
  • 网站设计风格怎么写百度爱采购排名
  • 杭州小程序网站开发公司搜索引擎是指什么
  • 如何查询网站是不是诈骗网站外贸网站平台哪个好
  • 企业做网站属于广告宣传费吗今日世界杯比分预测最新
  • 更换wordpress图标河北seo网络推广
  • 中企动力官做网站怎么样简述搜索引擎的工作原理