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

如何做网站广告百度推广优化排名

如何做网站广告,百度推广优化排名,光泽县规划建设局网站,广东省城乡建设部网站目录 链表的分类 带头双向循环链表的实现 带头双向循环链表的结构 带头双向循环链表的结构示意图 空链表结构示意图 单结点链表结构示意图 多结点链表结构示意图 链表创建结点 双向链表初始化 销毁双向链表 打印双向链表 双向链表尾插 尾插函数测试 双向链表头插 …

目录

链表的分类

带头双向循环链表的实现

带头双向循环链表的结构

带头双向循环链表的结构示意图

空链表结构示意图

单结点链表结构示意图

 多结点链表结构示意图

链表创建结点

双向链表初始化

销毁双向链表

打印双向链表

 双向链表尾插

尾插函数测试

双向链表头插

头插函数测试

 双向链表尾删

尾删函数测试

双向链表头删

头删函数测试

双向链表查找

双向链表pos位置前插

插入函数测试

 双向链表删除pos位置的结点

删除函数测试

利用 ListInsert()函数改造头插尾插函数

尾插函数改造版本

头插函数改造版本

利用ListEarse()函数改造头删 尾删函数

头删函数改造版本

尾删函数改造版本

计算双向链表长度


链表的分类

  • 单向/双向

单向列表:每一个结点结构中只保存下一结点的地址,所以很难从后一结点找到前一节点;

双向列表:每一个结点结构中不仅保存下一结点的地址,还保存上一节点的地址;方便寻找前一节点和后一节点;

 

  • 带头/不带头

带头:在头结点之前有一个哨兵位结点,哨兵位的数据域不存储有效数据,指针域指向头结点

不带头:没有哨兵位结点,尾插尾删考虑头结点情况;

 

  • 循环/非循环

循环:头结点与尾结点相连;

非循环:头结点与尾结点不相连;

上述情况相互组合,共有8种情况,  实际中使用的链表数据结构,都是带头双向循环链表,带头双向循环链表虽然结构复杂,但是其结构具有很多优势,实现反而简单;

带头双向循环链表的实现

带头双向循环链表的结构

typedef int LTDataType;
typedef struct ListNode
{struct ListNode* prev;//前址域-存放前一个结点的地址LTDataType data;//数据域struct ListNode* next;//后址域-存放后一个结点的地址
}ListNode;

逻辑图:

物理图:

带头双向循环链表的结构示意图

  • 空链表结构示意图

由图可知,head->prev=head; head->next=head;

  • 单结点链表结构示意图

由图可知:

head->next=FirstNode;

head->prev=FirstNode;

FirstNode->prev=head;

FirstNode->next=head;

  •  多结点链表结构示意图

由图可知:

head->next=firstnode;

head->prev=tail;

tail->next=head;

firstnode->prev=head;

链表创建结点

//创建链表结点,返回链表结点地址
ListNode* BuyListNode(LTDataType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (newnode == NULL){perror("malloc failed:");exit(-1);}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}

双向链表初始化

 注:函数调用时得到动态开辟的链表空间起始地址的两种方案如下

方案一: 当传参时为链表结点的地址,函数的形参设计为二级指针,只有通过传址调用,可以将动态开辟的链表的起始地址带出函数;

方案二: 设计函数的返回类型为结点指针,返回动态开辟的链表结点指针,如此可以得到链表空间的起始地址;

//初始化链表(空链表)
ListNode* ListInit()
{//创建哨兵位结点ListNode* head = BuyListNode(0);//0不是有效数据//初始化哨兵位结点的指针域head->next = head;head->prev = head;return head;
}

销毁双向链表

  • 循环遍历释放结点,包含哨兵位结点;
  • 释放前保存下一结点地址,避免地址丢失;
//销毁链表,包含哨兵位结点
void DestoryList(ListNode* phead)
{assert(phead);//创建寻址指针ListNode* cur = phead;//断开循环链表phead->prev->next = NULL;while (cur != NULL){//记录下一结点地址ListNode* next = cur->next;//释放当前结点free(cur);//寻找下一节点cur = next;}return;
}

打印双向链表

  • 循环遍历链表打印数据,不显示哨兵位结点的数据域;
  • 以哨兵位头结点作为结束标志;
