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

网站seo优缺点合肥网站设计

网站seo优缺点,合肥网站设计,网页图片尺寸多大合适,网页设计与制作教程电子版pdf文章目录 一、前言二、链表的分类2.1是否带头2.2单向或者双向2.3循环或者不循环 三、双链表3.1双链表的概念3.2双链表的结构 四、双链表各功能的实现4.1双链表结点的创建4.2双链表的初始化4.2.1第一种初始化方式4.2.2第二种初始化方式 4.3双链表判断是否为空4.4双链表的尾、头及…

文章目录

  • 一、前言
  • 二、链表的分类
    • 2.1是否带头
    • 2.2单向或者双向
    • 2.3循环或者不循环
  • 三、双链表
    • 3.1双链表的概念
    • 3.2双链表的结构
  • 四、双链表各功能的实现
    • 4.1双链表结点的创建
    • 4.2双链表的初始化
      • 4.2.1第一种初始化方式
      • 4.2.2第二种初始化方式
    • 4.3双链表判断是否为空
    • 4.4双链表的尾、头及pos位置插入
      • 4.4.1尾插
      • 4.4.2头插
      • 4.4.3pos位置之后插入
      • 4.4.4pos位置之前插入
    • 4.5双链表的尾、头及pos位置删除
      • 4.5.1尾删
      • 4.5.2头删
      • 4.5.3pos位置结点删除
    • 4.6双链表特定元素的查找
    • 4.7双链表元素的打印
    • 4.8双链表的销毁
      • 4.8.1第一种销毁方式
      • 4.8.2第二种销毁方式
    • 4.9双链表的传参
  • 五、双链表整体代码分析
    • 5.1头文件——List.h及代码展示
    • 5.2主体代码文件——List.c及代码展示
    • 5.3测试文件——test.c及代码展示
      • 5.3.1尾插演示
      • 5.3.2头插演示
      • 5.3.3尾删演示
      • 5.3.4头删演示
      • 5.3.5特定元素查找演示
      • 5.3.6pos位置后插入演示
      • 5.3.7pos位置前插入演示
      • 5.3.8pos结点删除演示
      • 5.3.9链表销毁演示
  • 六、总结

一、前言

hello啊,各位宝子们。今天的你是在继续选择躺平,还是在持之以恒地努力学习呢?躺平呢有躺平的安逸,努力呢也有努力的收获。也希望大家平衡好这两者之间的得失关系。言归正传,今天咱们继续深入翱翔数据结构与算法的海洋,进一步领悟其独特的魅力。,up今天所要给大家介绍的数据结构就是——双链表。希望大家努力学习,耐心阅读。

二、链表的分类

这时候有的宝子可能就比较困惑。up我们之前不是才学习了单链表的数据结构吗?而今天又要开始学习双链表,那么链表到底又是怎么一个分类法呢。别急,up这就带领大家解开这层神秘的面纱。
链表的结构非常多样化,具体分为三个大方面——是否带头、方向指向以及是否循环。这样的话由于每个大方面存在两种情况,所以组合情况就有8(222)种链表结构。
在这里插入图片描述

2.1是否带头

在这里插入图片描述

2.2单向或者双向

在这里插入图片描述

2.3循环或者不循环

在这里插入图片描述
到这里,大家的困惑相信也就烟消云散了吧。那我们之前所学习的单链表,它的全称就是不带头单向不循环链表。而我们这次所要学习的双链表,全称则就是带头双向循环链表。虽然链表的结构分类可达8种之多,但是最常见的就是单链表和双链表这两种结构

三、双链表

3.1双链表的概念

双链表是一种数据结构,它的每个节点除了存储数据外,还有两个指针,分别指向前一个节点和后一个节点。这种结构使得双链表在进行插入和删除操作时更为高效,因为可以直接访问任何节点的前驱和后继节点。

3.2双链表的结构

在这里插入图片描述

四、双链表各功能的实现

4.1双链表结点的创建

在这里插入图片描述
代码展示:

