本文源码:GitHub·点这里 || GitEE·点这里

一、链表简介

1、链表概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列节点组成,节点可以在运行时动态生成,节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

2、基础特点

内存存储

逻辑结构

特点描述

  • 物理存储上是无序且不连续的;
  • 链表是由多个节点以链式结构组成;
  • 逻辑层面上看形成一个有序的链路结构;

链表结构解决数组存储需要预先知道元素个数的缺陷,可以充分利用内存空间,实现灵活的内存动态管理。

二、单向链表

1、基础描述

单向链表是链表的一种,其特点是链表的链接方向是单向的,链表的遍历要从头部开始顺序读取;结点构成,head指针指向第一个成为表头结点,终止于最后一个指向NULL的指针。

2、基础操作

添加数据

  • 初始化head节点,作为链表的头;
  • 修改当前末尾节点的next指针;
  • 新添加的节点房子在链表末尾;

删除数据

遍历找到要删除的节点,把删除节点前个节点的指针指向该删除节点的下个节点;

三、双向链表

1、概念描述

双向链表也叫双链表,是链表的一种,链表的每个数据结点中都有两个指针,分别指向直接后继和直接前驱,从双向链表中的任意一个结点开始,都可以很快速地访问它的前驱结点和后继结点,链表结构的使用多数都是构造双向循环链表。

2、基础操作

添加数据

  • 遍历找到链表的最后一个节点;
  • 修改当前末尾节点的next指针;
  • 新添加的节点房子在链表末尾;
  • 添加最新尾节点的prev指针;

删除数据

  • 双向链表,基于要删除节点操作即可;
  • 操作上图中要删除的Node2节点;
  • Node2.prev.next = Node2.next;
  • Node2.next.prev = Node2.prev;

通过上述流程的操作,就把链表中一个节点删除,剩下节点再度连接成链式结构。

3、源码分析

在Java的API中,LinkedList是典型的双向链表结构,下面基于LinkedList源码看双向链表的操作。

基础案例

public class M01_Linked {public static void main(String[] args) {List<User> userList = new LinkedList<>() ;User removeUser = new User(200,"Second") ;// 添加元素userList.add(new User(100,"First")) ;userList.add(removeUser) ;userList.add(new User(300,"Third")) ;System.out.println("初始化:"+userList);// 修改元素userList.get(0).setUserName("Zero");System.out.println("修改后:"+userList);// 删除元素userList.remove(removeUser) ;System.out.println("删除后:"+userList);}
}
class User {private Integer userId ;private String userName ;public User(Integer userId, String userName) {this.userId = userId;this.userName = userName;}@Overridepublic String toString() {return "User{" +"userId=" + userId +", userName='" + userName + '\'' +'}';}// 省略Get和Set方法
}

节点描述

节点三个核心描述:数据,next指针,prev指针。

private static class Node<E> {E item;         // 数据Node<E> next;   // 下个指针Node<E> prev;   // 上个指针Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}

首位节点处理

基于LinkedList源码,首尾节点方式,针对上图双链表的首位指针特点,这里源码很好理解。

public class LinkedList {transient Node<E> first;transient Node<E> last;// 处理首节点private void linkFirst(E e) {final Node<E> f = first;final Node<E> newNode = new Node<>(null, e, f);first = newNode;if (f == null)last = newNode;elsef.prev = newNode;}// 处理尾节点void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;}
}

添加节点

添加节点的方法直接调用linkLast方法,把新节点放到链表的尾部即可。

public boolean add(E e) {linkLast(e);return true;
}

删除节点

第一步:遍历对比,找到要删除的节点;

public boolean remove(Object o) {if (o == null) {for (Node<E> x = first; x != null; x = x.next) {if (x.item == null) {unlink(x);return true;}}} else {for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item)) {unlink(x);return true;}}}return false;
}

第二步:移除节点,重新搭建链表结构,并且把当前链表的数据置为null,并返回被移除的节点;

E unlink(Node<E> x) {final E element = x.item;final Node<E> next = x.next;final Node<E> prev = x.prev;if (prev == null) {first = next;} else {prev.next = next;x.prev = null;}if (next == null) {last = prev;} else {next.prev = prev;x.next = null;}x.item = null;return element;
}

如上就是对Java中LinkedList双链表源码的部分结构分析,这种代码看多了,总感觉自己写的代码不是Java。

四、环形链表

在单链表中,将终端结点的指针域NULL改为指向表头结点或开始结点,这样就形成了环形链表:

环形链表链表的一种结构,特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。

五、源代码地址

GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

推荐阅读:算法与数据结构

