双向链表的模仿实现 —— LinkedList

[复制链接]
发表于 2025-12-13 07:48:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
MyLinkedList类
  1. public class MyLinkedList {
  2.     // 定义节点类
  3.     static class Node {
  4.         int val;
  5.         Node prev;
  6.         Node next;
  7.         public Node() {
  8.         }
  9.         public Node(int val) {
  10.             this.val = val;
  11.         }
  12.     }
  13.     // 定义头节点
  14.     private Node head;
  15.     // 定义尾结点
  16.     private Node tail;
  17.     // 头插
  18.     public void headInsert(int val) {
  19.         // 申请节点
  20.         Node node = new Node(val);
  21.         // 判空
  22.         if (head == null) {
  23.             // head 和 tail 都指向 node
  24.             head = node;
  25.             tail = node;
  26.             return;
  27.         }
  28.         // head 不为空,则进行头插
  29.         node.next = head;
  30.         head.prev = node;
  31.         // 重置头节点
  32.         head = node;
  33.     }
  34.     // 尾插
  35.     public void tailInsert(int val) {
  36.         // 申请节点
  37.         Node node = new Node(val);
  38.         // 判空
  39.         if (head == null) {
  40.             head = node;
  41.             tail = node;
  42.             return;
  43.         }
  44.         // 非空情况下进行尾插
  45.         tail.next = node;
  46.         node.prev = tail;
  47.         // 重置尾结点
  48.         tail = node;
  49.     }
  50.     // 在 index 处插入元素
  51.     public void randomInsert(int index, int val) {
  52.         // 判空
  53.         if (head == null) return;
  54.         // 下标判断
  55.         if (index < 0 || index > size()) {
  56.             throw new IndexOfLinkedListException("下标 index :" + index + " 出现异常!");
  57.         }
  58.         // 头插
  59.         if (index == 1) {
  60.             headInsert(val);
  61.             return;
  62.         }
  63.         // 尾插
  64.         if (index == size()) {
  65.             tailInsert(val);
  66.             return;
  67.         }
  68.         // 找到要插入的位置
  69.         Node cur = head;
  70.         Node node = new Node(val);
  71.         for (int i = 0; i < index; i++) {
  72.             cur = cur.next;
  73.         }
  74.         // 进行插入
  75.         cur.prev.next = node;
  76.         node.next = cur;
  77.         node.prev = cur.prev;
  78.         cur.prev = node;
  79.     }
  80.     // 删除与 val 相等的元素节点
  81.     public void remove(int val) {
  82.         // 判空
  83.         if (head == null) return;
  84.         Node cur = head;
  85.         while (cur != null) {
  86.             // 值相等,进行删除
  87.             if (cur.val == val) {
  88.                 // 头节点的情况
  89.                 if (cur == head) {
  90.                     head = head.next;
  91.                     head.prev = null;
  92.                     break;
  93.                 }
  94.                 // 尾结点的情况
  95.                 if (cur == tail) {
  96.                     tail = tail.prev;
  97.                     tail.next = null;
  98.                     break;
  99.                 }
  100.                 // 中间节点删除
  101.                 cur.prev.next = cur.next;
  102.                 cur.next.prev = cur.prev;
  103.             }
  104.             cur = cur.next;
  105.         }
  106.     }
  107.     // 删除 index 处的元素
  108.     public void removeOfIndex(int index) {
  109.         // 判空
  110.         if (head == null) return;
  111.         // 下标判断
  112.         if (index < 0 || index > size()) {
  113.             throw new IndexOfLinkedListException("下标 index :" + index + " 出现异常!");
  114.         }
  115.         // 头删
  116.         if (index == 1) {
  117.             head = head.next;
  118.             head.prev = null;
  119.             return;
  120.         }
  121.         // 尾删
  122.         if (index == size()) {
  123.             tail = tail.prev;
  124.             tail.next = null;
  125.             return;
  126.         }
  127.         // 找到要删除的位置
  128.         Node cur = head;
  129.         for (int i = 1; i < index; i++) {
  130.             cur = cur.next;
  131.         }
  132.         // 进行删除操作
  133.         cur.prev.next = cur.next;
  134.         cur.next.prev = cur.prev;
  135.     }
  136.     // 删除所有与 val 相等的节点
  137.     public void removeAllVal(int val) {
  138.         // 判空
  139.         if (head == null) return;
  140.         // 判断 val 值是否在链表中出现
  141.         if (!contains(val)) return;
  142.         // 从头节点开发判断
  143.         Node cur = head;
  144.         while (cur != null) {
  145.             // 相等则进行删除
  146.             if (cur.val == val) {
  147.                 // 是头节点的情况
  148.                 if (head == cur) {
  149.                     // head 走到下一个节点处
  150.                     head = head.next;
  151.                     head.prev = null;
  152.                 } else if (tail == cur) {
  153.                     // tail 走到上一个节点处
  154.                     tail = tail.prev;
  155.                     tail.next = null;
  156.                 } else {
  157.                     // 中间节点,让删除节点的前一个节点和后一个节点进行连接
  158.                     cur.next.prev = cur.prev;
  159.                     cur.prev.next = cur.next;
  160.                 }
  161.             }
  162.             // 注意,cur 无论是否删除了当前节点,都应该要走到下一步
  163.             cur = cur.next;
  164.         }
  165.     }
  166.     // 查找 val 第一次出现的下标
  167.     public int indexOf(int val) {
  168.         // 判空
  169.         if (head == null) return -1;
  170.         Node cur = head;
  171.         for (int i = 1; i < size() + 1; i++) {
  172.             // 找到了
  173.             if (cur.val == val) {
  174.                 return i;
  175.             }
  176.             cur = cur.next;
  177.         }
  178.         // 没找到
  179.         return -1;
  180.     }
  181.     // 查找 val 最后一次出现的下标
  182.     public int lastOfIndex(int val) {
  183.         // 判空
  184.         if (head == null) return -1;
  185.         int index = -1;
  186.         Node cur = tail;
  187.         for (int i = size(); i > 0; i--) {
  188.             // 找到了
  189.             if (cur.val == val) {
  190.                 index = i;
  191.             }
  192.             cur = cur.prev;
  193.         }
  194.         // 没找到
  195.         return index;
  196.     }
  197.     // 判断 val 是否在链表中
  198.     public boolean contains(int val) {
  199.         // 判空
  200.         if (head == null) return false;
  201.         Node cur = head;
  202.         while (cur != null) {
  203.             // 找到了
  204.             if (cur.val == val) {
  205.                 return true;
  206.             }
  207.             cur = cur.next;
  208.         }
  209.         // 没找到
  210.         return false;
  211.     }
  212.     // 获取元素个数
  213.     public int size() {
  214.         Node cur = head;
  215.         // 获取链表中的元素个数
  216.         int count = 0;
  217.         while (cur != null) {
  218.             count++;
  219.             cur = cur.next;
  220.         }
  221.         return count;
  222.     }
  223.     // 打印链表
  224.     public void display() {
  225.         Node cur = head;
  226.         // 进行打印操作
  227.         while (cur != null) {
  228.             System.out.print(cur.val + " ");
  229.             cur = cur.next;
  230.         }
  231.         // 换行
  232.         System.out.println();
  233.     }
  234.     // 清空链表
  235.     public void clear() {
  236.         Node cur = head;
  237.         // 把每个节点都置为 null
  238.         while (cur != null) {
  239.             Node tmp = cur.next;
  240.             cur.next = null;
  241.             cur.prev = null;
  242.             cur = tmp;
  243.         }
  244.         // 头节点和尾结点置空
  245.         head = null;
  246.         tail = null;
  247.     }
  248. }
