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

主营网站建设品牌网络零售的优势有哪些

主营网站建设品牌,网络零售的优势有哪些,html5 网站建设,百科网站怎么做本章目标 0.双向链表的基本结构 1.双向链表的初始化 2.头插尾插 3.头删尾删 4.查找与打印 5.在指定位置之前插入数据/在指定位置之后插入数据 6.在指定位置之前删除数据/在指定位置之后删除数据 7.销毁链表 0.双向链表的基本结构 本章所实现的双向链表是双向循环带头链表,是…

本章目标

0.双向链表的基本结构
1.双向链表的初始化
2.头插尾插
3.头删尾删
4.查找与打印
5.在指定位置之前插入数据/在指定位置之后插入数据
6.在指定位置之前删除数据/在指定位置之后删除数据
7.销毁链表

0.双向链表的基本结构

本章所实现的双向链表是双向循环带头链表,是stl中list容器的结构一致.
在这里插入图片描述
它有一个真正意义上的头结点,但该结点并不存储数据,我们一般管它叫做哨兵位.
它与单链表不同的是它的结点中有两个指向结点的指针,分别是前一个结点和下一个结点的指针.

typedef int listdatatype;struct listNode
{listdatatype data;struct listNode* prev;struct listNode* next;
};
typedef struct listNode listNode;

我们把数据类型和链表结点进行typedef方便后面我们进行实现该链表的函数.

1.双向链表的初始化

与单链表不同的是,每当我们创建链表的时候,需要创建一个新的哨兵位,然后才能将数据进行插入,删除操作.既然要创建一个新的结点,我们就需要将该逻辑进行分装,方便后续使用.

listNode* buyNode(listdatatype x)
{listNode* newnode = (listNode*)malloc(sizeof(listNode));if (!newnode){perror("malloc fail");exit(1);}newnode->data = x;newnode->next = newnode->prev = newnode;return newnode;
}

对于头节点的创建我们有两种方法,第一个中是在函数体内实现,另一种是传过来一个指针进行操作,如果时第二种方法,我们就需要传址,需要二级指针,如果传一级指针相当于传值操作,当函数结束的时候,函数栈帧会自动销毁,那么外面的指针就成为野指针了.

listNode* listinit()
{listNode* newnode = buyNode(-1);return newnode;}void listintalpha(listNode **pphead)
{*pphead = buyNode(-1);
}

因为该结点时头节点,并不存储数据,所以在创建结点时给的参数可以随便给.

2.头插尾插

2.1头插

在这里插入图片描述
对于头插来说,我们需要操作三个部分,哨兵位,哨兵位的下一个结点,newnode.
我们先讨论newndoe,要让它的prev指向哨兵位,next指向哨兵位的下一个结点,该操作时不会对链表产生影响的.我可以随意他们的顺序.
接着让哨兵位的下一个结点的prev指向newnode,然后再让哨兵位的next指向newnode.
该操作是有顺序要求的,如果先让哨兵位的next指向newnode,会找不到后面的链表,当然我们也可以提前保存一份,这样就可以随意操作了.

void listpushfront(listNode* phead, listdatatype x)
{assert(phead);listNode* newnode = buyNode(x);newnode->prev = phead;newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;
}

2.2.尾插

在这里插入图片描述
对于尾插来说,我们要操作的结点一共有三个,最后一个结点,哨兵位,newnode.
我们先操作对链表没有影响newnode,让它的prev的结点指向最后一个结点(头节点的prev结点)
让它的next结点指向哨兵位,然后让最后一个结点的下一个结点的指针指向newnode,让哨兵位的prev结点指向newnode.

void listpushback(listNode* phead,listdatatype x)
{assert(phead);listNode* newnode = buyNode(x);newnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}

3.头删尾删

3.0判断链表是否为空

当我们如果要进行删除操作的时候链表中一定是有元素的.我们可以将链表的判空封装成一个方法.
如果当前结点下一个结点仍然是当前结点就证明,该链表为空.

/判断是否非空
bool LTEmpty(listNode* phead)
{assert(phead);return phead->next == phead;
}

3.1头删

因为我们传过来的结点一定是哨兵位,我们删除的数据是它的下一个结点.为了防止丢失,我们可以提前将它保存为del.与它相关联的结点时哨兵位以及del的下一个结点,我们要让它的del的下一个结点的prev指向哨兵位,哨兵位的next指向del的下一个结点.然后释放del,置空.
该实现该函数的时候要注意判空.

void listpopfront(listNode* phead)
{assert(!LTEmpty(phead));listNode* del = phead->next;del->next->prev = phead;phead->next = del->next;free(del);del = NULL;
}

3.2尾删

对于尾删来说,我们要删除最后一个有数据的结点,与之关联的结点一共有两个,哨兵位以及它的前一个结点.我们要让它的前一个结点的next指向哨兵位,让哨兵位的prev指针指向要删除结点的前一个结点.然后释放该结点.我们可以提前保存该结点为del,方便操作.