文章标题
结构与算法:稀疏数组和二维数组转换
结构与算法:队列和栈结构
算法应用:RSA算法,加密解密,签名验签流程详解
算法应用:递归算法,处理树形结构下的业务数据

结构与算法(03):单向链表和双向链表相关推荐

  1. java 快速从树节点找到数据_数据结构与算法:单向链表和双向链表

    一.链表简介 1.链表概念 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列节点组成,节点可以在运行时动态生成,节点包括两个部分:一个 ...

  2. 数据结构与算法之反转单向链表和双向链表

    数据结构与算法之反转单向链表和双向链表 目录 反转单向链表和双向链表 1. 反转单向链表和双向链表 题目描述 代码实现 public class Code_ReverseList {public st ...

  3. 长风破浪会有时:单向链表、双向链表和循环链表图文解析

    链表的种类有很多.我们常常会用到的链表有:单向链表.双向链表和循环链表. 链表不同于数组的地方在于:它的物理存储结构是非连续的,也就是说链表在内存中不是连续的,并且无序.它是通过数据节点的互相指向实现 ...

  4. 已知p是一个指向类a的数据成员m的指针_第三十八章、结构体指针、单向链表简介...

    最近比较忙,一下子有好几天没更新了,今天我们先来了解下结构体指针. 和普通的指针一样,结构体指针就是指向结构体变量的指针. 结构体指针指向的是结构体变量的起始位置. 1. 声明结构体指针 我们用一幅图 ...

  5. 数据结构——数组、单向链表、双向链表

    原文:http://www.cnblogs.com/skywang12345/p/3561803.html 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性 ...

  6. C语言随笔小算法:单向链表

    C语言随笔小算法:单向链表 参考链接: 代码参考:https://blog.csdn.net/go_sann/article/details/80508284 原理参考:https://blog.cs ...

  7. 《恋上数据结构第1季》单向链表、双向链表

    链表(Linked List) 链表的接口设计 单向链表(SingleLinkedList) 获取元素 – get() 清空元素 – clear() 添加元素 – add(int index, E e ...

  8. java基础之面试篇四-单向链表和双向链表区别

    区别主要在头结点,for遍历,有无前驱结点地址. 单向链表的头结点不是哑元(哑元的意思是能不能从头节点遍历,能则不是哑元),遍历的时候要第二次才能进入for循环,第一次需要去找表头,无前驱结点地址,只 ...

  9. python单向链表和双向链表的图示代码说明

    图示说明: 单向链表: insert. remove. update.pop方法 class Node:def __init__(self, data):self.data = dataself.ne ...

最新文章

  1. 多目标检测跟踪文献代码汇总
  2. 使用sed和awk取除最后两个字段之外的字段
  3. lolfps高但画面不流畅_全面解析:高刷新率真能提高FPS游戏技术?
  4. Qt文档阅读笔记-QTcpServer官方解析与实例(使用QSocket创建简单的HTTP服务器)
  5. 判定重大风险有哪几种_安全风险识别和评估的方法有哪些?
  6. 基于注意力机制的seq2seq网络
  7. 5招详解linux之openEuler /centos7防火墙基本使用指南
  8. 性能测试之JMeter接口关联【JSON提取器】详解
  9. 趣味俄罗斯方块——C语言
  10. videojs暂停时显示大按钮_服务失败时进行故障恢复,Windows 7系统如何打开服务管理程序...
  11. Active Directory Get User's groups using LDAP
  12. 实现WP7下ListBox分页加载接口
  13. 爬虫:爬取微软必应翻译做成API
  14. linux 原型软件,10个在线原型设计软件推荐
  15. Python将Word转换为Pdf格式文件(包含批量转换)
  16. 《正见——佛陀的证悟》读后感
  17. Ubuntu18.04安装搜狗输入以及五笔输入法
  18. ChatGPT聊天机器人如何发图片????
  19. vivo Y79的Usb调试模式在哪里,打开vivo Y79Usb调试模式的方法
  20. gpu服务器压力测试方法,如何用Furmark对GPU进行压力测试?

热门文章

  1. 计算机网络之数据链路层:12、CSMA/CA协议-随机访问介质访问控制
  2. 4-4:TCP协议之TCP头部格式详解
  3. 8-3:C++继承之继承中的作用域,隐藏,重定义和静态成员
  4. poj 2262 Goldbach's Conjecture(筛素数)
  5. Python subprocess命令行中文乱码
  6. Java 反射调用方法实例,动态动用方法实例
  7. 13. OD-内嵌补丁,过期的软件DVD Menu Studio破解,switch函数,break等于KillTimer
  8. C语言:16进制字符串转int
  9. 洛谷P2312解方程题解
  10. 个人博客 V0.0.3 版本 ...