说明:数组提供了连续内存空间的访问和使用,而链表是对内存零碎空间的有效组织和使用。链表又分为单向链表和双向链表,单向链表仅提供了链表的单方向访问,相比之下,双向链表则显得十分方便。

一.单向链表的节点

如下代码所示,双向链表的节点包含两个指向关系和一个数据空间,两个指向分别连接该节点的上一个和下一个节点,数据类型可以是一个结构体类型,也可以是其他类型。

  1 typedef struct node
2 {
3 int data;
4 struct node *pre;
5 struct node *next;
6 }Node;

二.双向链表的创建

头插法和尾插法只看代码比较难以与理解,建议画出插入节点时的链表变化图则会非常容易理解,另外,个人认为头插法较优,因为其插入逻辑一步到位,不像尾插法还需在后面完成双向链表的环状连接。

1.头插法

  1 Node * creatList()
2 {
3 Node * head = (Node*)malloc(sizeof(Node));
4 Node * cur = NULL;
5 head->next = head;
6 head->pre = head;
7 int data;
8 scanf("%d",&data);
9 while(data)
10 {
11 cur = (Node*)malloc(sizeof(Node));
12 cur->data = data;
13 cur->next = head->next;
14 cur->pre = head;
15 head->next = cur;
16 cur->next->pre = cur;
17 scanf("%d",&data);
18 }
19 return head;
20 }

2.尾插法

  1 Node * creatList()
2 {
3 Node * head = (Node*)malloc(sizeof(Node));
4 Node * phead = head;
5 Node * cur = NULL;
6 phead->next = NULL;
7 phead->pre = NULL;
8 int data;
9 scanf("%d",&data);
10 while(data)
11 {
12 cur = (Node*)malloc(sizeof(Node));
13 cur->data = data;
14 phead->next = cur;
15 cur->pre = phead;
16 phead = cur;
17 scanf("%d",&data);
18 }
19 //完成回环
20 cur->next = head;
21 head->pre = cur;
22 return head;
23 }

三.双向链表的元素插入(头插法)

插入方法:先让插入的节点有所指向,再考虑指向它的指针,具体插入如下:

  1 void insertList(Node * head)
2 {
3 printf("intsert new node:");
4 int data;
5 scanf("%d",&data);
6 Node * cur;
7 cur = (Node*)malloc(sizeof(Node));
8 cur->data = data;
9 cur->next = head->next;
10 cur->pre = head;
11 head->next = cur;
12 cur->next->pre = cur;
13 }

四.双向链表的查找

既然是双向链表,其查找方式也应该是是双向查找,比起单向链表的单向查找,双向查找同时从两个方向进行查找,加快了查找的速度。

  1 Node * searchList(Node * head,int find)
2 {
3 Node * pClock = head->next;
4 Node * pAntiClock = head->pre;
5 while (pAntiClock != pClock->pre)
6 {
7 if(pClock->data == find)
8 return pClock;
9 if(pAntiClock->data == find)
10 return pAntiClock;
11 if(pClock == pAntiClock)
12 return NULL;
13 pClock = pClock->next;
14 pAntiClock = pAntiClock->pre;
15 }
16 return NULL;
17 }

五.删除某个节点

  1 void deleteList(Node * pfind)
2 {
3 if(pfind == NULL)
4 return;
5 else
6 {
7 pfind->pre->next = pfind->next;
8 pfind->next->pre = pfind->pre;
9 free(pfind);
10 }
11 }

六.链表排序(按值排序)

  1 void sortList(Node * head,int n)
2 {
3 Node * p,*q;
4 for(int i=0; i<n-1; i++)
5 {
6 p = head->next;
7 q = p->next;
8 for(int j=0; j<n-1-i; j++)
9 {
10 if(p->data > q->data)
11 {
12 p->data = p->data ^ q->data;
13 q->data = p->data ^ q->data;
14 p->data = p->data ^ q->data;
15 }
16 p = p->next;
17 q = q->next;
18 }
19 }
20 }

七.链表的销毁

  1 void destroyList(Node * head)
2 {
3 head->pre->next = NULL;
4 Node * pre = head;
5 while(head != NULL)
6 {
7 head = head->next;
8 free(pre);
9 pre = head;
10 }
11 }

说明:链表的操作还有如求长度、打印以及交换指针排序等,由于相对较为简单,此处就不再例举。重要提醒:链表的某些操作较难理解,最好画图加以辅助理解。