复制代码
 
IndexOfLinkedListException类
  1. public class IndexOfLinkedListException extends RuntimeException {
  2.     public IndexOfLinkedListException() {
  3.     }
  4.     public IndexOfLinkedListException(String message) {
  5.         super(message);
  6.     }
  7. }
复制代码
 
 Test类
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         MyLinkedList linkedList = new MyLinkedList();
  4.         // 头插
  5.         linkedList.headInsert(1);
  6.         linkedList.headInsert(2);
  7.         linkedList.headInsert(3);
  8.         // 打印链表
  9.         linkedList.display();
  10.         // 获取长度
  11.         System.out.println(linkedList.size());
  12.         // 尾插
  13.         linkedList.tailInsert(4);
  14.         linkedList.tailInsert(5);
  15.         linkedList.tailInsert(6);
  16.         linkedList.display();
  17.         System.out.println(linkedList.size());
  18.         // 任意位置插入
  19.         linkedList.randomInsert(1, 7);
  20.         linkedList.randomInsert(1, 7);
  21.         linkedList.randomInsert(1, 7);
  22.         linkedList.randomInsert(8, 8);
  23.         linkedList.display();
  24.         linkedList.randomInsert(8, 7);
  25.         linkedList.display();
  26.         linkedList.randomInsert(8, 8);
  27.         linkedList.display();
  28.         System.out.println(linkedList.size());
  29.         linkedList.randomInsert(2, 111);
  30.         linkedList.randomInsert(3, 111);
  31.         linkedList.display();
  32.         System.out.println(linkedList.size());
  33.         // 删除所有和 val 相等的节点
  34.         linkedList.removeAllVal(7);
  35.         linkedList.display();
  36.         System.out.println(linkedList.size());
  37.         // 删除链表中第一个 val 相等的节点
  38.         linkedList.remove(111);
  39.         linkedList.remove(6);
  40.         linkedList.remove(3);
  41.         linkedList.display();
  42.         System.out.println(linkedList.size());
  43.         // 删除 index 处的节点
  44.         linkedList.removeOfIndex(1);
  45.         linkedList.removeOfIndex(6);
  46.         linkedList.removeOfIndex(2);
  47.         linkedList.display();
  48.         System.out.println(linkedList.size());
  49.         // 找到 val 第一次出现的位置
  50.         System.out.println(linkedList.indexOf(2));
  51.         System.out.println(linkedList.indexOf(8));
  52.         // 找到val 最后一次出现的位置
  53.         System.out.println(linkedList.lastOfIndex(2));
  54.         System.out.println(linkedList.lastOfIndex(8));
  55.         // 清空链表
  56.         linkedList.clear();
  57.         System.out.println(linkedList.size());
  58.     }
  59. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表