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

wordpress爆破公司官网优化方案

wordpress爆破,公司官网优化方案,wordpress导航栏代码,手机在线logo免费设计1.链表的分类 链表的结构有多种多样,以下情况组合起来就有8种(2x2x2)链表结构: 虽然有这么多的链表结构,但是我们实际中最常用的还是两种结构:单链表和双向带头循环链表。 无头单向非循环链表:结…

1.链表的分类

链表的结构有多种多样,以下情况组合起来就有8种(2x2x2)链表结构

虽然有这么多的链表结构,但是我们实际中最常用的还是两种结构:单链表和双向带头循环链表。

  • 无头单向非循环链表:结构简单,一般不会单独用来存数据实际中更多是作为其他数据结构的子结构,如哈希桶.图的邻接表等等。另外这种结构在笔试面试中出现很多。
  • 带头双向循环链表:结构最为复杂,一般用在单独存储数据实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然复杂,但是用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现就知道了。

 2.带头双向循环链表的实现

       和前面的数据结构的实现一样我们需要用三个文件,List.h(链表结构的声明以及链表的函数的声明),List.c(函数功能的实现),test.c(函数功能的测试文件)

2.1 List.h(链表结构的定义以及链表的函数的声明)

        在这里我们需要理解双向是啥意思,双向在结构中体现不仅有指向前一个节点的指针,而且有指向下一个节点的指针。初次之外通过这两个指针让链表也构成了循环。示意图如下:

故而带头双向链表在定义的时候需要用一个包含三个变量的结构变量,具体定义如下:

注:和前面一样在这里我们操作的数据类型可变,所以对类型重命名的方法。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>//带头双向链表的结构的定义 以及所要实现的函数的声明
typedef int LTDatatype;
typedef struct ListNode
{LTDatatype data;struct ListNode* prev;struct ListNode* next;
}LTNode;//打印链表
void LTPrint(LTNode* phead);//初始化  需要创建哨兵位 这样插入和删除的时候就不要考虑链表为空了
void LTInit(LTNode** pphead);
//因此双向链表为空的情况就是链表中只有一个哨兵位//插入
//头插   因为有了哨兵位就并不会影响头结点,故传一级指针即可
void LTPushBack(LTNode* phead, LTDatatype x);
//头插
void LTPushFront(LTNode* phead, LTDatatype x);//对链表进行判空
bool* LTEmpty(LTNode* phead);//删除
//尾删
void LTPopBack(LTNode* phead);
//头删
void LTPopFront(LTNode* phead);//数据的查找
LTNode* LTFind(LTNode* phead, LTDatatype x);//指定位置的操作
//指定位置之后数据的插入
void* LTInsert( LTNode* pos, LTDatatype x);//指定位置的数据的删除
void LTErase( LTNode* pos);//链表的销毁
void LTDestroy(LTNode* phead);

2.2 List.c(函数功能的实现)  需要包含头文件#include "List.h"

2.2.1 链表的初始化

LTNode* LTBuyNode(LTDatatype x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc fail");exit(1);}newnode->data = x;newnode->prev = newnode;newnode->next = newnode;return newnode;
}
void LTInit(LTNode** pphead)  //需要改变头结点(影响头结点)所以传二级指针
{*pphead=LTBuyNode(-1);
}

实现思路:

  • 在初始化之前我们得先实现一个申请新节点的函数。实现该函数需要用到malloc函数申请一个节点的空间,再进行判断看是否申请成功。如果申请成功就将数据保存在newnode->data中,并且将两个指针变量newnode->pre和newnode->next都指向新节点。最后返回新节点的地址。
  • 因为我们实现的是带头的链表,这个头是方便插入和删除(就相当于哨兵位),所以在初始化时只需要创建一个携带无效数据的节点即可。

2.2.2 链表的打印

//链表的打印
void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;if(pcur->next!=phead)printf("plist->");while (pcur != phead){printf("%d->", pcur->data);pcur = pcur->next;}printf("plist\n");
}

实现思路:

       我们需要遍历链表,对链表中的数据进行打印即可。但是需要注意的是,遍历链表的时候需要从头结点的下一个节点开始遍历,遍历结束条件是当前节点所指向的下一个节点 不能是头结点(哨兵位)。

2.2.3 链表的数据的插入

//插入
//尾插   因为有了哨兵位就并不会影响头结点,故传一级指针即可
void LTPushBack(LTNode* phead, LTDatatype x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//改变 phead->prev phead->prev->next newnode->prev newnode->nextnewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}
//头插
void LTPushFront(LTNode* phead, LTDatatype x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//改变 phead phead->prev  phead->next  phead->next->prev的指向关系newnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}

实现思路:

       在实现头插和尾插时都需要先判断所传值的有效性,以及先申请到一个新节点。

  • 尾插:       先将新节点的prev指向目前链表的尾节点,再将新节点的next指向头结点。除此之外,我们还需要将链表的尾节点的next指向新节点,将头结点的prev指向新节点。
  • 头插:       先将新节点的next指向头结点的下一个节点,再将新节点的prev指向头结点。除此之外我们还需要将头节点的下一个节点的prev指向新节点,再将头结点的next指向新节点。

2.2.4 链表的判空

//对链表进行判空
bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}

实现思路:

       返回值为bool类型,先判断值的有效性。然后将判断头结点的下一个指针是否为它本身返回即可。

2.2.5 链表的数据的删除

//删除
//尾删
void LTPopBack(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));//改变phead-prev->prev的next   phead->prev的指向LTNode* del = phead->prev;LTNode* delprev = del->prev;phead->prev = delprev;delprev->next = phead;free(del);del = NULL;
}
//头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));//改变phead->next->next的prev  phead的nextLTNode* del = phead->next;LTNode* delnext = del->next;phead->next = delnext;delnext->prev = phead;free(del);del = NULL;
}