ListNode* Listbuynode(ListDataType x)//申请结点
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (newnode == NULL){printf("malloc fail!");exit(1);}newnode->data = x;newnode->pre = newnode->next = newnode;return newnode;
}

4.2双链表的初始化

4.2.1第一种初始化方式

代码展示:

void ListInit1(ListNode** pphead)//第一种初始化
{assert(pphead);*pphead = Listbuynode(-1);
}

4.2.2第二种初始化方式

ListNode*  ListInit2()//第二种初始化
{ListNode* phead = Listbuynode(-1);return phead;
}

以上两种初始化的方式具体的不同在于:初始化1采用的是void类型,不需要返回值;初始化二采用的是ListNode*型,需要返回值。

4.3双链表判断是否为空

代码展示:

bool ListEmpty(ListNode* phead)//判空
{assert(phead);return phead->next == phead;
}

4.4双链表的尾、头及pos位置插入

4.4.1尾插

在这里插入图片描述

尾插的实质:在判断链表不为空的前提下,先让新结点的newnode->pre和newnode->next分别指向原链表的phead->pre和phead,最后再让原链表中的phead->pre->next和phead->pre再分别指向新节点newnode.
代码展示:

void ListPushBack(ListNode* phead,ListDataType x)//尾插
{assert(phead);ListNode* newnode = Listbuynode(x);newnode->pre = phead->pre;newnode->next = phead;phead->pre->next = newnode;phead->pre = newnode;}

4.4.2头插

在这里插入图片描述
头插的实质:在判断链表不为空的情况下,先让新节点的newnode->pre和newnode->next分别指向原链表的phead和phead->next,最后再让原链表中的phead->next->pre和phead->next再分别指向新节点newnode。
注意事项:头插的位置是是在头结点之后,如果插入在头结点之前,实际效果是尾插。
代码展示:

void ListPushFront(ListNode* phead, ListDataType x)//头插
{assert(phead);ListNode* newnode = Listbuynode(x);newnode->next = phead->next;newnode->pre = phead;phead->next->pre = newnode;phead->next = newnode;
}

4.4.3pos位置之后插入

在这里插入图片描述
pos位置后插入的实质:在pos结点不为空的情况下,先让新结点newnode->next和newnode->pre分别指向原链表中的pos->next和pos,最后再让原链表中的pos->next->pre和pos->next指向新节点newnode。
代码展示:

void ListInsertBack(ListNode* pos, ListDataType x)//在pos位置后插入结点
{assert(pos);ListNode* newnode = Listbuynode(x);newnode->next = pos->next;newnode->pre = pos;pos->next->pre = newnode;pos->next = newnode;}

4.4.4pos位置之前插入

在这里插入图片描述
pos位置之前插入的实质:pos结点不为空的情况下先让新节点newnode->next和newnode->pre分别指向原链表中的pos和pos->pre,最后再让原链表中的pos->pre->next和pos->pre分别指向新节点newnode。
代码展示:

void ListInsertFront(ListNode* pos, ListDataType x)//在pos位置前插入结点
{assert(pos);ListNode* newnode = Listbuynode(x);newnode->next = pos;newnode->pre = pos->pre;pos->pre->next = newnode;pos->pre = newnode;
}

4.5双链表的尾、头及pos位置删除

4.5.1尾删

在这里插入图片描述
尾删的实质:在判断链表非空的情况下,先把尾结点用del保存下来方便后续操作,再让del结点的del->pre->next指向phead,并且让phead->pre指向del->pre,最后再把del结点释放掉并且置为空即可。
代码展示:

void ListPopBack(ListNode* phead)//尾删
{assert(!ListEmpty(phead));ListNode* del = phead->pre;del->pre->next = phead;phead->pre = del->pre;free(del);del = NULL;
}

4.5.2头删

在这里插入图片描述
头删的实质:在判断链表非空的情况下,先把头删结点用del保存下来方便后续操作,接着再让del结点的del->next->pre指向phead,并且让phead->next指向del->next,最后再把del结点释放掉并且置为空即可。
注意事项: 头删删除的是头结点的下一个结点也就是11结点,并非是头结点,因为在双链表中头结点是不能删除和销毁的。

