当前位置:   article > 正文

Java实现单链表_java 写单链表

java 写单链表

目录

一.单链表

二.单链表基本操作的实现

1.单链表类、属性的定义

2.求链表长度

3.链表是否包含值为key的节点

4.添加元素

5.删除节点

6.清空链表

三、完整代码


一.单链表

链表是一种在物理存储结构非连续存储结构,数据元素的逻辑顺序通过链表中的引用链接次序实现。链表的结构多样,我们通过实现无头单向非循环链表,来进一步理解链表。

从图中可以看出,链表在逻辑上连续的,但在物理存储结构上不一定是连续的

由于链表是单向的,可以通过前一个节点访问后一个节点,不能通过后一个节点访问前一个结点

二.单链表基本操作的实现

1.单链表类、属性的定义

要创建链表首先要有节点,我们可以将节点定义为内部类

  1. public class MySingleList{
  2. static class ListNode{
  3. //存放当前结点的值
  4. private int val;
  5. //存放下一节点的地址
  6. private ListNode next;
  7. public ListNode(){}
  8. public ListNode(int val){
  9. this.val = val;
  10. }
  11. }
  12. }

由于链表是通过前一个节点访问下一个节点的,因此我们需要知道链表的第一个节点,因此我们需要定义一个头节点

private ListNode head;//第一个节点

2.求链表长度

 定义变量count用以计算,遍历链表,统计链表节点个数

  1. //求链表长度
  2. public int size() {
  3. int count = 0;
  4. //定义节点cur,用于遍历链表
  5. ListNode cur = head;
  6. while(cur != null){
  7. count++;
  8. //指向下一节点
  9. cur = cur.next;
  10. }
  11. return count;
  12. }

3.链表是否包含值为key的节点

遍历链表,判断节点的值是否等于key

  1. public boolean contains(int key) {
  2. ListNode cur = head;
  3. while(cur != null){
  4. if(cur.val == key){
  5. return true;
  6. }
  7. cur = cur.next;
  8. }
  9. return false;
  10. }

4.添加元素

链表添加元素的方式通常有三种,头插、尾插和在指定位置添加元素。

头插:在链表的第一个节点前插入元素

 实现头插,就是让要插入的节点node指向原本链表的头节点head,再更新链表的第一个节点,让head指向新插入的节点

  1. //头插
  2. public void addFirst(int data) {
  3. //创建新节点
  4. ListNode listNode = new ListNode(data);
  5. listNode.next = head;
  6. head = listNode;
  7. }

尾插:在链表的最后插入元素

实现尾插,首先要找到链表的最后一个节点,再将最后一个节点的next更新为新节点即可

  1. //尾插
  2. public void addLast(int data) {
  3. ListNode newNode = new ListNode(data);
  4. //若链表为空,直接将head更新为插入节点
  5. if(head == null){
  6. head = newNode;
  7. }else{
  8. //通过遍历找到最后一个节点
  9. ListNode cur = head;
  10. while(cur.next != null){
  11. cur = cur.next;
  12. }
  13. cur.next = newNode;
  14. }
  15. }

在指定位置添加元素

 在指定位置添加元素,首先要判断指定位置index是否合法,若index < 0 或 index > size,则不能添加元素,然后通过遍历找到节点插入的位置,由于链表为单链表,不能通过后一节点找到前一节点,因此,我们需要找到插入位置的前驱节点,然后通过前驱节点实现链表在index位置的插入

  1. //在任意位置添加元素
  2. public void addIndex(int index, int data) {
  3. //index不正确,无法添加元素
  4. if(index < 0 || index > size()){
  5. throw new RuntimeException("输入位置不正确,无法添加元素!");
  6. }else if(index == 0){//在0位置插入,即为头插
  7. addFirst(data);
  8. }else{
  9. ListNode cur = head;//用cur遍历链表,找到前驱节点
  10. ListNode listNode = new ListNode(data);
  11. int count = 0;
  12. while(count != index-1){
  13. count++;
  14. cur = cur.next;
  15. }
  16. //添加元素
  17. listNode.next = cur.next;
  18. cur.next = listNode;
  19. }
  20. }

5.删除节点

删除第一个值为key的节点:与在指定位置添加元素相同,我们需要找到第一个值为key的节点node的前驱节点,然后才能删除值为key的节点。由于JVM会将未被任何引用指向的对象回收掉,我们只需让node的前驱节点指向node的下一节点,即可实现删除

  1. //删除第一个值为key的节点
  2. public boolean remove(int key) {
  3. ListNode cur = head;
  4. //链表第一个节点的值即为key,头删
  5. if(head.val == key){
  6. head = head.next;
  7. return true;
  8. }//通过遍历找到第一个值为key的节点的前驱节点
  9. while(cur.next != null){
  10. if(cur.next.val == key){//找到了,删除节点
  11. cur.next = cur.next.next;
  12. return true;
  13. }
  14. cur = cur.next;
  15. }
  16. return false;//未找到值未key的节点,返回false
  17. }