实现思路:

       在实现尾删和头删时都需要先进行对所传值的有效性进行判断,再进行判断链表是否为空(除头结点外是否还有其他的有效节点)。

  • 尾删:        先将要删除的节点,即尾节点先保存下来;同时将尾节点的前一个节点保存下来delprev。(要不然直接释放掉就找不到了)   然后将头结点的prev指向delprev尾节点的前一个节点,将delprev的next指向头节点。最后释放掉del,并将del置为空
  • 头删:        先将要删除的节点,即头节点先保存下来;同时将尾节点的下一个节点保存下来delnext。(要不然直接释放掉就找不到了)  然后将头节点的nedxt指向delnext,再将delnext的prev指向头结点。 最后释放掉要删除的节点,并将其置为空。

注:因为每个节点都是通过动态内存申请的空间,所以在删除节点的时候是通过free,切记释放完需置为空,避免对野指针的使用。

2.2.6 链表中数据的查找

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

实现思路:

       先判断所传phead 的有效性,再进行判空。然后再进行链表的遍历,如果当前节点的数据刚好为所要查找的数据,则就返回当前节点的位置,否则就返回空指针。

2.2.7 链表中指定位置的操作

// 指定位置的操作
//指定位置之后数据的插入
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 LTErase(LTNode* pos)
{assert(pos);pos->prev->next= pos->next;pos->next->prev = pos->prev;free(pos);pos = NULL;
}

实现思路:

 指定位置之后的插入和指定位置的删除都需要先对所要操作的位置的有效性进行判断。

  • 指定位置之后的插入:     申请一个新节点,将新节点的next指向pos的下一个节点,将新节点的prev指向pos。将pos 的下一个节点的prev指向新节点,将pos的next指向新节点。
  • 指定位置的删除:           先将pos之前的节点的next指向pos的下一个节点,再将pos的下一个节点的prev指向pos的前一个节点。

2.2.8 链表的销毁

//链表的销毁
void LTDestroy(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = next;}free(phead);phead = pcur = NULL;
}

实现思路:

先判断所传值的有效性,因为每个节点都是通过动态内存申请的空间,所以链表的销毁需要通过free函数,通过遍历逐一释放节点, 释放完需要将当前节点和头结点置为空

  但是值得注意的是:

  • 在释放当前节点时,得先将当前节点的下一个节点保存下来。
  • 释放加点时,应该从头结点的下一个节点开始销毁(即从有效节点开始释放)

2.3 test.c(函数功能的测试文件)

#include "List.h"
void test()
{LTNode* lt = NULL;LTInit(&lt);//LTPrint(lt);LTPushBack(lt, 1);LTPushFront(lt, 29);LTPushFront(lt, 25);LTPushFront(lt, 2);LTPushFront(lt, 33);LTPrint(lt);LTPopBack(lt);//LTPushBack(lt, 1);//LTPopBack(lt);LTPrint(lt);/*LTPopFront(lt);LTPopFront(lt);LTPopFront(lt);LTPopFront(lt);LTPrint(lt);*/LTNode*ret=LTFind(lt, 25);if (ret)printf("ҵ%d\n",ret->data);elseprintf("δҵ\n");LTInsert(ret, 56);LTErase(ret);LTPrint(lt);LTDestroy(lt);LTPrint(lt);
}
int main()
{test();return 0;
}

如有错误,还望改正!!!

关注博主,优质内容不断更新!

http://www.tj-hxxt.cn/news/66841.html

相关文章:

  • 三水网站建设首选公司项目网站
  • wordpress手机注册登录搜索引擎seo如何赚钱
  • java网站开发模式有哪些成都seo培训班
  • wordpress添加模板文件合肥网络seo推广服务
  • 发展历程 网站建设深圳网站开发技术
  • 用虚拟机做网站服务器杭州seo靠谱
  • wordpress 微软北京专业网站优化
  • 漳州市建设局网站软件外包平台
  • 做门窗五金的网站semen是什么意思
  • 手机表格制作软件网站优化设计的基础是网站基本要素及每个细节的优化
  • HTML可以做彩票网站吗杭州seo代理公司
  • 广州海珠区有什么好玩的景点西安seo网站建设
  • 网站托管公司如何选择营销推广技巧
  • 鲜花销售网站开发费用推广类软文案例
  • 青海省公路建设管理局官方网站整合营销传播的定义
  • 网站联系方式要素希爱力的功效及副作用
  • wordpress连接插件南宁百度seo价格
  • vi设计与网站建设招标文件网站分析工具
  • wordpress qq音乐播放器seo平台有哪些
  • 企业网站制作需要多少费用搜索引擎平台排名
  • wordpress 新闻采集站竞价托管
  • 菠菜网站开发杭州百度人工优化
  • ps怎么做网站界面设计怎么注册电商平台
  • Wordpress页面手机不适配学seo需要学什么专业
  • 怎么做盗版网站网络营销渠道建设方案
  • 软件开发者英语广州百度快速排名优化
  • 在哪下载.net网站作品会计培训班初级费用
  • 长春网站制作报价怎么建立一个属于自己的网站
  • 深圳谷歌seo推广竞价推广和seo的区别
  • 阿里 域名解析 网站建设网站的搜索引擎