代码展示:

void ListPopFront(ListNode* phead)//头删
{assert(!ListEmpty(phead));ListNode* del = phead->next;del->next->pre = phead;phead->next = del->next;free(del);del = NULL;
}

4.5.3pos位置结点删除

在这里插入图片描述
pos位置删除实质:在判断pos结点不为空的情况下,先让pos->next->pre指向pos->pre,接着让pos->pre->next指向pos->next,最后将pos结点释放掉并且置为空即可。
代码展示:

void ListErase(ListNode* pos)//删除pos位置结点
{pos->next->pre = pos->pre;pos->pre->next = pos->next;free(pos);pos = NULL;
}

4.6双链表特定元素的查找

查找的实质:在判断链表不为空的情况下,定义一个开始结点指针pcur从phead->next结点开始,遍历整个链表,如果找到了则return pcur,没找到则return NULL,直到pcur = phead为止跳出循环。
代码展示:

ListNode* ListFind(ListNode* phead, ListDataType x)//查找特定元素
{assert(phead);ListNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x)//找到了{return pcur;}pcur = pcur->next;}return NULL;//未找到
}

4.7双链表元素的打印

打印的实质:在判断链表不为空的情况下,定义一个开始结点指针pcur从phead->next结点开始,遍历整个链表,逐一打印元素,直到pcur=phead为止跳出循环。

void ListPrint(ListNode* phead)//双链表的打印
{assert(phead);ListNode* pcur = phead->next;while (pcur != phead){printf("%d ->", pcur->data);pcur = pcur->next;}printf("\n");
}

4.8双链表的销毁

4.8.1第一种销毁方式

void ListDestroy1(ListNode** pphead)//第一种销毁方法
{assert(pphead);ListNode* pcur = (*pphead)->next;while (pcur != *pphead){ListNode* next = pcur->next;free(pcur);pcur = next;}free(*pphead);*pphead = NULL;
}

4.8.2第二种销毁方式

void ListDestroy(ListNode* phead)//第二种销毁方法
{assert(phead);ListNode* pcur = phead->next;while (pcur != phead){ListNode* next = pcur->next;free(pcur);pcur = next;}free(phead);phead = NULL;
}

销毁的实质:在判断链表不为空的情况下,定义一个开始结点指针pcur从pcur->next结点开始,遍历整个链表,逐一销毁,直到pcur = phead为止跳出循环,最后再把头结点销毁掉在置为空即可。

4.9双链表的传参

上面所有功能对已经实现完毕了,但是你可能会懵逼——为什么有的函数传参传的是一级指针,而又有的是传的二级指针呢?这里up给大家统一回答:关于传参到底是传一级指针还是二级指针,是看头结点是否发生改变,如果头结点不发生改变就传一级指针,相反如果头结点发生改变就传二级指针。

五、双链表整体代码分析

5.1头文件——List.h及代码展示

在这里插入图片描述
代码展示:

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int ListDataType;//重命名
typedef struct  ListNode//结点的结构体创建
{ListDataType data;struct ListNode* pre;struct ListNode* next;
}ListNode;
ListNode* Listbuynode(ListDataType x);//申请结点
void ListInit1(ListNode** pphead);//第一种初始化
ListNode* ListInit2();//第二种初始化
bool ListEmpty(ListNode* phead);//判空
void ListPushBack(ListNode* phead, ListDataType x);//尾插
void ListPushFront(ListNode* phead, ListDataType x);//头插
void ListPopBack(ListNode* phead);//尾删
void ListPopFront(ListNode* phead);//头删
void ListInsertBack(ListNode* pos, ListDataType x);//在pos位置后插入结点
void ListInsertFront(ListNode* pos, ListDataType x);//在pos位置前插入结点
void ListErase(ListNode* pos);//删除pos位置结点
ListNode* ListFind(ListNode* phead, ListDataType x);//查找特定元素
void ListPrint(ListNode* phead);//双链表的打印
void ListDestroy1(ListNode** pphead);//第一种销毁方法
void ListDestroy(ListNode* phead);//第二种销毁方法

