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

免费咨询做网站企业年金的好处和坏处

免费咨询做网站,企业年金的好处和坏处,数据库与网站建设,做有搜索功能的网站一、双向链表介绍 二、实现双向链表 1.定义双向链表的结构 2.双向链表的初始化 3.双向链表的尾插 4.双向链表的头插 5.双向链表的打印 6.双向链表的尾删 7.双向链表的头删 8.查找指定位置的数据 9.在指定位置之后插入数据 10.删除指定位置的数据 11.链表的销毁 三、…

一、双向链表介绍

二、实现双向链表

1.定义双向链表的结构

2.双向链表的初始化

3.双向链表的尾插

4.双向链表的头插

5.双向链表的打印

6.双向链表的尾删

7.双向链表的头删

8.查找指定位置的数据

9.在指定位置之后插入数据

10.删除指定位置的数据

11.链表的销毁

三、代码展示

一、双向链表介绍

双向链表就是带头双向循环链表,带头链表里的头结点,实际为"哨兵位",哨兵位节点不存储任何有效元素,它存在的意义是遍历循环链表避免死循环。哨兵位节点不能被删除,节点的地址也不能发生改变。

二、实现双向链表

1.定义双向链表的结构

我们看一张图,会发现,每个节点由三个部分组成:1.节点的数据 2.节点存放着指向下一个节点的指针next  3.节点存放着指向上一个节点的指针prev,所以我们定义如下:

typedef int LTData;//便于应用各种数据
typedef struct ListNode
{LTData data;//数据struct ListNode* next;//指向下一个节点的指针struct ListNode* prev;//指向上一个节点的指针
}LTNode;//重命名为LTNode方便表达

这个放在list.h里面,我们一共有三个文件,list.h list.c和test.c

2.双向链表的初始化

双向链表初始化,我们要初始化哨兵位,哨兵位没有值,所以节点里面没有有效的数据,那我们先完成一个前置函数LTBuyNode,用它来创建节点,步骤很简单:malloc开辟,然后检查是否开辟成功,成功就传数据。

注意:链表循环的条件是尾结点的next指针不为空,所以这里初始化的prev和next都指向节点本身,代码如下:

接着调用一下这个前置函数就可以了:

LTNode* LTBuyNode(LTData x)//创建节点
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));//malloc开辟一块空间if (node == NULL)//判断空间是否为空{perror("malloc fail!");exit(1);}node->data = x;//将数据给data//这里prev和next不能指向NULL,不然就是不循环了,所以让他们指向本身node->next = node->prev = node;return node;//返回节点
}
void LTInit(LTNode** pphead)
{*pphead = LTBuyNode(-1);//给双向链表创建一个哨兵位//哨兵位没有值,所以传一个-1
}

3.双向链表的尾插

双向链表的尾插有些复杂

1.双向链表是带环链表,所以是头尾相连的,如果设指向头结点的指针是phead,那么phead的prev指针指向的也就是尾结点。

2.尾插一个新节点,叫做newnode,那需要建立一个新节点,调用函数LTBuyNode();

3.现在有三个节点,分别是phead指向的头结点,phead->prev指向的尾结点以及要插入的节点newnode

4.newnode有两个指针,它现在是新的尾结点,所以她的next指针指向头结点phead,它的prev指针指向前一个节点也是就phead->prev指向的节点,那原来的尾结点的next指针也要改变,改完指向下一个节点也就是newnode,头结点的prev指针也要改变,现在它指向新的尾结点也就是newnode。

代码如下:     

