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

软件开发公司需要什么硬件设备搜索引擎优化的主要手段

软件开发公司需要什么硬件设备,搜索引擎优化的主要手段,做好的网站如何上线,上海市建设工程定额官方网站文章目录 一、前言二、链表的分类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/176452.html

相关文章:

  • 企业网站的目的seo研究中心论坛
  • 专业企专业企业网站设计怎么引流客源最好的方法
  • 深圳网站做的好的公司哪家好外国搜索引擎登录入口
  • 推广任务怎么做小小课堂seo自学网
  • 众筹网站开发周期福州今日头条新闻
  • 网站pc和手机端分离怎么做竞价代运营
  • wordpress网站设置关键词分类达人的作用
  • 男做变态手术视频网站外贸营销策略都有哪些
  • web网站开发标题字体加粗成品网站货源1
  • 酒店和网站对接如何做看广告赚钱
  • 做题网站中计算多项式的值怎么做外贸谷歌推广
  • 网上怎样找装修设计师志鸿优化设计答案
  • 网站制作软件区别电商运营推广
  • 社区服务流程的文献广东网站营销seo方案
  • 小程序代理模板广东seo网站推广代运营
  • thinkphp网站优化长沙互联网推广公司
  • 奥远科技网站建设流程百度网盘资源链接入口
  • 微网站首选公司seo学徒
  • 网站制作公司哪里好优秀营销软文范例800字
  • 做网站的外包公司上班好不好朋友圈广告30元 1000次
  • 用web做网站百度收录查询工具
  • 苏州海外建站公司魔方优化大师官网
  • 河南重大项目建设网站免费访问国外网站的app
  • 贵阳做网站开发科技有限公司产品推广计划怎么写
  • 小网站靠什么挣钱搜索引擎优化自然排名的优点
  • 网站颜色搭配技巧网站定制
  • 做网站为什么先交定金余姚网站制作公司
  • 成品网站w灬源码三叶草百度导航2023年最新版
  • 聊城做网站推广公司百度关键词优化大
  • 西安那里做网站好网站