文章目录

  • 前言
  • 头插法
  • 尾插法
  • 删除节点
  • 测试代码如下

前言

双向链表和单链表的唯一区别就是多个一个指针域而已,该指针域可以访问链表的上一个节点。

关于构造双向链表的过程我们常见的有两种方法,和单链表一样:头插法和尾插法。
头插法:字面意思也是很好理解,每次插入的元素在上一个节点之前
尾插法:字面意思也表达出了每次的元素插入会在上一个节点之后
详细插入过程可以参考如下


头插法

头插法基本过程如下图,已经描述的很清楚了

简单讲一下,这里需要有一个指向的顺序问题
第三步和第四步是需要有先后关系的
第三步: head -> next -> prev = p ,这一步是更新head节点下一个节点的pre域链接的;而第四步: head -> next = p,则是更新head的next域。
如果第四步在前,第三步的head -> next -> prev 就变为了 p -> prev = p,显然不合理。

实现算法如下(文末有完整源码)

Data *insert_head(int n) {Data *head = (Data *)malloc(sizeof(Data));head->next = NULL;head -> prev = head;Data *r = head -> next;while (n--){int tmp;Data *p = (Data *)malloc(sizeof(Data));scanf("%d", &tmp);p -> data = tmp;/*考虑头节点的next域为空,防止访第3步head->next->prev访问到空的指针*/if (head -> next == NULL) { p -> next = NULL;p -> prev = head;head -> next = p;} else{p -> next = head -> next;p -> prev = head;head -> next -> prev = p;head -> next = p;}}return head -> next;
}

尾插法

具体步骤如下:

具体指向的过程看图就可以,非常清晰
这里多了一个第五步,是为了保证临时节点r的移动,持续指向插入节点的上一个节点。
实现代码如下:

Data *insert_tail(int n){Data *head = (Data *)malloc(sizeof(Data));head->next = NULL;head -> prev = head;Data *r = head;while (n --){int tmp;Data *p = (Data *)malloc(sizeof(Data));scanf("%d", &tmp);p -> data = tmp;/*同样为了防止第三部 r->next->prev访问到了空节点,提前进行处理*/if (r -> next == NULL) {p -> next = NULL;p -> prev = r;r -> next = p;} else  {p -> next = NULL;p ->prev = r;r -> next -> prev = p;r -> next = p;}r = p;}return head -> next;
}

删除节点

删除过程很简单,主要是上下节点的直接指向:

  1. 找到要删除的节点p,以及其上一个节点r
  2. 重新指向r的next域,跳过需要删除的节点
Data *delete_list(Data *head, int data) {Data *p;Data *r = head ;/*找到要删除的节点,命名为p,同时需要获取p的上一个节点r*/while (r->next) {if (r-> next ->data == data) {p = r->next;break;}r = r->next;}/*删除节点p*/r->next = p -> next;p->next->prev = r;p = NULL;return head;
}

测试代码如下

#include <stdio.h>
#include <stdlib.h>typedef struct DoubleLink {int data;struct DoubleLink *next;struct DoubleLink *prev;
}Data;/*打印链表,先next顺序打印,再prev逆序打印*/
void print_list(Data *head) {if(head == NULL)return;printf("next \n");while (head -> next) {printf("%d ",head->data);head = head -> next;}printf("%d\n",head->data);Data *p = head;printf("\nprev \n");while (p -> prev != p) {printf("%d ",p->data);p = p ->prev;}printf("\n");
}/*尾插法*/
Data *insert_tail(int n){Data *head = (Data *)malloc(sizeof(Data));head->next = NULL;head -> prev = head;Data *r = head;while (n --){int tmp;Data *p = (Data *)malloc(sizeof(Data));scanf("%d", &tmp);p -> data = tmp;if (r -> next == NULL) {p -> next = NULL;p -> prev = r;r -> next = p;} else  {p -> next = NULL;p ->prev = r;r -> next -> prev = p;r -> next = p;}r = p;}return head -> next;
}/*头插法*/
Data *insert_head(int n) {Data *head = (Data *)malloc(sizeof(Data));head->next = NULL;head -> prev = head;Data *r = head -> next;while (n--){int tmp;Data *p = (Data *)malloc(sizeof(Data));scanf("%d", &tmp);p -> data = tmp;if (head -> next == NULL) {p -> next = NULL;p -> prev = head;head -> next = p;} else{p -> next = head -> next;p -> prev = head;head -> next -> prev = p;head -> next = p;}}return head -> next;}/*删除链表,删除节点data为2的链表*/
Data *delete_list(Data *head, int data) {if(head == NULL)return NULL;Data *p;Data *r = head ;while (r->next) {if (r-> next ->data == data) {p = r->next;break;}r = r->next;}r->next = p -> next;p->next->prev = r;p = NULL;return head;
}int main()
{printf("construct the double list tail\n");Data * head = insert_tail(5);print_list(head);printf("construct the double list head\n");Data * tail = insert_head(5);print_list(tail);printf("delete the double list node\n");Data * test = insert_head(5);Data *result = delete_list(test,2);print_list(result);return 0;
}