5.2主体代码文件——List.c及代码展示

在这里插入图片描述
代码展示:

#include "List.h"
ListNode* Listbuynode(ListDataType x)//申请结点
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (newnode == NULL){printf("malloc fail!");exit(1);}newnode->data = x;newnode->pre = newnode->next = newnode;return newnode;
}
void ListInit1(ListNode** pphead)//第一种初始化
{assert(pphead);*pphead = Listbuynode(-1);
}
ListNode*  ListInit2()//第二种初始化
{ListNode* phead = Listbuynode(-1);return phead;
}
bool ListEmpty(ListNode* phead)//判空
{assert(phead);return phead->next == phead;
}
void ListPushBack(ListNode* phead,ListDataType x)//尾插
{assert(phead);ListNode* newnode = Listbuynode(x);newnode->pre = phead->pre;newnode->next = phead;phead->pre->next = newnode;phead->pre = newnode;
}
void ListPushFront(ListNode* phead, ListDataType x)//头插
{assert(phead);ListNode* newnode = Listbuynode(x);newnode->next = phead->next;newnode->pre = phead;phead->next->pre = newnode;phead->next = newnode;
}
void ListPopBack(ListNode* phead)//尾删
{assert(!ListEmpty(phead));ListNode* del = phead->pre;del->pre->next = phead;phead->pre = del->pre;free(del);del = NULL;
}
void ListPopFront(ListNode* phead)//头删
{assert(!ListEmpty(phead));ListNode* del = phead->next;del->next->pre = phead;phead->next = del->next;free(del);del = NULL;
}
void ListInsertBack(ListNode* pos, ListDataType x)//在pos位置后插入结点
{assert(pos);ListNode* newnode = Listbuynode(x);newnode->next = pos->next;newnode->pre = pos;pos->next->pre = newnode;pos->next = newnode;}
void ListInsertFront(ListNode* pos, ListDataType x)//在pos位置前插入结点
{assert(pos);ListNode* newnode = Listbuynode(x);newnode->next = pos;newnode->pre = pos->pre;pos->pre->next = newnode;pos->pre = newnode;
}
void ListErase(ListNode* pos)//删除pos位置结点
{pos->next->pre = pos->pre;pos->pre->next = pos->next;free(pos);pos = NULL;
}
ListNode* ListFind(ListNode* phead, ListDataType x)//查找特定元素
{assert(phead);ListNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x)//找到了{return pcur;}pcur = pcur->next;}return NULL;//未找到
}
void ListPrint(ListNode* phead)//双链表的打印
{assert(phead);ListNode* pcur = phead->next;while (pcur != phead){printf("%d ->", pcur->data);pcur = pcur->next;}printf("\n");
}
void ListDestroy1(ListNode** pphead)//第一种销毁方法
{assert(pphead);ListNode* pcur = (*pphead)->next;while (pcur != *pphead){ListNode* next = pcur->next;free(pcur);pcur = next;}free(*pphead);*pphead = NULL;
}
void ListDestroy(ListNode* phead)//第二种销毁方法
{assert(phead);ListNode* pcur = phead->next;while (pcur != phead){ListNode* next = pcur->next;free(pcur);pcur = next;}free(phead);phead = NULL;
}

5.3测试文件——test.c及代码展示

5.3.1尾插演示