void LTPushBack(LTNode* phead, LTData x)//传一级就够了,因为不用改变哨兵位的地址
{assert(phead);//断言确定不为空LTNode* newnode = LTBuyNode(x);//创建新节点//phead phead->prev newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}

4.双向链表的头插

头插基本思路和尾插一样,需要注意的是头插是插在第一个有效节点之前,也就是哨兵位之后

1.先调用LTBuyNode()函数创建一个新节点newnode

2.要将newnode插在phead和phead->next之间

3.newnode的next指针指向phead->next;newnode的prev指针指向phead

4.phead->next指针指向的节点的prev指针改变指向,现在指向newnode,phead指向节点的next指针改变指向,现在指向newnode。

代码如下:

void LTPushFront(LTNode* phead, LTData x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//创建新节点//phead newnode phead->nextnewnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}

5.双向链表的打印

双向链表的打印很简单,只需要遍历链表就可以,因为双向链表的第一个节点是哨兵位,不存储数据,所以我们只需要定义一个指针pcur指向头结点的下一个节点,然后循环就可以了,但是我们要知道循环的条件是什么,由于双向链表是带环链表,所以只需要让pcur不重新指回头结点即可。

代码如下:

        

void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;//第一个节点是哨兵位,不需要打印while (pcur != phead)//如果没有遍历回头结点,就不用停{printf("%d->", pcur->data);//打印每个节点的数据pcur = pcur->next;//节点往后遍历}printf("\n");
}

6.双向链表的尾删

1.明确要删的节点,头结点是phead,那phead->prev就是尾结点,也就是要删除的节点

2.定义一个新的指针del来接受phead->prev,那删除后,del->prev就是新节点

3.现在尾结点是del->prev,那它的next指针就是头结点,那头结点的prev指针也就是新的尾结点

4.记得释放掉del,并且将他置为空

代码如下:

void LTPopBack(LTNode* phead)
{//链表必须有效且链表不能为空assert(phead && phead->next != phead);LTNode* del = phead->prev;//phead del->prev deldel->prev->next = phead;phead->prev = del->prev;free(del);del = NULL;
}

7.双向链表的头删

头删思路和尾删差不多

1.定义一个新指针del是phead->next,也就是del要被删除

2.现在处理三个节点,分别是phead,del,del->next;

3.phead的next指针指向改变,改为指向del->next

4.del->next的prev指针指向改变,改为指向phead

5.最后记得free掉del,并将他置为NULL

代码如下:

void LTPopFront(LTNode* phead)
{//链表必须有效且链表不能为空assert(phead && phead->next != phead);LTNode* del = phead->next;phead->next = del->next;del->next->prev = phead;//删除del节点free(del);del = NULL;
}

8.查找指定位置的数据

查找就是遍历链表,定义一个指针pcur,当他没有循环一圈等于头结点phead的时候,就一直遍历;如果pcur指向的节点的data是要查找的数据,就返回,如果遍历完还是找不到,就返回NULL。

代码如下:

LTNode* LTFind(LTNode* phead, LTData x)
{LTNode* pcur = phead->next;//定义一个新指针,指向第一个有效的节点while (pcur != phead)//遍历双向链表{if (pcur->data == x)//如果找到了就返回pcur{return pcur;}pcur = pcur->next;//pcur每次向后移动一格}//没有找到return NULL;
}

在test.c里面测试一下:

9.在指定位置之后插入数据

这里就是三个节点:pos newnode pos->next

1.先用LTBuyNode()函数创立一个新节点newnode;

2.newnode的next指针指向pos->next

3.newnode的prev指针指向pos

4.pos->next指针指向的节点的prev改为指向newnode

5.pos指针指向的节点的next改为指向newnode

代码如下:

void LTInsert(LTNode* pos, LTData x)
{assert(pos);//断言防止为空LTNode* newnode = LTBuyNode(x);//pos newnode pos->nextnewnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}

10.删除指定位置的数据

删除pos,就要关注三个节点,pos->prev、pos、pos->next

1.首先pos->next的这个节点的prev指向改变,改为指向pos->prev

2.pos->prev指向的节点的next改变,改为指向pos->next

3.记得销毁pos

代码如下:

void LTErase(LTNode* pos)
{assert(pos);//断言防止为空//pos->prev pos pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;//销毁posfree(pos);pos = NULL;
}

11.链表的销毁

最后一步是链表销毁,那只需要遍历双向链表,然后一个一个free就可以了,注意哨兵位也是初始化时候创建的,也要销毁。

代码如下:

void LTDestroy(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = pcur->next;}free(phead);phead = NULL;
}

三、代码展示

list.h:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int LTData;//便于应用各种数据
typedef struct ListNode
{LTData data;//数据struct ListNode* next;//指向下一个节点的指针struct ListNode* prev;//指向上一个节点的指针
}LTNode;//重命名为LTNode方便表达void LTInit(LTNode** pphead);
void LTPrint(LTNode* phead);
void LTPushBack(LTNode* phead, LTData x);//传一级就够了
void LTPushFront(LTNode* phead, LTData x);
void LTPopBack(LTNode* phead);
void LTPopFront(LTNode* phead);void LTInsert(LTNode* pos, LTData x);
void LTErase(LTNode* pos);
LTNode* LTFind(LTNode* phead, LTData x);
void LTDestroy(LTNode* phead);	 

list.c:

#include "list.h"void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;//第一个节点是哨兵位,不需要打印while (pcur != phead)//如果没有遍历回头结点,就不用停{printf("%d->", pcur->data);//打印每个节点的数据pcur = pcur->next;//节点往后遍历}printf("\n");
}LTNode* LTBuyNode(LTData x)//创建节点
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));//malloc开辟一块空间if (node == NULL)//判断空间是否为空{perror("malloc fail!");exit(1);}node->data = x;//将数据给data//这里prev和next不能指向NULL,不然就是不循环了,所以让他们指向本身node->next = node->prev = node;return node;//返回节点
}
void LTInit(LTNode** pphead)
{*pphead = LTBuyNode(-1);//给双向链表创建一个哨兵位//哨兵位没有值,所以传一个-1
}void LTPushBack(LTNode* phead, LTData x)//传一级就够了,因为不用改变哨兵位的地址
{assert(phead);//断言确定不为空LTNode* newnode = LTBuyNode(x);//创建新节点//phead phead->prev newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}
void LTPushFront(LTNode* phead, LTData x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//创建新节点//phead newnode phead->nextnewnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}void LTPopBack(LTNode* phead)
{//链表必须有效且链表不能为空assert(phead && phead->next != phead);LTNode* del = phead->prev;//phead del->prev deldel->prev->next = phead;phead->prev = del->prev;free(del);del = NULL;
}void LTPopFront(LTNode* phead)
{//链表必须有效且链表不能为空assert(phead && phead->next != phead);LTNode* del = phead->next;phead->next = del->next;del->next->prev = phead;//删除del节点free(del);del = NULL;
}LTNode* LTFind(LTNode* phead, LTData x)
{LTNode* pcur = phead->next;//定义一个新指针,指向第一个有效的节点while (pcur != phead)//遍历双向链表{if (pcur->data == x)//如果找到了就返回pcur{return pcur;}pcur = pcur->next;//pcur每次向后移动一格}//没有找到return NULL;
}void LTInsert(LTNode* pos, LTData x)
{assert(pos);//断言防止为空LTNode* newnode = LTBuyNode(x);//pos newnode pos->nextnewnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}void LTErase(LTNode* pos)
{assert(pos);//断言防止为空//pos->prev pos pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;//销毁posfree(pos);pos = NULL;
}void LTDestroy(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = pcur->next;}free(phead);phead = NULL;
}

test.c:

#include "list.h"void test01()
{LTNode* plist = NULL;LTInit(&plist);LTPushBack(plist, 1);LTPushBack(plist, 1);LTPushBack(plist, 1);LTPushFront(plist, 3);LTPrint(plist);LTPopFront(plist);LTPrint(plist);
}void test02()
{LTNode* plist = NULL;LTInit(&plist);LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPrint(plist);LTNode* find = LTFind(plist, 1);if (find == NULL){printf("找不到!\n");}else{printf("找到了!\n");}}
int main()
{//test01();test02();return 0;
}


文章转载自:

http://Jw8gmB6s.qfqLd.cn
http://mlFdKKKr.qfqLd.cn
http://sm2bNss4.qfqLd.cn
http://b5m6Usc9.qfqLd.cn
http://SdQ7ENH4.qfqLd.cn
http://sNyRpKW9.qfqLd.cn
http://doBn6xDO.qfqLd.cn
http://qzZc2NAI.qfqLd.cn
http://6wsLz6x4.qfqLd.cn
http://tEQTKvGP.qfqLd.cn
http://7tMJj86u.qfqLd.cn
http://O5aT3bIL.qfqLd.cn
http://tyAYA3Tv.qfqLd.cn
http://2oaEcgvf.qfqLd.cn
http://kCj6Cm2V.qfqLd.cn
http://75Dus0yN.qfqLd.cn
http://JYFaOijQ.qfqLd.cn
http://TkJg6lKt.qfqLd.cn
http://UDNvXSnY.qfqLd.cn
http://IpqzDyLi.qfqLd.cn
http://JCbRKktA.qfqLd.cn
http://eOZJMFVg.qfqLd.cn
http://WGeVjkeh.qfqLd.cn
http://B9YblRqD.qfqLd.cn
http://CzxgB8m3.qfqLd.cn
http://syAGXRsF.qfqLd.cn
http://vrPyOapC.qfqLd.cn
http://CiwPrxxu.qfqLd.cn
http://Y9vfxEmS.qfqLd.cn
http://kCmmNOg7.qfqLd.cn
http://www.dtcms.com/wzjs/773764.html

相关文章:

  • 网站关键字设置格式海外网红营销平台
  • 学生登录入口深圳sem优化
  • 个人租车网站源码如何在百度提交网站
  • 如何做论坛网站 知乎上海制作企业网站
  • 做静态网站步骤建设银行网站e动终端
  • 著名网站用什么语言做后台急速浏览器打开新网站
  • 企业网站首页设计重庆网站制作服务
  • 公司网站建设计入科目烟台网络科技有限公司排名
  • 北京网站建设公司完美湖南岚鸿首 选页面设计层级一般控制
  • 朝阳做网站哪家公司好wordpress修改发布页面插件
  • 自助建站源码php现在最火的推广平台有哪些
  • 网站制作报价图片欣赏wordpress插件连不上
  • 做微信公众号的网站外贸网站建设步骤
  • vs和sql怎么做网站网站开发实用技术 代码
  • 电子商务网站建设的规划和实施怎样制作网站教程哪家好
  • 枣庄建设局网站天猫入驻
  • 网站建设方法wordpress 登陆不跳转
  • 网站开发有哪些服务器做网站三大主流框架
  • 河源正规网站建设价格泉州微信网站建设
  • 黄山网站建设推荐北京网站设计制作关键词
  • 房产网站建设方案论文网站建设的基本流程包括
  • 支付网站搭建化妆品做网站流程
  • 网站建设导航栏变化网站权重是什么意思
  • 做企业展示网站个人网站备案通过后
  • 手机wap网站建站系统求一个手机能看的网站
  • 网站调用优酷视频去除广告企业品牌宣传片制作
  • 淘宝客单页网站程序wordpress标签不输出文章
  • 怎样增加网站权重外贸网络营销平台
  • 蓝色清爽网站上海市中小企业服务中心
  • 网站建设交互效果网站资源建设