手撸双链表,图解

C语言,链表

C++实现单向链表

深入理解Linux内核链表

跟单链表不同,双链表的节点包含两个指针,一个指针指向上一个元素,一个指针指向下一个元素。

▌如下图

学习数据结构的时候,要像认识一个人一样,要了解这个人有什么特点,比如喜欢打球,喜欢喝酒之类的。学习数据结构也是一样,要了解数据结构的特点。

我们要学习双链表,需要搞明白链表这几个特点

  1. 创建链表

  2. 往链表插入数据

  3. 删除链表中的某个数据

  4. 删除整个链表

  5. 查找链表

  6. 反转链表

▌先看看如何创建一个链表

创建一个链表无非就是搞定链表头,没有头的链表就是死链表,有头就表示这个链表是存在的。当然了,可能会存在循环链表,只有位置,没有固定的头指针

创建一个pHead,并且以后pHead头指针保持不动,就表示我们创建好了一个链表头指针。

typedef struct Node{struct Node *prev;struct Node *next;int elements;
}pNode;pNode * CreateHead(void)
{pNode *head = NULL;head = (pNode *)malloc(sizeof(struct Node));head->next = NULL;head->prev = NULL;return head;
}

▌插入元素

插入元素的方式有多种,可以头插,可以尾插,也可以任意插,我只写了简单的插入方式-尾插。

int InsertElement(pNode *head,int element)
{if(head == NULL){PRINTK_LINK("Head NULL\n");return (-1);}pNode * pTemp = head;while(pTemp->next != NULL){pTemp = pTemp->next;}pNode * pElement = (pNode *)malloc(sizeof(struct Node));pElement->elements = element;pTemp->next = pElement;pElement->prev = pTemp;PRINTK_LINK("Element:%d\n",element);return (0);
}

▌遍历一个链表

遍历链表是常规的操作,但是遍历链表的方法有很多种,可以从头开始遍历,可以从尾部开始,在涉及二分查找的时候可以从中间某个位置开始遍历。虽然方法很多,但是我只写了一种方法,就是从头开始遍历链表,因为是最简单的。

int TraverseLink(pNode *head)
{if(head == NULL){PRINTK_LINK("Head NULL\n");return (-1);}pNode * pTemp = head;while(pTemp->next != NULL){pTemp = pTemp->next;PRINTK_LINK("Element:%d\n",pTemp->elements);}return (0);
}

▌删除链表

删除整个链表是把链表的每个元素都删除,并且把头也删除,并且把头指针指向NULL。如果需要找到链表中的某个元素并删除,就需要先找到链表中的元素,删除掉,并且把前后的两个元素连在一起。

int DeleteLink(pNode *head)
{if(head == NULL){PRINTK_LINK("Head NULL\n");return (-1);}pNode * pTemp = head;while(pTemp->next != NULL){pTemp = pTemp->next;}while(pTemp != NULL){free(pTemp);        pTemp = NULL;pTemp = pTemp->prev;}return (0);
}

▌完整代码

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define LOG_TAG "[LINK]: %s() line: %d "
#define PRINTK_LINK(fmt, args...)  printf(LOG_TAG fmt, __FUNCTION__, __LINE__,  ##args)typedef struct Node{struct Node *prev;struct Node *next;int elements;
}pNode;pNode * CreateHead(void)
{pNode *head = NULL;head = (pNode *)malloc(sizeof(struct Node));head->next = NULL;head->prev = NULL;return head;
}int InsertElement(pNode *head,int element)
{if(head == NULL){PRINTK_LINK("Head NULL\n");return (-1);}pNode * pTemp = head;while(pTemp->next != NULL){pTemp = pTemp->next;}pNode * pElement = (pNode *)malloc(sizeof(struct Node));pElement->elements = element;pTemp->next = pElement;pElement->prev = pTemp;PRINTK_LINK("Element:%d\n",element);return (0);
}int TraverseLink(pNode *head)
{if(head == NULL){PRINTK_LINK("Head NULL\n");return (-1);}pNode * pTemp = head;while(pTemp->next != NULL){pTemp = pTemp->next;PRINTK_LINK("Element:%d\n",pTemp->elements);}return (0);
}int DeleteLink(pNode *head)
{if(head == NULL){PRINTK_LINK("Head NULL\n");return (-1);}pNode * pTemp = head;while(pTemp->next != NULL){pTemp = pTemp->next;}while(pTemp != NULL){free(pTemp);pTemp = pTemp->prev;}return (0);
}int main()
{pNode * pHead = CreateHead();InsertElement(pHead,13);InsertElement(pHead,8);InsertElement(pHead,0);InsertElement(pHead,4);InsertElement(pHead,485);InsertElement(pHead,94);TraverseLink(pHead);DeleteLink(pHead);return 0;
}