void PrintList(ListNode* phead)
{assert(phead != NULL);ListNode* cur = phead->next;printf("phead<==>");while (cur != phead){printf("%d<==>", cur->data);cur = cur->next;}printf("\n");
}

 双向链表尾插

  •  尾插先找尾,哨兵位的前址域即为尾结点即tail=head->prev;
  • 当链表为空时,连接的逻辑关系相同(创建三个指针变量,按照新结点的前址域指向谁,谁指向新结点,新结点的后址域指向谁,谁指向新结点进行连接);
void ListPushBack(ListNode* phead, LTDataType x)
{assert(phead);//寻找尾结点ListNode* tail = phead->prev;//创建新结点ListNode* newnode = BuyListNode(x);//尾插newnode->prev = tail;tail->next = newnode;newnode->next = phead;phead->prev = newnode;
}
尾插函数测试
void Test1()
{ListNode* plist=ListInit();ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushBack(plist, 5);PrintList(plist);
}
int main()
{Test1();return 0;
}

运行结果:

双向链表头插

  • 头插前先保存哨兵位结点的下一节点即原先真正的首节点;
  • 按照按照新结点的前址域指向谁,谁指向新结点,新结点的后址域指向谁,谁指向新结点进行连接从而实现头插,链表为空时,头插逻辑仍然相同;
//链表头插
void ListPushFront(ListNode* phead, LTDataType x)
{assert(phead);//保存原先的首节点ListNode* firstnode = phead->next;//创建新结点ListNode* newnode = BuyListNode(x);//头插newnode->prev = phead;phead->next = newnode;newnode->next = firstnode;firstnode->prev = newnode;
}
头插函数测试
void Test2()
{ListNode* plist = ListInit();ListPushFront(plist, 10);ListPushFront(plist, 20);ListPushFront(plist, 30);ListPushFront(plist, 40);ListPushFront(plist, 50);PrintList(plist);}
int main()
{Test2();return 0;
}

运行结果:

 双向链表尾删

  • 链表中只剩哨兵位结点,此时链表为空,不再进行尾删;
  • 尾删前记录前一节点的地址,方便修改逻辑关系;
