文章目录

  • 一、链表
    • 概念
    • 结构
  • 二、无头单链表
    • 图解
    • 代码实现
    • 特点
  • 三、带头单链表
    • 为何引入带头单链表
    • 代码实现
    • 注意

提示:以下是本篇文章正文内容,Java系列学习将会持续更新

一、链表

概念

链表:逻辑上连续,多个节点采用挂载式进行连接。但是物理上非连续存储结构。(火车)

结构:从头开始遍历,一直到达尾部。
火车:当数据空间不够时,就新增一节车厢挂载到火车尾。

结构

链表的结构十分多样,以下条件组合起来会有8种链表结构
  ①单向、双向
  ②带头、不带头
  ③循环、非循环
重点掌握其中两种:
  ①无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
  ②无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。

回到目录…

二、无头单链表

图解

单向遍历,默认从前向后遍历。只能从头部车厢开始遍历,依次走到尾部。

代码实现

/*火车车厢类,一个车厢只能存放一个元素*/
public class Node {//存放具体数据int value;//保存下一个车厢的地址Node next;public Node(int value){ this.value = value;}
}
/*** 火车类,是由多个车厢连接起来的*/
public class SingleLinkedList {//当前火车中车厢节点的个数(实际就是元素的个数)private int size;//当前火车的头车厢地址private Node head;/****  添加  *********************///头插法public void addFirst(int value){//新建一个车厢节点Node node = new Node(value);//先判断当前火车是否为空if(head == null){head = node;}else{//火车头有节点,要把当前新车厢挂载到火车头部//先把原本的头部车厢指向新车厢的下一节node.next = head;//再将这个新增的车厢node指向头部headhead = node;}size++;}//索引插入public void addIndex(int index,int value){//先判断是否索引越界if(index<0||index>size){System.err.println("add index illegal!");return;}//index==0,说明是头插if(index == 0){addFirst(value);return;}//创建一个新的车厢Node node = new Node(value);//建一个prev,寻找插入位置的前驱,从头节点开始向后走index-1步Node prev = head;for(int i=0;i<index-1;i++){prev = prev.next;}//node的下一节指向前驱temp的下一节node.next = prev.next;//前驱的下一节指向nodeprev.next = node;size++;}//尾插public void addLast(int value){addIndex(size,value);}/****  查找  *********************///返回索引处value的值public int get(int index){if(rangeCheck(index)){//从头节点开始,走到index的位置Node node = head;for(int i=0;i<index;i++){node = node.next;}return node.value;}else{System.err.println("get index illegal!");return -1;}}//判断链表中是否有value这个数据、public boolean contains(int value){for(Node temp=head;temp!=null;temp=temp.next){if(temp.value == value)return true;}return false;}/****  修改  *********************///将单链表中索引为index的元素修改,并返回修改前的值public int set(int index,int value){if(rangeCheck(index)){Node node = head;for(int i=0;i<index;i++){node = node.next;}int old = node.value;node.value = value;return old;}else{System.err.println("set index illegal!");return -1;}}/****  删除  *********************///删除索引处的数据public void removeIndex(int index){if(rangeCheck(index)){if(index == 0){Node temp = head;head = head.next;temp.next = null;size--;}else{//找到待删除节点的前驱Node prev = head;for(int i=0;i<index-1;i++){prev = prev.next;}//cur表示待删除节点Node cur = prev.next;prev.next = cur.next;cur.next = null;size--;}}else{System.err.println("remove index illegal!");}}//删除单链表中的第一个value值public void removeOnceValue(int value){//遍历链表,找到value的节点的前驱//头节点没有前驱,要特殊处理if(head!=null && head.value == value){removeIndex(0);return;}//找待删节点的前驱,该前驱的下一节点就是valueNode prev = head;while(prev.next != null){if(prev.next.value == value){//cur就是待删节点Node cur = prev.next;prev.next = cur.next;cur.next = null;size--;return;}//prev不是待删节点的前驱,让prev继续向后走prev = prev.next;}}//删除单链表中的全部value值public void removeAllValue(int value){//判断头节点是否为待删除节点while(head!=null && head.value==value){head = head.next;size--;}if(head == null){//说明链表中全是待删节点,此时链表被删空return;}else{//此时head一定不是待删节点,再看链表中的其它节点Node prev = head;while(prev.next != null){if(prev.next.value == value){//cur就是待删节点Node cur = prev.next;prev.next = cur.next;cur.next = null;size--;}else{//只有确保prev的下一个不是待删节点,才让prev继续向后走一步prev = prev.next;}}}}//打印public String toString(){String str = "";//遍历这个火车类,从头部(head)走到尾部//暂时存储头节点地址,避免遍历结束影响head的值Node node = head;while(node != null){str += node.value;str += " -> ";//当前地址指向下一节车厢的地址node = node.next;}str += "NULL";return str;}//判断 查、改、删操作时,索引是否越界private boolean rangeCheck(int index){if(index<0||index>=size)return false;elsereturn true;}
}