▌程序输出

ubuntu1804:~/c$ gcc shuanglianbiao.c && ./a.out
[LINK]: InsertElement() line: 40 Element:13
[LINK]: InsertElement() line: 40 Element:8
[LINK]: InsertElement() line: 40 Element:0
[LINK]: InsertElement() line: 40 Element:4
[LINK]: InsertElement() line: 40 Element:485
[LINK]: InsertElement() line: 40 Element:94
[LINK]: TraverseLink() line: 56 Element:13
[LINK]: TraverseLink() line: 56 Element:8
[LINK]: TraverseLink() line: 56 Element:0
[LINK]: TraverseLink() line: 56 Element:4
[LINK]: TraverseLink() line: 56 Element:485
[LINK]: TraverseLink() line: 56 Element:94

▌总结

我上面的代码只设计了链表头,如果设计链表尾部指针,应用会更加灵活。

相比于单链表,双链表的操作会更加灵活,当然,每一个节点都需要新增一个指向于上一个位置的指针。

双链表还可以把头尾连接起来变成一个环形队列。

链表相对于数组来说,插入和删除数据非常快,因为不需要移动数据,只需要改变指针的指向。

双链表内存利用率高,如果是内存紧张的硬件设备,使用链表操作可以节省内存。相对于数组,链表可以做到按需分配内存

链表是一种基础的数据结构,建议做到自己能写出一个链表,不要求十全十美,我曾经面试遇到让我手撸一个栈。相对于那些C语言基础,写代码更能彰显程序员的技术。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VS建lUML画类图

https://blog.csdn.net/caoshangpa/article/details/79797849

C++学习方法

1.把C当成一门新的语言学习(和C没啥关系!真的。);   2.看《Thinking In C》,不要看《C变成死相》;   3.看《The C Programming Language》和《Inside The C Object Model》,不要因为他们很难而我们自己是初学者所以就不看;   4.不要被VC、BCB、BC、MC、TC等词…

IBM DS300 安装

还是不太习惯51的BLOG,用多了其它网站的!转载于:https://blog.51cto.com/jackzzs/145512

Python编程之数据结构与算法练习_004

Some排序算法的Python实现。不废话写原理,直接撸代码。 1.Bubble sort 冒泡排序 import random import copymaxSize 10000 maxValue 10000#Generate random data array[0]*maxSize for i in range(maxSize):array[i] random.randint(10,maxValue)#Correct method…

STM32串口用中断还是用轮询

1.从轮询到中断很多同学都不喜欢用中断,而偏爱用轮询的操作方式。这是不是和我们的天性有关呢?每个人都喜欢一切尽在掌握中,肯定都不喜欢被打断。我们常常都有这样的经验:正在跟别人说一件事,然后突然有个电话打进来&a…

Castle

Csocket的作用 利用MFC的Csocket类实现网络通信 https://www.cnblogs.com/sva2005/articles/319796.html _tcstod 字符串转 IEEE 双精度浮点数 http://www.cppfans.com/cbknowledge/reference/cstdlib/strtod.asp strtol, _tcstol, wcstol - 字符串转 32 位长整数 (long), 支…

linux 笔记之一mysql源码包安装

linux的MySQL安装 添加mysql组 1 groupadd mysql 将MySQL用户添加到MySQL组中 2 useradd -g mysql mysql 进入MySQL目录 3 cd src/mysql-4.0.27 在安装过程中缺少文件(Linuxthreads)所以将Linuxthreads从定到/usr/include/pthread.h 4 echo /* Linuxthreads */ >> /u…

C++ —— C++高手之路

推荐一些C经典书籍 c程序设计教程 c编程思想 c大学教程 c程序设计语言 数据结构算法与应用c语言描述 c标准模板库------自修教程与参考手册 泛型编程与STL 深度探索c对象模型 设计模式---可复用面向对象软件的基础 重构---改善既有代码的设计 Essential c Effective…