在这里插入图片描述
`
代码展示;

ListPushBack(plist, 1);//尾插
ListPushBack(plist, 2);
ListPushBack(plist, 3);
ListPushBack(plist, 4);

5.3.2头插演示

在这里插入图片描述
在这里插入图片描述
代码展示;

ListPushFront(plist, 5);//头插
ListPushFront(plist, 6);

5.3.3尾删演示

在这里插入图片描述
在这里插入图片描述
代码展示:

	ListPopBack(plist);//尾删ListPopBack(plist);

5.3.4头删演示

在这里插入图片描述
在这里插入图片描述

ListPopFront(plist);//头删
ListPopFront(plist);

5.3.5特定元素查找演示

在这里插入图片描述
在这里插入图片描述
代码展示:

	ListNode* find = ListFind(plist, 4);//特定位置元素查找if (find != NULL){printf("找到了!");}else{printf("未找到!");}

5.3.6pos位置后插入演示

在这里插入图片描述
在这里插入图片描述
代码展示:

	ListInsertBack(find, 4);//pos后插入结点

5.3.7pos位置前插入演示

在这里插入图片描述
在这里插入图片描述
代码展示:

	ListInsertFront(find, 3);//pos前插入结点

5.3.8pos结点删除演示

在这里插入图片描述
在这里插入图片描述

	ListErase(find);//删除pos结点

5.3.9链表销毁演示

在这里插入图片描述
在这里插入图片描述
代码展示:

ListDestroy(plist);//链表的销毁
plist = NULL;
ListPrint(plist);
#include "List.h"
void test01()
{//ListNode* plist = NULL;//初始化1//ListInit1(&plist);ListNode* plist = ListInit2();//初始化2ListPushBack(plist, 1);//尾插ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushFront(plist, 5);//头插ListPushFront(plist, 6);//ListPopBack(plist);//尾删//ListPopBack(plist);//ListPopFront(plist);//头删//ListPopFront(plist);//ListNode* find = ListFind(plist, 4);//特定位置元素查找//if (find != NULL)//{//	printf("找到了!");//}//else//{//	printf("未找到!");//}//ListInsertBack(find, 4);//pos后插入结点//ListInsertFront(find, 3);//pos前插入结点//ListErase(find);//删除pos结点ListDestroy(plist);//链表的销毁plist = NULL;ListPrint(plist);}
int main()
{test01();return 0;
}

六、总结

OK啦宝子们,到这里,数据结构——双链表以及所有功能的实现就讲述完毕了。怎么样大家的功力是否又蹭蹭蹭地往上涨了呢?经过这么久的努力学习,相信大家已然成为了一个高手了吧,哈哈哈。不过不要骄傲,我相信大家一定可以越来越NB。最后呢,祝大家在学习的道路上一帆风顺,终成大神。记得三连O。

只有不断学习,才能不断进步,才能在激烈的竞争中立于不败之地。
在这里插入图片描述

http://www.dtcms.com/wzjs/422816.html

相关文章:

  • 南宁网站建设公司招聘百度竞价开户3000
  • 怎么把文件放到网站的根目录网站提交入口百度
  • 长春网站开发培训价格seo智能优化
  • wordpress文本块表格株洲百度seo
  • 广西壮族自治区党委seo网络推广怎么做
  • 沙田镇做网站搜索引擎优化简称seo
  • 湛江专门做网站百度网站站长工具
  • 做美食下载什么网站比较成功的网络营销案例
  • html5网站开发功能需求表在线观看的seo综合查询
  • 佛山新网站制作怎么样关键词优化排名怎么做
  • 男女性直接做的视频网站知乎营销推广
  • 如何登录网站制作平台网站推广关键词排名优化
  • 网站建设简洁seo推广网站
  • 网站推广关键词排名我想在百度上发布广告怎么发
  • 用wordpress做企业网站视频教程大数据分析培训机构
  • 抖音代运营服务明细表上海百度seo公司
  • 服务器关闭 网站被k长尾关键词搜索网站
  • 网站建设属于什么专业产品推广ppt
  • 水果网站 模板竞价排名深度解析
  • 行业门户网站设计企业管理培训机构排名前十
  • 做百度文库需要网站吗正规的培训学校
  • 当今做网站的流行趋势如何做推广
  • 网站需求说明百度集团股份有限公司
  • bootstrap网站模板导航市场推广方案范文
  • 中国战事新闻最新消息青岛百度seo代理
  • 备案网站建设方案微信朋友圈广告在哪里做
  • 做网站推广 优帮云岳阳网站建设推广
  • java多人视频广州seo黑帽培训
  • java视频网站开发技术全国疫情最新数据
  • 那曲网站建设河南网站设计