(C/C++学习)18.C语言双向链表的更多相关文章

  1. GO学习-(18) Go语言基础之并发

    Go语言基础之并发 并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微 ...

  2. c语言学习书籍推荐《C语言学习路线图•C语言必须知道的300个问题》下载

    下载地址:点我 <C语言学习路线图•C语言必须知道的300个问题>以基础知识为框架,介绍了c语言各部分知识所对应的常见开发疑难问题,并作了透彻地解析.<C语言学习路线图•C语言必须知 ...

  3. GO学习-(19) Go语言基础之网络编程

    Go语言基础之网络编程 现在我们几乎每天都在使用互联网,我们前面已经学习了如何编写Go语言程序,但是如何才能让我们的程序通过网络互相通信呢?本章我们就一起来学习下Go语言中的网络编程. 关于网络编程其 ...

  4. 值得学习的C语言开源项目

    值得学习的C语言开源项目   - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工 ...

  5. [java学习笔记]java语言核心----面向对象之this关键字

    一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理:         代表的是当前对象.         this就是所在函数 ...

  6. [java学习笔记]java语言核心----面向对象之构造函数

    1.构造函数概念 特点: 函数名与类名相同 不用定义返回值类型 没有具体的返回值 作用:                给对象进行初始化 注意: 默认构造函数 多个构造函数是以重载出现的 一个类中如果 ...

  7. Java学习笔记:语言基础

    Java学习笔记:语言基础 2014-1-31   最近开始学习Java,目的倒不在于想深入的掌握Java开发,而是想了解Java的基本语法,可以阅读Java源代码,从而拓展一些知识面.同时为学习An ...

  8. IOS学习笔记07---C语言函数-printf函数

    IOS学习笔记07---C语言函数-printf函数 0 7.C语言5-printf函数 ------------------------- ----------------------------- ...

  9. IOS学习笔记06---C语言函数

    IOS学习笔记06---C语言函数 --------------------------------------------  qq交流群:创梦技术交流群:251572072              ...

随机推荐

  1. 123 c#调用oracle存储过程返回数据集 --通过oracle存储过程返回数据集

    c#调用oracle存储过程返回数据集 2008-12-20 10:59:57|  分类: net|字号 订阅   CREATE OR REPLACE PACKAGE pkg_tableTypeIS  ...

  2. php语法错误导致服务器错误(500)解决

    PHP编码出错不提示,而是提示500错误,这对于开发来说,是很不方便的.下面讲解如何开启错误提示步骤: 1. 打开php.ini文件.以我的ubuntu为例,这个文件在: /etc/php5/apac ...

  3. 什么是需求Bug、设计Bug、功能bug?

    首先什么是需求Bug.设计Bug.功能bug? 需求Bug,指由于客户需求描述不清晰或错误.需求收集人员自身原因及需求本身模糊难于分析.获取等原因,导致客户需求获取不准确,后期产品不能满足客户.用户的 ...

  4. asp.net mvc6学习资料整理

    十分钟轻松让你认识ASP.NET MVC6 http://www.cnblogs.com/n-pei/p/4272105.html ASP.NET 5系列教程 (六): 在 MVC6 中创建 Web ...

  5. hdu4738(边双连通分量,桥)

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. [App Store Connect帮助]六、测试 Beta 版本(4.2) 管理 Beta 版构建版本:查看构建版本状态和指标

    必要职能:“帐户持有人”职能.“管理”职能.“App 管理”职能.“开发者”职能或“营销”职能.请参见职能权限. 在首页上,点按“我的 App”,选择您的 App,然后在工具栏中点按“TestFlig ...

  7. [Swift通天遁地]一、超级工具-(11)使用EZLoadingActivity制作Loading加载等待动画

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  8. Cmake编译protobuf

    编译指令,在powershell中执行 :      .\protoc.exe .\ive.proto --cpp_out .      .\protoc.exe .\ive.proto --csha ...

  9. Nginx开启http2访问和gzip网页压缩功能

    准备工作   如果Nginx要开启http2需要满足以下2个条件: nginx >=1.9.5 openSSL >= 1.0.2 所以这里我们首先要检查Nginx的版本如果没有安装要先安装 ...

  10. 基于Web的Kafka管理器工具之Kafka-manager的编译部署详细安装 (支持kafka0.8、0.9和0.10以后版本)(图文详解)(默认端口或任意自定义端口)

    不多说,直接上干货! 至于为什么,要写这篇博客以及安装Kafka-manager? 问题详情 无奈于,在kafka里没有一个较好自带的web ui.启动后无法观看,并且不友好.所以,需安装一个第三方的 ...