使用Buildroot为I.MX6制作根文件系统

1.引言接触Freescale/NXP的I.MX6处理器大概有了两年多的时间,对于一个最初玩MCU的我来说,真是面临了很多的挑战。最让我感到郁闷和崩溃的是那个官方的基于Yocto的开发环境,搭建它要求真是太高了,机器得有上百G的空间,U…

SQL查询优化《三》:少做重复的工作

1.控制同一语句的多次执行2.减少多次的数据转换3.杜绝不必要的子查询和连接表,子查询在执行计划一般解释成外连接,多余的连接表带来额外的开销。4.合并对同一表同一条件的多次UPDATE,比如 UPDATE EMPLOYEE SET FNAMEHAIWER WHERE EMP_ID VPA3…

C++ —— 初识C++

初识C 一、C概述 1、C语言诞生 (1)C语言也是诞生于美国贝尔实验室 (2)C语言是1983年由Bjarne Stroustrup推出的 (3)C语言是在C语言的基础上推出的 (4)C语言进一步扩充和完善了C…

扁平的信标灯

▌交流磁场信号会改变地磁计吗?卓大,我想问个问题,智能车比赛的交流信号磁场会对地磁计产生影响吗?▓ 回复: 在今年的智能车竞赛中存在两个交流信号源:(1)第一种是电磁赛道上的电磁导引线&…

如何选择合适的Web安全网关?

日益加剧的网络威胁让Web安全网关(Web Security Gateway,WSG)逐渐成为企业边界网络安全防护的新宠。基于OSI模型第七层(应用层)的Web安全网关具有反恶意软件、上网行为管理以及安全审计等诸多安全检测或管控能力。然而面对铺天盖地的广告和琳…

ADS TC3通信

倍福TC3安装方法 WIN7 32 https://wenku.baidu.com/view/7fb11a200a4e767f5acfa1c7aa00b52acec79c62.html [Visual Studio C] [ 倍福 TwinCAT3 ] ADS通讯工程实现 https://blog.csdn.net/Robot_Starscream/article/details/83869264 倍福TwinCAT3上位机与PLC通信测试(ADS通信)…

js字符串转数字(小数),数字转字符串

将字符串转化为小数并加法计算,然后保留两位小数(parseFloat(that.data.pay_price) parseFloat(that.data.qiandao)).toFixed(2)将数字转为字符串并计算长度yuan_price10yuan_price.toString.length //输出2 转载于:https://www.cnblogs.com/shark1100913/p/8782…

C++ —— C++程序编译的四个过程

C —— C程序编译的四个过程 g是Linux下C的编译器;我为什么会选择Linux下的g编译器,就是因为g可以看到程序从编译到运行的过程做了些什么。而VS等集成开发环境看不到这些,并不是说VS工具不好,(VS还是相当好用的...&…

屏下指纹介绍

一、光学指纹问题现状光学指纹当前随着成本的下降,各大厂商都在低中高端旗舰用上了光学指纹。有别于传统的电容指纹,光学指纹在解锁性能上目前都进行了优化,性能接近电容指纹。二、光学指纹电容指纹原理两者原理都是对指纹的纹路脊谷进行信号…

关于 SAP 访问关键字的说明

SAP 为了保护标准程序和字典对象,对于标准代码的修改都设定了访问关键字控制,用户需要修改时必须输入正确的访问关键字才可以编辑标准程序和字典对象,这个关键字可以到 SAP 网站上申请。 地址为 http://service.sap.com,用你公司的…

ABAP Netweaver和Hybris里获得内存使用统计数据

ABAP Netweaver 事物码ST06 Hybris 每隔5秒钟,Hybris Administration console会发起一个到Java后台的AJAX查询请求: 这个5秒的时间间隔定义在project.properties配置文件里, 然后使用JavaScript的setInterval建立定期轮询: Java后…

Linux中常用C/C++一些头文件的作用

<assert.h>&#xff1a;ANSI C。提供断言&#xff0c;assert(表达式) <glib.h>&#xff1a;GCC。GTK&#xff0c;GNOME的基础库&#xff0c;提供很多有用的函数&#xff0c;如有数据结构操作函数。使用glib只需要包含<glib.h> <dirent.h>&#xff1a;G…