输出结果如下:

construct the double list tail
1 2 3 4 5next
1 2 3 4 5
prev
5 4 3 2 1 construct the double list head
1 2 3 4 5next
5 4 3 2 1
prev
1 2 3 4 5 delete the double list node
1 2 3 4 5
next
5 4 3 1
prev
1 3 4 5

C语言的双向链表头插法和尾插法,指定节点删除相关推荐

  1. 单链表的头插法和尾插法c语言实现

    /*单链表的头插法和尾插法c语言实现*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #d ...

  2. c语言 链表建立头插法尾插法,单链表的创建(头插法和尾插法)

    单链表的创建分为头插法和尾插法,头插法是不断地向头结点插入新的结点.这样会使你所插入的结点值呈现逆序,所以头插法也可以实现单链表的逆置.尾插法是不断地向插入的新元素之后再插入新的元素.需要注意的是头插 ...

  3. 采用头插法和尾插法建立单链表

    面说一下如果用C语言建立单链表,分为头插法和尾插法两种. 采用头插法建立单链表 该方法从一个空表开始,生成新结点,并将读取到的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头,即头结点之后 ...

  4. 计算机软件技术 上海电力学院,上海电力学院 计算机软件技术 实验三 用头插法和尾插法创建线性表...

    上海电力学院计算机软件技术实验三用头插法和尾插法创建线性表 #include #define MAXLEN 9 struct table {int key; int othererm; } ; typ ...

  5. 数据结构学习(二)——单链表的操作之头插法和尾插法创建链表

    http://blog.csdn.net/abclixu123/article/details/8210109 链表也是线性表的一种,与顺序表不同的是,它在内存中不是连续存放的.在C语言中,链表是通过 ...

  6. 头插法和尾插法创建链表(有无头结点)

    头插法和尾插法创建链表(有无头结点) 文章目录 头插法和尾插法创建链表(有无头结点) 1 头插法 1.1头插法建表规则: 1.2 头插法建表代码实现 2 尾插法 2.1 尾插法建表规则: 2.2 尾插 ...

  7. 头插法和尾插法的详细区别

    浅析线性表(链表)的头插法和尾插法的区别及优缺点 线性表作为数据结构中比较重要的一种,具有操作效率高.内存利用率高.结构简单.使用方便等特点,今天我们一起交流一下单向线性表的头插法和尾插法的区别及优缺 ...

  8. 双向循环链表的头插法和尾插法

    我们平常学链表的时候会学单向不循环链表,单向循环链表,双向不循环链表,双向循环链表及内核链表,各种格式的链表.今天我因为忘记双向循环链表的头插法和尾插法的顺序了,特意写一篇文章来巩固一下.首先我根据顺 ...

  9. 头插法和尾插法建立带头节点的单链表

    有两种方法建立单链表,尾插法和头插法,他们的区别是:头插法是按照输入元素倒序建立,为尾插法为顺序插入,并且多一个尾节点,我们一般使用尾插法. 一.头插法 代码为: pCurr -> next = ...

最新文章

  1. pandas根据数据类型筛选数据
  2. 工作中Oracle常用的SQL
  3. WPF与缓动(一) N次缓动
  4. 深度学习在推荐领域的应用
  5. 1 时间序列基本概念
  6. Java学习笔记(二):String
  7. KeyMob手机聚合平台已集成多家移动广告平台
  8. 第五章:逻辑回归(Logistic 回归)
  9. POJ-3259-Wormholes
  10. roboware下载链接
  11. 爬取中国地震台网以及地震科学数据
  12. 西数发布首款消费级SSD:蓝盘、绿盘齐飞
  13. [uboot]What is MLO file?
  14. 测试韩国真假唇釉软件,3ce蓝管唇釉怎么辨别真假 3ce唇釉推荐色号
  15. windows防火墙开端口失败
  16. 通用爬取文章及图片导出到Word主程序代码
  17. ERROR:ORA-01031:insufficient privileges完美解决方法
  18. windows7蓝牙怎么打开_英特尔升级WiFi 和蓝牙驱动,Win10 更新5月版稳了
  19. 微信小程序textarea换行输入的文本,在view中如何换行渲染
  20. 最主流的视频剪辑软件,附安装包

热门文章

  1. 杂谈 - 开始认认真真写博客了
  2. 30 个 php 操作 redis 常用方法代码例子
  3. msvcrt.lib和LIBCD.lib链接冲突
  4. There is no Citrix MetaFrame server configured on the specified address错误的解决方法
  5. php把单词切割成数组,PHP – 将单词分解为数组
  6. 中断原理在计算机中的应用,计算机组成原理期末考试简答题重点
  7. input限制文字个数但是输入中文时会被切断_Python文字转换语音,让你的文字会「说话」抠脚大汉秒变撒娇萌妹...
  8. Python OpenCV分水岭算法分割和提取重叠或有衔接的图像中的对象
  9. Flume基础及Flume高质量博客合集
  10. 数据结构--树和二叉树