数据结构与算法–链表实现以及应用

  • 链表是面试时候使用最频繁的一种数据结构。链表的结构简单,他由指针将若干个节点链接成链状结构。链表的创建,插入,删除,查询操作都只有几行代码可以完成,代码量比较少,可以在较短的时间内完成,这样可以在短时间内考察出人员对数据结构的理解。而且链表数据结构很灵活,可以用来各种灵活的试题。
  • 链表是一种动态数据结构,因为在建立链表的时候,无需知道链表的长度,当插入一个节点时候,只需要为新节点分配内存,然后调整链表中对应节点的指针指向就可以完成节点的插入。内存分配不是在创建链表的时候一次性完成,而是每添加一个节点分配一个节点的内存,由于没有和数组一样的闲置的内存,所以链表比之数组的内存利用率更高。
  • 我们用如下方式定义链表节点:
/*** 链表元素节点** @author liaojiamin* @Date:Created in 12:17 2021/3/5*/
public class ListNode implements Comparable<ListNode> {private String key;private Integer value;private ListNode next;private ListNode before;public ListNode() {}public ListNode(String key, Integer value){this.key = key;this.value = value;this.next = null;this.before = null;}public ListNode(Integer value) {this.value = value;this.next = null;this.before = null;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public ListNode getNext() {return next;}public void setNext(ListNode next) {this.next = next;}public ListNode getBefore() {return before;}public void setBefore(ListNode before) {this.before = before;}@Overridepublic int compareTo(ListNode o) {return this.value - o.value;}
}
  • 话不多说,我们如下实现单向链表的CURD
/*** 单向链表实现** @author liaojiamin* @Date:Created in 12:21 2021/3/5*/
public class MyLinkedList {/*** 链表尾部添加节点*/public static ListNode addToTail(ListNode head, String key, Integer value) {ListNode newNode = new ListNode(key, value);if (head == null) {head = newNode;}else {ListNode pointNode = head;while (pointNode.getNext() != null){pointNode = pointNode.getNext();}pointNode.setNext(newNode);}return head;}/*** 链表尾部添加节点*/public static ListNode addToTail(ListNode head, ListNode newNode) {if (head == null) {head = newNode;}else {ListNode pointNode = head;while (pointNode.getNext() != null){pointNode = pointNode.getNext();}pointNode.setNext(newNode);}return head;}/*** 从头打印链表数据* */public static void print(ListNode head){if(head == null){System.out.println("is empty list");}ListNode pointNode = head;while (pointNode != null){System.out.print(pointNode.getValue());System.out.print(", ");pointNode = pointNode.getNext();}}/*** 查找节点* */public static ListNode search(ListNode head, Integer value){if(head == null || value == null){System.out.println("not in");}ListNode pointNode = head;while (pointNode != null){if(pointNode.getValue() == value){System.out.println("is in");return pointNode;}else {pointNode = pointNode.getNext();}}System.out.println("not in");return null;}/*** 通过key查找节点* */public static ListNode search(ListNode head, String key){if(head == null || key == null){System.out.println("not in");}ListNode pointNode = head;while (pointNode != null){if(pointNode.getKey().equals(key)){System.out.println("is in");return pointNode;}else {pointNode = pointNode.getNext();}}System.out.println("not in");return null;}/*** 删除节点* */public static ListNode delete(ListNode head, Integer value){if(head == null || value == null || head.getNext() == null){return head;}ListNode delNode= null;if(head.getValue() == value){head = head.getNext();delNode = head;}else {ListNode pointNode = head;while (pointNode.getNext() != null && pointNode.getNext().getValue() != value){pointNode = pointNode.getNext();}if(pointNode.getNext() != null && pointNode.getNext().getValue() == value){delNode = pointNode.getNext();pointNode.setNext(pointNode.getNext().getNext());}}if(delNode != null){System.out.println("delete success val="+ delNode.getValue());}return head;}public static void main(String[] args) {Random random = new Random(100);ListNode myHead = new ListNode(random.nextInt(100));for (int i = 0; i < 20; i++) {addToTail(myHead, random.nextInt(100));}print(myHead);if(search(myHead, 74)){delete(myHead, 74);}print(myHead);System.out.println();// printOver(myHead);System.out.println();// printOver_2(myHead);}
}
  • 由于链表内存不是一次性分配,所以内存是不连续的,通过指针来关键每个节点的内存地址,因此我们也不能像数组一样通过下标去获取对应的节点,只能从头开始遍历节点找到第 i 个节点,时间复杂度是O(n)。

变种题型