void listpopback(listNode* phead)
{assert(!LTEmpty(phead));listNode* del = phead->prev;del->prev->next = phead;phead->prev = del->prev;free(del);del = NULL;
}

4.查找与打印

4.1查找

对于查找来说,它需要遍历整个链表,然后用当前值与该结点数据域中的值进行比对.如果找到就返回该结点,找不到就返回空.结束条件时当前结点等于哨兵位

listNode* listFind(listNode* phead, listdatatype x)
{listNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}

4.2打印

打印仍然时遍历链表,直到结束条件时当前结点等于哨兵位.

void print(listNode* phead)
{listNode* pcur = phead->next;while (pcur != phead){printf("%d->",pcur->data);pcur = pcur->next;}printf("\n");
}

5.在指定位置之前插入数据/在指定位置之后插入数据

5.1在指定位置之前插入数据

该函数实现涉及三个结点pos结点,pos结点的前一个结点.newnode.
我们让newnode的prev指向pos结点的前一个结点.它的next结点指向pos结点.
pos结点的前一个结点的next指针指向newnode,pos结点的prev指针指向newnode即可

void listinsertFront(listNode* pos, listdatatype x)
{assert(pos);listNode* newnode = buyNode(x);newnode->next = pos;newnode->prev = pos->prev;pos->prev->next = newnode;pos->prev = newnode;
}

5.2在指定位置之后插入数据

该方法实现涉及三个结点.pos结点.pos结点的下一个结点,newnode.
我们仍然newnode结点的prev和next分别指向pos结点和pos结点的下一个结点.
pos结点的下一个结点的prev指针指向newnode,pos结点的next指针指向newnode.

void listinsertBack(listNode* pos, listdatatype x)
{assert(pos);listNode* newnode = buyNode(x);newnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}

6.在指定位置之前删除数据/在指定位置之后删除数据

6.1在指定位置之前删除数据

我们先要将pos之前那个要删除的结点保存为del.
让del的前一个结点的next指针指向pos.
pos的prev指针指向del的前一个结点,然后释放del.
但再删除前仍然需要判空.

void listErasefront(listNode* pos)
{assert(!LTEmpty(pos));listNode* del = pos->prev;del->prev->next = pos;pos->prev = del->prev;free(del);del = NULL;
}

6.2在指定位置之后删除数据

我们要先将pos结点之后的那个要删除的结点保存为del,然后让del的下一个结点的prev指向pos.
pos的next指针指向del的下一个结点,然后释放del.

void listEraseback(listNode* pos)
{assert(!LTEmpty(pos));listNode* del = pos->next;del->next->prev = pos;pos->next = del->next;free(del);del = NULL;
}

7.销毁链表

与链表的初始化相对,它也有两种实现方式,但大体的思想都是循环销毁.

void destroyalpha(listNode** pphead)
{listNode* pcur = (*pphead)->next;while (pcur != (*pphead)){listNode* next = pcur->next;free(pcur);pcur = next;}free((*pphead));*pphead = NULL;
}void destroybata(listNode* phead)
{listNode* pcur = phead->next;while (pcur != phead){listNode* next = pcur->next;free(pcur);pcur = next;}free(phead);phead = NULL;}

但要注意第二种方式如果使用,我们需要再外面对结点置空,防止成为野指针,

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

相关文章:

  • 什么网站类型全球十大网站排名
  • 建c2c网站今日新闻最新10条
  • 互联网行业网站建设网络营销有哪些推广方式
  • 哪里找网站建设靠谱 知乎软文代写公司
  • 兰州网站seo费用千锋教育可靠吗
  • 网页网站开发手机游戏百度电脑版网页版入口
  • vue 做电商网站怎么去推广自己的店铺
  • 百度云 做视频网站35个成功的市场营销策划案例
  • 网站开发吃香吗整合营销网络推广
  • 哪里做网站域名不用备案百度人工客服在线咨询电话
  • 装修价格seo教程自学
  • 做网站被抓推广软文营销案例
  • 轻量应用云服务器搜索优化软件
  • 网站 psd高平网站优化公司
  • 昆明做网站优化哪家好微信广告推广如何收费
  • iis一个文件夹配置多个网站长沙靠谱的关键词优化
  • 公司网页如何建立优化营商环境心得体会2023
  • 娱乐论坛网站建设方案范文营销图片素材
  • 这2个代码 找做网站的 安装一下网络游戏推广平台
  • 昆山规模的网站建设公司有哪些免费网站谁有靠谱的
  • 单位网站建设的优势百度推广运营工作是什么
  • 如何做网站的301重定向泉州seo培训
  • 国内电商网站跳出率是多少最新新闻事件今天国内大事
  • 怎样做咨询网站aso优化哪家好
  • 福州做企业网站域名权重是什么意思
  • 西乡做网站哪家便宜深圳竞价托管公司
  • 网站制作模板下载电商seo名词解释
  • 长沙高校网站制作公司中国职业培训在线
  • jsp小型网站开发代码360seo排名优化服务
  • 建设像京东一样的网站厨师培训机构 厨师短期培训班