//链表尾删
void ListPopBack(ListNode* phead)
{assert(phead);//链表中只剩哨兵位的情况assert(phead->next != phead);//查找尾结点ListNode* tail = phead->prev;//保存尾结点的上一节点ListNode* tailprev = tail->prev;//尾删free(tail);//建立链接关系tailprev->next = phead;phead->prev = tailprev;}
尾删函数测试
void Test3()
{ListNode* plist = ListInit();ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushBack(plist, 5);PrintList(plist);ListPopBack(plist);PrintList(plist);ListPopBack(plist);PrintList(plist);ListPopBack(plist);PrintList(plist);}
int main()
{Test3();return 0;
}

运行结果:

双向链表头删

  • 链表中只剩哨兵位结点,此时链表为空,不再进行头删;
  • 头删前记录下一节点的地址,方便修改逻辑关系;
//链表头删
void ListPopFront(ListNode* phead)
{assert(phead);//只剩哨兵位,不再头删assert(phead->next != phead);//保存原先的首节点ListNode* head = phead->next;//保存首结点的下一节点ListNode* headnext = phead->next->next;//头删free(head);//建立链接关系headnext->prev = phead;phead->next = headnext;}
头删函数测试
void Test4()
{ListNode* plist = ListInit();ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushBack(plist, 5);PrintList(plist);ListPopFront(plist);PrintList(plist);ListPopFront(plist);PrintList(plist);ListPopFront(plist);PrintList(plist);
}
int main()
{Test4();return 0;
}

运行结果:

双向链表查找

  • 循环遍历链表,从首节点开始遍历,以哨兵位头结点作为结束标志;
  • 根据数据域进行查找,找到返回数据域的结点地址,找不到返回空指针;
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;
}

双向链表pos位置前插

  • 前插时保存pos位置的前一个节点,方便修改逻辑关系;
  • 按照按照新结点的前址域指向谁,谁指向新结点,新结点的后址域指向谁,谁指向新结点进行链接;
void ListInsert(ListNode* pos, LTDataType x)
{assert(pos != NULL);//创建新结点ListNode* newnode = BuyListNode(x);//保存pos位置的前一个结点ListNode* posprev = pos->prev;//前插newnode->prev = posprev;posprev->next = newnode;newnode->next = pos;pos->prev = newnode;
}
插入函数测试
void Test5()
{ListNode* plist = ListInit();ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushBack(plist, 5);int x = 0;printf("请输入查找的数值:");scanf("%d", &x);ListNode* pos = ListFind(plist, x);if (pos == NULL){printf("要查找的值不存在\n");return;}//在查找到数值前插入100ListInsert(pos, 100);PrintList(plist);}
int main()
{Test5();return 0;
}

运行结果:

 双向链表删除pos位置的结点

  • 链表删除pos位置处的结点前先保存前结点和后结点的地址,方便处理链接关系;
//双向链表删除pos位置
void ListEarse(ListNode* pos)
{assert(pos);//保存pos位置处的前一个和后一个结点;ListNode* posprev = pos->prev;ListNode* posnext = pos->next;//删除pos位置结点free(pos);//建立前后节点的链接关系posprev->next = posnext;posnext->prev = posprev;}
删除函数测试
void Test6()
{ListNode* plist = ListInit();ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushBack(plist, 5);PrintList(plist);int x = 0;printf("请输入删除的数值:");scanf("%d", &x);ListNode* pos = ListFind(plist, x);if (pos == NULL){printf("要删除的值不存在\n");return;}ListEarse(pos);PrintList(plist);
}
int main()
{Test6();return 0;
}

运行结果:

利用 ListInsert()函数改造头插尾插函数

  • 尾插函数改造版本
void Listpushback(ListNode* phead, LTDataType x)
{assert(phead);ListInsert(phead, x);
}
  • 头插函数改造版本
void Listpushfront(ListNode* phead, LTDataType x)
{assert(phead);ListInsert(phead->next, x);
}

利用ListEarse()函数改造头删 尾删函数

  • 头删函数改造版本
void Listpopfront(ListNode* phead)
{assert(phead);//只剩哨兵位,不再头删assert(phead->next != phead);ListEarse(phead->next);
}
  • 尾删函数改造版本
void Listpopback(ListNode* phead)
{assert(phead);//链表中只剩哨兵位的情况assert(phead->next != phead);ListEarse(phead->prev);
}

计算双向链表长度

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

 

 

 

 

 

 

http://www.hkea.cn/news/13830/

相关文章:

  • wordpress 插件日志百度seo优化排名
  • 泰兴做网站嘉兴网络推广
  • 怎么把网站做成app网站开发流程有哪几个阶段
  • 教你做面食的网站办理培训机构需要具备的条件
  • 为什么要做外贸网站自己的app如何接广告
  • 动漫网站首页设计企业管理咨询
  • 淄博网站制作开发优化百度网盘搜索引擎入口在哪
  • 微网站开发如何制作网页游戏
  • 企业营销型网站建设开发2023年免费进入b站
  • 网站建设中栏目是什么百度浏览器官网在线使用
  • 那些网站可以做公司的推广网站做优化好还是推广好
  • 网站怎么做充值提现功能什么推广方法是有效果的
  • 西安志成网站建设公司网站查询服务器
  • 长沙诚信做网站上海网站seo招聘
  • vps 需刷新几次才能打开网站seo综合查询怎么进入网站
  • 德州做网站最好的公司网站播放视频速度优化
  • vs网站开发参考文献在线智能识图
  • 网站的界面设计广告营销推广
  • 陕西省建设工会网站深圳seo公司助力网络营销飞跃
  • 淘客网站后台怎么做企业文化的重要性
  • 桂林微信网站十大跨境电商erp排名
  • 房产如何做网站seo专家是什么意思
  • 惠州做网站乐云seoseo优化百度技术排名教程
  • 外国人学做中国菜的网站外贸网站搭建推广
  • b2b网站发布信息企业网络推广
  • 苏州苏州设计公司seo内容优化方法
  • 郑州建材公司网站建设武汉网站开发公司seo
  • 佛山新网站建设流程上海网站建设开发公司
  • 做视频网站需要什么软件有哪些百度信息流广告推广
  • 甘肃自助建站系统哪家好重庆seo推广外包