  • 简单的单向链表实现的基础上,我们看一个特别的:从尾到头打印单向链表中每个节点值
分析
  • 单向链表从尾开始打印,简单的做法是将链表中的指针反转,但是这样会改变元数据的结构,但是打印一般是只读的,这样显然不可行
  • 顺序打印可以直接从头结点开始读取就可以,要从尾到头反转,也就是说有如下特性:第一个先遍历,但是他必须最后输出,此时我们可以借助其他的数据结构,将第一次遍历看出输入,也就是第一个输入的必须最后一个输出,这是典型的先进后出的顺序,栈很显然符合这种标准,我们有如下实现:
 /*** 栈方法,* 从尾到头打印单向链表值* */public static void printOver(ListNode head){MyStack myStack = new MyStack();if(head == null){return;}ListNode pointNode = head;while (pointNode != null){myStack.push(pointNode.getValue().toString());pointNode = pointNode.getNext();}while (!myStack.isEmpty()){System.out.print(myStack.pop());System.out.print(", ");}}
  • 注意:此处用的myStack用的上一节中自己实现的栈,详情点击
  • 以上实现用栈可以实现,那么一定可以用递归来完成,因为递归本质上就是栈的一种结构,那么我们用递归每次打印节点的时候都判断是否有子节点,有则下打印子节点,如下实现。
/*** 递归方式* 从尾到头打印单向链表* */public static void printOver_2(ListNode head){if(head == null){return;}ListNode pointNode = head;if(pointNode.getNext() != null){printOver_2(pointNode.getNext());}System.out.print(pointNode.getValue());System.out.print(", ");}
  • 问题:以上递归方式的代名词看起来更简单一点,但是有一个问题,当链表长度非常长的时候,可能会导致函数栈溢出。而之前用栈的方法虽然需要两次循环但是代码的鲁棒性还是要更好一点,因此我认为最优解是使用栈的方式。

上一篇:数据结构与算法–利用栈实现队列
下一篇:数据结构与算法–查找与排序另类用法

数据结构与算法--链表实现以及应用相关推荐

  1. JavaScript数据结构与算法——链表详解(下)

    在JavaScript数据结构与算法--链表详解(上)中,我们探讨了一下链表的定义.实现原理以及单链表的实现.接下来我们进一步了解一下链表的其他内容. 1.双向链表 双向链表实现原理图: 与单向链表不 ...

  2. JavaScript数据结构与算法——链表详解(上)

    注:与之前JavaScript数据结构与算法系列博客不同的是,从这篇开始,此系列博客采用es6语法编写,这样在学数据结构的同时还能对ECMAScript6有进一步的认识,如需先了解es6语法请浏览ht ...

  3. 数据结构与算法-链表学习笔记

    数据结构与算法-链表学习笔记 链表的概念 链表是有序的列表. 链表是以节点的方式来存储,是链式存储,它在内存中并不是一定是连续的. 每个节点包含 data 域:存储数据, next 域:指向下一个节点 ...

  4. 数据结构与算法 -- 链表

    一.链表介绍 1.链表有地址不连续的结点序列,必须通过指针相互连接. 2.链表的分类: (1)单向线性链表 每个节点中除了存储数据结构内容以外,还需要保存指向下一个节点的指针,叫做后指针.最后一个节点 ...

  5. 数据结构与算法 —— 链表linked list(01)

    链表(维基百科) 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储, ...

  6. 数据结构与算法-链表篇

    链表与数组不同,是在物理空间中非连续的,依靠前一个节点记录下一个节点的地址进行连接的一种数据结构. 链表中每个节点存储的内容为当前节点和下个节点的指针. 链表一般分为三种 1.单向链表 2.双向链表 ...

  7. 数据结构和算法-链表

    链表分类 单向链表 双向链表 优势: 删除某个节点更加高效, 可以快速找到前驱节点 可以方便的在某个节点前插入元素 循环链表 当要处理的数据具有环形结构的时候, 适合循环链表. 如约瑟夫环问题 双向循 ...

  8. 数据结构与算法-链表

    在讲述链表之前让我们对数据结构进行一个简单的回顾:我们知道,数据结构指的是描述实际问题中各个数据项节点之间的前后逻辑结构关系,即要么是线性结构(即某一数据项的前继节点和后继节点有且只有一个)要么是非线 ...

  9. 数据结构与算法 | 链表

    链表是一种物理存储结构上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的. 对于表,图,栈,队列,树等数据结构,我们采用链式和顺序结构都可以实现. 而链表又分为很多种,这一 ...

最新文章

  1. pythonbyte连接_Python3之字节串bytes与字节数组bytearray的使用详解
  2. acm教程 java版_[转]ACM之java速成
  3. Java 内存泄露总结
  4. python 自动输入用户密码_Linux中Python自动输入sudo 密码
  5. [android] 练习使用ListView(二)
  6. 加密保护软件 WinLicense常见问题整理大全(四)
  7. 【图像处理】MATLAB:点、线、边缘检测
  8. 小顶堆时间复杂度_时间轮算法以及时间轮在Netty和Kafka中的应用的
  9. 图像处理 - 滤波器 Filter
  10. shell脚本获取mysql插入数据自增长id的值
  11. systemctl start named失败的解决方法_有关平安银行的提额方法和提额失败的解决方法...
  12. 大疆DJI Thermal SDK Linux编译
  13. svn sync主从同步学习
  14. 转载-【常用RGB颜色查询对照表及感情色】
  15. PostgreSQL12中文手册
  16. Win7 登录WinXP 共享文件夹,总是提示用户名或密码错误 的解决办法
  17. cisco思科交换机的密码恢复
  18. OTL,OCL,BTL电路的性能特点和差别
  19. DP:地头蛇PIPI
  20. 【IOS】IOS工程自动打包并发布脚本实现

热门文章

  1. linux shell之控制台打印各种颜色字体和背景
  2. 用单片机测量流体流速的_流量测量的主要方法
  3. 机器学习与数据挖掘——第二章 数据与数据预处理
  4. 那些奇奇怪怪的男性用品......
  5. 踩自行车来进行人力发电,真的能驱动旋转木马吗?
  6. 85元一个万能工具箱,配齐24种螺丝刀+扳手,媲美德国工艺,家庭必备
  7. 她,既是一个风华绝代的演员,更是WiFi之母...
  8. 他读博期间连发3篇Science,28岁任武大教授后再发Nature!
  9. 你真的不了解这个地球
  10. 一位像素艺术家用39张动图,将大自然的唯美尽收眼底…