删除所有值为key的节点:首先要找到值为key的节点node,将node的上一节点指向node的下一节点,即可删除值为key的节点,注意考虑头节点值为key的情况,要删除链表中所有值为key的节点,利用while循环即可实现。

  1. //删除所有值为key的节点
  2. public void removeAllKey(int key) {
  3. //若链表为空,则直接返回null
  4. if(head == null){
  5. return;
  6. }
  7. ListNode cur = head;
  8. while(cur.next != null){
  9. if(cur.next.val == key){
  10. cur.next = cur.next.next;
  11. }else{
  12. cur = cur.next;
  13. }
  14. }
  15. //单独考虑头节点的值是否等于val
  16. if(head.val == key){
  17. head = head.next;
  18. }
  19. }

6.清空链表

由于JVM会将未被任何引用指向的对象回收掉,清空链表可以将每个节点的指向都置为null,即切断节点之间的链接,也可以直接将head置为null

将每个节点的指向都置为null

  1. //清空链表
  2. public void clear() {
  3. if(head == null){//链表本身为空
  4. return;
  5. }
  6. ListNode cur = head;
  7. while(cur != null){
  8. ListNode next = cur.next;//记录下一节点
  9. cur.next = null;
  10. cur = next;
  11. }
  12. }

直接将head置为null

  1. //清空链表
  2. public void clear() {
  3. head = null;
  4. }

三、完整代码

  1. public class MySingleList {
  2. static class ListNode{
  3. //存放当前结点的值
  4. private int val;
  5. //存放下一节点的地址
  6. private ListNode next;
  7. public ListNode(){}
  8. public ListNode(int val){
  9. this.val = val;
  10. }
  11. }
  12. private ListNode head;//第一个节点
  13. //求链表长度
  14. public int size() {
  15. int count = 0;
  16. //定义节点cur,用于遍历链表
  17. ListNode cur = head;
  18. while(cur != null){
  19. count++;
  20. //指向下一节点
  21. cur = cur.next;
  22. }
  23. return count;
  24. }
  25. //链表是否包含值为key的节点
  26. public boolean contains(int key) {
  27. ListNode cur = head;
  28. while(cur != null){
  29. if(cur.val == key){
  30. return true;
  31. }
  32. cur = cur.next;
  33. }
  34. return false;
  35. }
  36. //头插
  37. public void addFirst(int data) {
  38. //创建新节点
  39. ListNode listNode = new ListNode(data);
  40. listNode.next = head;
  41. head = listNode;
  42. }
  43. //尾插
  44. public void addLast(int data) {
  45. ListNode newNode = new ListNode(data);
  46. //若链表为空,直接将head更新为插入节点
  47. if(head == null){
  48. head = newNode;
  49. }else{
  50. //通过遍历找到最后一个节点
  51. ListNode cur = head;
  52. while(cur.next != null){
  53. cur = cur.next;
  54. }
  55. cur.next = newNode;
  56. }
  57. }
  58. //在任意位置添加元素
  59. public void addIndex(int index, int data) {
  60. //index不正确,无法添加元素
  61. if(index < 0 || index > size()){
  62. throw new RuntimeException("输入位置不正确,无法添加元素!");
  63. }else if(index == 0){//在0位置插入,即为头插
  64. addFirst(data);
  65. }else{
  66. ListNode cur = head;//用cur遍历链表,找到前驱节点
  67. ListNode listNode = new ListNode(data);
  68. int count = 0;
  69. while(count != index-1){
  70. count++;
  71. cur = cur.next;
  72. }
  73. //添加元素
  74. listNode.next = cur.next;
  75. cur.next = listNode;
  76. }
  77. }
  78. //删除第一个值为key的节点
  79. public boolean remove(int key) {
  80. ListNode cur = head;
  81. //链表第一个节点的值即为key,头删
  82. if(head.val == key){
  83. head = head.next;
  84. return true;
  85. }//通过遍历找到第一个值为key的节点的前驱节点
  86. while(cur.next != null){
  87. if(cur.next.val == key){//找到了,删除节点
  88. cur.next = cur.next.next;
  89. return true;
  90. }
  91. cur = cur.next;
  92. }
  93. return false;//未找到值未key的节点,返回false
  94. }
  95. //删除所有值为key的节点
  96. public void removeAllKey(int key) {
  97. //若链表为空,则直接返回null
  98. if(head == null){
  99. return;
  100. }
  101. ListNode cur = head;
  102. while(cur.next != null){
  103. if(cur.next.val == key){
  104. cur.next = cur.next.next;
  105. }else{
  106. cur = cur.next;
  107. }
  108. }
  109. //单独考虑头节点的值是否等于val
  110. if(head.val == key){
  111. head = head.next;
  112. }
  113. }
  114. //清空链表
  115. public void clear() {
  116. if(head == null){//链表本身为空
  117. return;
  118. }
  119. ListNode cur = head;
  120. while(cur != null){
  121. ListNode next = cur.next;//记录下一节点
  122. cur.next = null;
  123. cur = next;
  124. }
  125. //或直接将head置为null
  126. //head = null;
  127. }
  128. }
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/777332
推荐阅读
相关标签
  

闽ICP备14008679号