当前位置: 首页 > news >正文

[数据结构] 链表

一.链表

1.链表概念

链表是一种 物理存储结构上非连续 的存储结构 , 数据元素的逻辑顺序是通过 链表中的引用链接次序实现的

注意:

  • 从上图中可以看出 , 链表结构在逻辑上是连续的 , 但是在物理上是不连续的
  • 现实中的结点一般都是从 堆上申请出来的
  • 从堆上申请的空间 , 是按照一定的策略来分配的 , 两次申请的 空间可能连续 , 也可能不连续


2.链表分类(8种)

实际中的链表的结构非常多样 , 以下情况组合起来就有8种

  • 单向或双向
  • 带头结点或者不带头结点
  • 循环或非循环

类型结构特点核心引用域
单向链表每个节点只指向后一个节点,尾节点nextnull,只能从头部遍历next
双向链表每个节点同时指向前后节点,支持双向遍历,尾节点nextnullprev + next
循环链表尾节点的next指向头节点(单向循环)或头节点的prev指向尾节点(双向循环),可循环遍历同单向 / 双向

头结点可以存放数据 , 但是无任何意义


3.链表的实现

  • 无头单项非循环链表的实现
  • 头插法 , 尾插法 , 任意位置插入 , 查找 , 删除 , 长度 , 清空 , 打印等功能 

①接口的实现

public interface IList {//头插法public void addFirst(int data);//尾插法public void addLast(int data);//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data);//查找是否包含关键字key是否在单链表当中public boolean contains(int key);//删除第一次出现关键字为key的节点public void remove(int key);//删除所有值为key的节点public void removeAllKey(int key);//得到单链表的长度public int size();public void clear();public void display();
}

②功能的实现

//无头单项非循环链表的实现
public class MyLinkedList implements IList {static class ListNode {public int val;public ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head;//求链表的长度@Overridepublic int size() {if(head == null) {return 0;}else {int len = 0;ListNode cur = head;while (cur.next != null){cur = cur.next;len++;}return len;}}//头插法@Overridepublic void addFirst(int data) {ListNode node = new ListNode(data);if(head == null){head =  node;}else {node.next = head;head = node;}}//尾插法@Overridepublic void addLast(int data) {ListNode node = new ListNode(data);if(head == null){head =  node;}else{ListNode cur = head;while(cur.next!=null){cur = cur.next;}cur.next = node;}}//在下标 index 位置 , 插入 data@Overridepublic void addIndex(int index, int data) {ListNode node = new ListNode(data);int len = size();if(index<0||index>len){throw new IndexOutOfBoundsException("下标越界");}if(index == 0){addFirst(data);}if(index == len){addLast(data);}ListNode cur = head;for (int i = 0; i < index; i++) {cur = cur.next;}node.next = cur.next;cur.next = node;}//查找是否包含关键字key是否在单链表当中@Overridepublic boolean contains(int key) {int len = size();if(len == 0) {return false;}ListNode cur = head;while (cur.next!=null)if(cur.val == key) {return true;}cur = cur.next;return false;}//删除第一次出现关键字为key的节点@Overridepublic void remove(int key) {// 空链表直接返回if(head == null) {return;}// 处理头节点是目标节点的情况if(head.val == key) {head = head.next;return;}// 查找并删除中间/尾部的目标节点ListNode cur = head;while (cur.next != null) {if (cur.next.val == key) {// 找到目标节点,进行删除cur.next = cur.next.next;return; // 只删除第一个匹配的节点}cur = cur.next;}// 循环结束仍未找到,说明链表中没有该节点,无需操作}//删除所有值为key的节点@Overridepublic void removeAllKey(int key) {if(head == null){return;}ListNode prev = head;ListNode cur = head.next;while (cur != null){if(cur.val == key){prev.next = cur.next;cur = cur.next;}else {prev = cur;cur = cur.next;}}if(head.val == key ){head = head.next;}}//清空链表@Overridepublic void clear() {ListNode cur = head;while (cur!=null){ListNode curN = cur.next;cur = null;cur = curN;}head =null;}//打印链表@Overridepublic void display() {ListNode cur = head;while (cur!=null){System.out.println(cur.val+" ");cur = cur.next;}}
}


4.链表与数组的对比

  • 内存分配:链表动态分配内存,数组需连续内存。
  • 访问效率:数组随机访问O(1),链表需遍历O(n)。
  • 插入/删除:链表在已知位置操作更高效(O(1)或O(n)),数组需移动元素(O(n))。
对比维度链表(LinkedList)数组(ArrayList)
内存存储非连续内存,通过引用连接连续内存,元素按索引存储
增删效率头部 / 尾部增删 O (1),中间增删 O (n)(需遍历)尾部增删 O (1),头部 / 中间增删 O (n)(需移动元素)
查询效率按索引查询 O (n)(需遍历)按索引查询 O (1)(直接通过地址偏移获取)
动态扩容无需扩容(节点可动态创建)需扩容(默认扩容为原容量 1.5 倍,浪费内存)
线程安全非线程安全非线程安全
适用场景频繁增删(尤其是头部 / 尾部)、不确定长度频繁查询、已知大致长度


5.总结