特点

1.每次增、删操作时,都要改动size的值
2.每当对head进行操作时,必须先考虑head是否为空. (防止空指针异常)
3.进行查、改、删操作时,需要判断用户输入的索引是否越界[0,size)
4.在进行索引插入和删除操作时,都需要找前驱节点。(但是头节点没有前驱,所以要特殊处理)

回到目录…

三、带头单链表

为何引入带头单链表

 因为初学的单链表每次插入删除元素时,都需要找前驱;此时需要特殊处理头节点。(因为头节点没有前驱)
 为了避免这一步繁琐的操作,将所有节点都一视同仁 ——> 不用处理头节点 ——> 虚拟头节点(这个节点仅仅作为链表的头部,不储存具体元素) ——> 火车头不坐乘客

代码实现

/*** 带头单链表*/
public class SingleLinkedListWithHead {//表示当前链表中元素的个数private int size;//创建虚拟头节点private Node dummyHead = new Node(-1);/****  添加  *********************/public void addIndex(int index,int value){//判断index合法性if(index<0 || index>size){System.err.println("add index illegal!");return;}//此时的插入就不可能是头插Node node = new Node(value);//找到插入位置的前驱Node prev = dummyHead;for(int i=0;i<index;i++){//因为链表的头部有个虚拟节点,所以要走index步才行prev = prev.next;}//此时prev指向待插位置的前驱node.next = prev.next;prev.next = node;size++;}public void addFirst(int value){addIndex(0,value);}public void addLast(int value){addIndex(size,value);}/****  查找  *********************///返回索引处value的值public int get(int index){if(rangeCheck(index)){Node node = dummyHead.next;for(int i=0;i<index;i++){node = node.next;}return node.value;}else{System.err.println("get index illegal!");return -1;}}//判断链表中是否有value这个数据public boolean contains(int value){for(Node temp=dummyHead.next;temp!=null;temp=temp.next){if(temp.value == value)return true;}return false;}/****  修改  *********************///将单链表中索引为index的元素修改,并返回修改前的值public int set(int index,int value){if(rangeCheck(index)){Node node = dummyHead.next;for(int i=0;i<index;i++){node = node.next;}int old = node.value;node.value = value;return old;}else{System.err.println("set index illegal!");return -1;}}/****  删除  *********************/public void removeIndex(int index){if(rangeCheck(index)){Node prev = dummyHead;for(int i=0;i<index;i++){prev = prev.next;}Node cur = prev.next;prev.next = cur.next;cur.next = null;size--;}else{System.err.println("remove index illegal!");}}public void removeOnceValue(int value){Node prev = dummyHead;while(prev.next!=null){if(prev.next.value == value){Node cur = prev.next;prev.next = cur.next;cur.next = null;size--;return;}prev = prev.next;}}public void removeAllValue(int value){Node prev = dummyHead;while(prev.next!=null){if(prev.next.value == value){Node cur = prev.next;prev.next = cur.next;cur.next = null;size--;}else{prev = prev.next;}}}public String toString(){String str = "";Node temp = dummyHead.next;while(temp!=null){str += temp.value;str += " -> ";temp = temp.next;}str += "NULL";return str;}private boolean rangeCheck(int index){if(index<0 || index>=size)return false;elsereturn true;}public int size(){return this.size;}
}

注意

1.虚拟头节点的值最好取value范围之外的值。Node dummyHead = new Node(value:-1);
2.dummyHead只是虚假的节点,进行查、改操作时,要避开它,从它的下一个节点开始遍历。

回到目录…


总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是Java数据结构的链表部分,介绍了链表的实现原理,以及带头单链表的引入。之后的学习内容将持续更新!!!

