• 模拟LinkedList实现的链表(无哨兵)


    1.前言

    我们将LinkdList视作链表, 底层设计了内部类Node类, 我这里依然没有用到泛型, 其实加上泛型依然很简单, 即将Node节点的数据域的类型由Int转换为E(), 我在此不做赘述.同时实现了增删查改, 遍历等操作.

    2.链表(无哨兵)的代码实现

    1. public class LinkListTest implements Iterable{
    2. //头指针
    3. static Node head;
    4. //内部类
    5. private static class Node{
    6. //数据域
    7. int value;
    8. //指针域
    9. Node next;
    10. public Node(int value, Node nest) {
    11. this.value = value;
    12. this.next = nest;
    13. }
    14. }
    15. //头插法
    16. public void addHead(int value) {
    17. Node p = new Node(value, null);
    18. p.next = head;
    19. head = p;
    20. }
    21. //遍历链表 : 方式1
    22. public void Traversal1() {
    23. Node p = head;
    24. while (p != null) {
    25. System.out.println("该节点的值是" + p.value);
    26. p = p.next;
    27. }
    28. }
    29. //获取指定索引位置上的节点的值
    30. public int get(int index) {
    31. Node p = findIndex(index);
    32. return p.value;
    33. }
    34. //返回指定索引的节点
    35. private Node findIndex(int index) {
    36. int count = 0;
    37. Node p = head;
    38. while (count < index) {
    39. if (p == null) {
    40. throw new IllegalArgumentException();
    41. }
    42. p = p.next;
    43. count++;
    44. }
    45. return p;
    46. }
    47. //找到尾节点
    48. private Node findLast() {
    49. //如果是空链表, 压根找不到最后的节点
    50. if (head == null) {
    51. return null;
    52. }
    53. Node p;
    54. //当p.next == null时, 则p指向了尾节点
    55. for (p = head; p.next != null; p = p.next) {
    56. ;
    57. }
    58. return p;
    59. }
    60. //尾插法
    61. public void addLast(int value) {
    62. Node last = findLast();
    63. //如果是一个空链表
    64. if (last == null) {
    65. addHead(value);
    66. return;
    67. }
    68. last.next = new Node(value, null);
    69. }
    70. public void Insert(int index, int value) {
    71. //如果插入的是第一个节点
    72. if (index == 0) {
    73. addHead(value);
    74. return;
    75. }
    76. //先找到index位置处的前一个节点
    77. Node p = findIndex(index - 1);
    78. p.next = new Node(value, p.next);
    79. }
    80. //删除最后一个节点
    81. public void removeFrist() {
    82. //如果是空链表
    83. if (head == null) {
    84. throw new RuntimeException();
    85. }
    86. //找到头节点
    87. Node p = findIndex(0);
    88. head = p.next;
    89. }
    90. public void remove(int index) {
    91. //如果是空链表
    92. if (head == null) {
    93. throw new RuntimeException();
    94. }
    95. //如果要删除的是最后一个节点, 那么调用removeFrist()方法
    96. if (index == 0) {
    97. removeFrist();
    98. return;
    99. }
    100. Node p = findIndex(index - 1);
    101. p.next = p.next.next;
    102. }
    103. //使用迭代器进行遍历
    104. @Override
    105. public Iterator iterator() {
    106. return new Iterator() {
    107. Node q = head;
    108. @Override
    109. public boolean hasNext() {
    110. if (q != null) {
    111. return true;
    112. }
    113. return false;
    114. }
    115. @Override
    116. public Integer next() {
    117. int value = q.value;
    118. q = q.next;
    119. return value;
    120. }
    121. };
    122. }
    123. //使用函数式接口进行链表的遍历
    124. public void Traverse2(Consumer consumer) {
    125. for (Node p = head; p != null; p = p.next) {
    126. consumer.accept(p.value);
    127. }
    128. }
    129. }

    3. 注

    • foreach循环的底层使用了迭代器.所以如果一个类的对象想要使用foreach循环遍历,则其类必须实现Iterable接口,并重写其中的抽象方法(iterable()).在其return语句中实现了匿名内部类,重写了Iterator接口的两个重要的抽象方法,hasNext()和next().不断迭代将next函数返回的值赋值给临时变量element.
    • 在Traverse2方法中,我们使用了函数式接口来进行链表的遍历.
      1. public void Traverse2(Consumer<Integer> consumer) {
      2. for (Node p = head; p != null; p = p.next) {
      3. consumer.accept(p.value);
      4. }
      5. }
      6. @Test
      7. public void test3() {
      8. LinkListTest l = new LinkListTest();
      9. l.addLast(12);
      10. l.addLast(23);
      11. l.addLast(34);
      12. l.addLast(45);
      13. l.addLast(56);
      14. l.addLast(67);
      15. l.Traverse2(value -> {
      16. System.out.println("该节点的值为" + value);
      17. });
      18. l.Traverse2(System.out :: println);
      19. }

      形参是一个消费型的函数式接口,实参我们可以传入接口的实现类的对象(lambda表达式或者方法引用实现).

  • 相关阅读:
    TS查漏补缺【类型守卫】
    Web核心快速学习之Servlet技术(其一)
    上周热点回顾(6.12-6.18)
    部署ZFile在线网盘
    STM32应用开发教程进阶--UART串口重定向(printf)
    JavaWeb 综合案例(包含注册与登录页面,包含对数据库的增删改查页面)新增加session与cookie与验证码
    GO微服务实战第二十二节 案例:如何通过 Service Meh 实现熔断和限流?
    Java真实面试(苏州安硕信息)
    用什么项目管理软件科学统筹“双11”
    MVC netbeans数据库操作注意事项
  • 原文地址:https://blog.csdn.net/2301_80912559/article/details/138168701