  • Java 中链表分为自定义链表和内置LinkedListLinkedList是双向循环链表,功能强大;
  • 链表的核心是节点和引用,增删灵活但查询效率低,适合频繁增删的场景;
  • 需掌握链表的基本操作(增、删、反转)和经典算法问题,理解指针(引用)的移动逻辑。


例1:

  • 给你单链表的头结点 head ,请你找出并返回链表的中间结点。
  • 如果有两个中间结点,则返回第二个中间结点。
class Solution {public ListNode middleNode(ListNode head) {ListNode cur1 = head;//快指针ListNode cur2 = head;//慢指针while(cur1!=null&&cur1.next!=null){//cur1 = cur1.next.next;cur2 = cur2.next;}return cur2;}
}


例2:

  • 链表的逆置
   //链表的逆置
public ListNode reverseList() {if(head == null||head.next == null) {return head;}ListNode cur = head.next;head.next = null;while(cur != null) {ListNode curN = cur.next;cur.next = head;head = cur;cur = curN;}return head;
}


例3:

  •     获取倒数第 k 个结点的数据
    //获取倒数第 k 个结点的数据public int kthToLast( int k) {if(head == null) return -1;if(k <= 0) {return -1;}ListNode fast = head;ListNode slow = head;int count = 0;while(count != k-1) {fast = fast.next;if(fast == null) {return -1;}count++;}while(fast.next != null) {fast = fast.next;slow = slow.next;}return slow.val;}



文章转载自:

http://DpZQpP8V.rdsst.cn
http://Qc2BjkoP.rdsst.cn
http://nUs0Ve4M.rdsst.cn
http://i1f8gMvd.rdsst.cn
http://mIoIOA9v.rdsst.cn
http://Fy3Cagga.rdsst.cn
http://VPtNZaui.rdsst.cn
http://QT4nnYQF.rdsst.cn
http://4waYkqBp.rdsst.cn
http://ZI5b9Hs7.rdsst.cn
http://ty5QiaGj.rdsst.cn
http://19kB3jnx.rdsst.cn
http://7G7QuFB8.rdsst.cn
http://nrU0LWKJ.rdsst.cn
http://aRUGmtKv.rdsst.cn
http://sATWf7Gl.rdsst.cn
http://zrTQGnw3.rdsst.cn
http://2iW91I5d.rdsst.cn
http://nHssj9hE.rdsst.cn
http://DwtVk8Aq.rdsst.cn
http://q06P4Bs3.rdsst.cn
http://e1v2xgbp.rdsst.cn
http://L0QOk9YC.rdsst.cn
http://cb3mLWLK.rdsst.cn
http://pcQcsJDe.rdsst.cn
http://oIQbQ9Gy.rdsst.cn
http://0dmuS4FS.rdsst.cn
http://ziO5rhkq.rdsst.cn
http://usGsgrQt.rdsst.cn
http://HkeTQCXS.rdsst.cn
http://www.dtcms.com/a/366214.html

相关文章:

  • 大学园区二手书交易平台(代码+数据库+LW)
  • CASToR 软件编译(使用 Makefile )
  • 惊!printf 不往屏幕输?都是 fd 在搞鬼!爆肝拆解 Linux 文件描述符 + 重定向底层,学会直接在终端横着走
  • NIPT 的时点选择与胎儿的异常判定
  • Spring Boot 启动卡死:循环依赖与Bean初始化的深度分析
  • Web与Nginx网站服务
  • 如何导出 手机中的APK并查看清单文件
  • 《R for Data Science (2e)》免费中文翻译 (第7章) --- Data import(1)
  • 2025高教社杯国赛数学建模选题建议+初步分析
  • 企业微信SCRM工具推荐:微盛AI·企微管家为什么是首选?
  • 直接让前端请求代理到自己的本地服务器,告别CV报文到自己的API工具,解放双手
  • 国产化Excel处理组件Spire.XLS教程:Java 向 Excel 写入数据的3种高效方法(含代码示例)
  • 8051单片机-成为点灯大师
  • 单片机实现分页显示环形更新的历史数据
  • 详细讲解pyspark中dsl格式进行大数据开发中的的所有编程情况
  • 大数据毕业设计选题推荐-基于大数据的懂车帝二手车数据分析系统-Spark-Hadoop-Bigdata
  • uni 拍照上传拍视频上传以及相册
  • React 中的 HOC 和 Hooks
  • 大数据毕业设计选题推荐-基于大数据的儿童出生体重和妊娠期数据可视化分析系统-Hadoop-Spark-数据可视化-BigData
  • 【C++练习】06.输出100以内的所有素数
  • 结合prompt源码分析NodeRAG的build过程
  • 【C++闯关笔记】STL:list 的学习和使用
  • 解密大语言模型推理:Prompt Processing 的内存管理与计算优化
  • Redis vs Memcached vs MongoDB:深入对比与选型指南
  • C# 修改基类List中某一元素的子类类型
  • 如何在 iPhone 或 iPad 上删除文件
  • MongoDB 高可用部署:Replica Set 搭建与故障转移测试
  • MacOS微信双开,亲测有效
  • MySQL事务的四大特性(ACID)
  • 数说故事 | 2025年运动相机数据报告,深挖主流品牌运营策略及行业趋势​