(C/C++学习)18.C语言双向链表
说明:数组提供了连续内存空间的访问和使用,而链表是对内存零碎空间的有效组织和使用。链表又分为单向链表和双向链表,单向链表仅提供了链表的单方向访问,相比之下,双向链表则显得十分方便。
一.单向链表的节点
如下代码所示,双向链表的节点包含两个指向关系和一个数据空间,两个指向分别连接该节点的上一个和下一个节点,数据类型可以是一个结构体类型,也可以是其他类型。
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语言双向链表的更多相关文章
- GO学习-(18) Go语言基础之并发
Go语言基础之并发 并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微 ...
- c语言学习书籍推荐《C语言学习路线图•C语言必须知道的300个问题》下载
下载地址:点我 <C语言学习路线图•C语言必须知道的300个问题>以基础知识为框架,介绍了c语言各部分知识所对应的常见开发疑难问题,并作了透彻地解析.<C语言学习路线图•C语言必须知 ...
- GO学习-(19) Go语言基础之网络编程
Go语言基础之网络编程 现在我们几乎每天都在使用互联网,我们前面已经学习了如何编写Go语言程序,但是如何才能让我们的程序通过网络互相通信呢?本章我们就一起来学习下Go语言中的网络编程. 关于网络编程其 ...
- 值得学习的C语言开源项目
值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工 ...
- [java学习笔记]java语言核心----面向对象之this关键字
一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理: 代表的是当前对象. this就是所在函数 ...
- [java学习笔记]java语言核心----面向对象之构造函数
1.构造函数概念 特点: 函数名与类名相同 不用定义返回值类型 没有具体的返回值 作用: 给对象进行初始化 注意: 默认构造函数 多个构造函数是以重载出现的 一个类中如果 ...
- Java学习笔记:语言基础
Java学习笔记:语言基础 2014-1-31 最近开始学习Java,目的倒不在于想深入的掌握Java开发,而是想了解Java的基本语法,可以阅读Java源代码,从而拓展一些知识面.同时为学习An ...
- IOS学习笔记07---C语言函数-printf函数
IOS学习笔记07---C语言函数-printf函数 0 7.C语言5-printf函数 ------------------------- ----------------------------- ...
- IOS学习笔记06---C语言函数
IOS学习笔记06---C语言函数 -------------------------------------------- qq交流群:创梦技术交流群:251572072 ...
随机推荐
- [Android6.0][RK3399] 双屏异显代码实现流程分析(二)【转】
本文转载自:http://blog.csdn.net/dearsq/article/details/55050125 Patch Code dtsi rk3399-androiddtsi rk3399 ...
- [翻译]NUnit---Action Attributes(八)
Attributes NUnit 1.0使用传统的基于继承和命名约定来识别测试.从2.0开始NUnit使用自定义特性来实现. 因为NUnit的test fixtures不是从框架类库继承,所以开发人员 ...
- Java 泛型 一
泛型在Java中有很重要的地位,网上很多文章罗列各种理论,不便于理解,本篇将立足于代码介绍.总结了关于泛型的知识. 先看下面的代码: List list = new ArrayList(); list ...
- codemirror插件-文件比较组件merge
目的: 为了实现文件比较功能 引用文件 从github下载项目后,从以下路径引用文件,其中部分github分支中codemirror.js 需要运行项目,自动合成 <link rel=style ...
- E20180113-hm
round robin algorithm 轮询调度算法 circular adj. 圆形的; 环行的; 迂回的,绕行的; 供传阅的,流通的;
- 洛谷 P2365 任务安排【dp】
其实是可以斜率优化的但是没啥必要 设st为花费时间的前缀和,sf为Fi的前缀和,f[i]为分组到i的最小花费 然后枚举j转移,考虑每次转移都是把j到i分为一组这样意味着j及之后的都要增加s的时间,同时 ...
- 商品期货高频交易策略Tick框架
原帖地址:https://www.fmz.com/bbs-topic/1184在商品期货高频交易策略中, Tick行情的接收速度对策略的盈利结果有着决定性的影响,但市面上大多数交易框架,都是采用回调模 ...
- 【洛谷4721】【模板】分治FFT(CDQ分治_NTT)
题目: 洛谷 4721 分析: 我觉得这个 "分治 FFT " 不能算一种特殊的 FFT ,只是 CDQ 分治里套了个用 FFT (或 NTT)计算的过程,二者是并列关系而不是偏正 ...
- Android 性能优化(26)*性能工具之「Batterystats,Battery Historian」Batterystats & Battery Historian Walkthrough
Batterystats & Battery Historian Walkthrough Working with Batterystats & Battery Historian B ...
- JavaScript 正则表达式(转自 mozilla)
正则表达式是被用来匹配字符串中的字符组合的模式.在JavaScript中,正则表达式也是对象. 这种模式可以被用于 RegExp 的 exec 和 test 方法以及 String 的 match.r ...