Java数据结构之链表(单链表)相关推荐

  1. Java数据结构与算法 day02 链表

    文章目录 第三章 链表 单链表介绍和内存布局 单链表创建和遍历的分析实现 添加(创建)过程 遍历过程 代码实现 单链表按顺序插入节点 单链表节点的修改 单链表节点的删除和小结 单链表面试题 新浪面试题 ...

  2. java数据结构 第4章-链表(双向链表)

    文章目录 4.4 双向链表应用实例 4.4.1双向链表的操作分析和实现 1.管理单向链表的缺点分析: 2.分析 双向链表的遍历,添加,修改,删除的操作思路 3.双向链表的代码实现 4.代码运行结果 4 ...

  3. 数据结构与算法--单链表相关面试题

    此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢! 一.概述 获取单链表的有效元素个数[新浪面试题1] 获取单链表倒数第k个结 ...

  4. python数据结构基础(单链表,多链表,二叉树)

    python数据结构基础(单链表,多链表,二叉树) 数据结构指数据对象中数据元素之间的关系 Python 给我们提供了很多现成的数据结构类型,这些系统自己定义好的,不需要我们自己去定义的数据结构叫做 ...

  5. java带头结点空单链表_Java版带头结点单链表的实现

    Java版带头结点单链表的实现 Java版带头结点单链表的实现 package dsr; public interface IList { public void clear();//8 public ...

  6. 数据结构之——《单链表》

    数据结构之--<单链表> 1.链表概念 2.链表分类 3.接口函数实现 1.链表概念 链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现. ...

  7. 数据结构上机-尾、头插法建立单链表-单链表遍历C语言完整代码实现

    点击此处跳转视频链接:数据结构上机-尾.头插法建立单链表-单链表遍历C语言完整代码实现

  8. 数据结构精讲——单链表

    新手必会数据结构精讲--单链表 链表的介绍 概念:链表是一种物理存储结构上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 . 实际中链表的结构非常多样,以下情况组合起来就 ...

  9. 数据结构基础(8) --单链表的设计与实现(1)之基本操作

    链表简介 数组的缺点: 1.元素插入:除了在数组的末尾插入元素之外,在数组的其他任何位置插入元素都需要进行数组元素的频繁移动(插入位置之后的元素都需往后移动), 时间复杂度约为O(N); 2.数组的删 ...

  10. 建立单链表 单链表的插入_单链列表插入

    建立单链表 单链表的插入 All possible cases: 所有可能的情况: Inserting at beginning 开始插入 Inserting at the ending 在末尾插入 ...

最新文章

  1. java实现线程同步的方法_Java实现线程同步方法及原理详解
  2. 如何编辑Subversion中已提交的日志消息?
  3. matlab patch函数_MATLAB实现紧束缚近似能带结构画图
  4. TabLayout让Fragment在ViewPager中的滑动切换更优雅
  5. python多个装饰器执行顺序_Python面试题之多个装饰器执行顺序
  6. Magicodes.IE已支持导出Word、Pdf和Html
  7. XidianOJ 1099 A simple problem
  8. 面向业务的立体化高可用架构设计
  9. 计算机应用技术专业标志,计算机应用技术论文
  10. 技术人的折腾(二)-缺少的东西,你迟早要补起来
  11. java.io.FileNotFoundException: ...\ibs\library-1.0.17.jar (系统找不到指定的文件。)
  12. Java新职篇:使用程序块
  13. c md5加密 和java不一样_C#的MD5加密为什么和JAVA的加密出来的结果不一样?
  14. SyncBird Pro的PhoneCare功能如何使用
  15. H - 命运(动态规划) 数塔问题
  16. 软件项目需求分析报告模板
  17. aotorun专杀工具(U盘病毒专杀)
  18. 音乐学院计算机音乐实验中心,中央音乐学院鼎石实验学校
  19. 【java学习】集合框架
  20. unity 鼠标按键点击判断函数

热门文章

  1. purnhurb网页版怎么进_怎么把微信里的gif动图表情保存到电脑使用?
  2. Java写内容到本地文件
  3. 树莓派安装python3替换python2_在树莓派上安装基于python3的OpenCV
  4. idea 新建/导入的xml 报文头报错 URI is not registered (Settings | Languages Frameworks | Schemas and DTDs)...
  5. 【日常】无字幕教学视频中的音频转换成文字
  6. 如何给微信头像加个圣诞帽
  7. win10搜索功能失效用不了如何解决|
  8. 算丰边缘计算开发板人脸检测识别-实现原理与代码介绍
  9. 计算机网络各种协议(会持续更新)
  10. 艺术摄影--摄影构图(2学时)--SDUST