链表的代码实现

news/2025/2/13 23:29:44/文章来源:https://www.cnblogs.com/techyu/p/18714594
  1. 双链表的代码实现
import java.util.NoSuchElementException;public class MyLinkedList<E> {// 虚拟头尾节点final private Node<E> head, tail;private int size;// 双链表节点private static class Node<E> {E val;Node<E> next;Node<E> prev;Node(E val) {this.val = val;}}// 构造函数初始化虚拟头尾节点public MyLinkedList() {this.head = new Node<>(null);this.tail = new Node<>(null);head.next = tail;tail.prev = head;this.size = 0;}// ***** 增 *****public void addLast(E e) {Node<E> x = new Node<>(e);Node<E> temp = tail.prev;// temp <-> xtemp.next = x;x.prev = temp;x.next = tail;tail.prev = x;// temp <-> x <-> tailsize++;}public void addFirst(E e) {Node<E> x = new Node<>(e);Node<E> temp = head.next;// head <-> temptemp.prev = x;x.next = temp;head.next = x;x.prev = head;// head <-> x <-> tempsize++;}public void add(int index, E element) {checkPositionIndex(index);if (index == size) {addLast(element);return;}// 找到 index 对应的 NodeNode<E> p = getNode(index);Node<E> temp = p.prev;// temp <-> p// 新要插入的 NodeNode<E> x = new Node<>(element);p.prev = x;temp.next = x;x.prev = temp;x.next = p;// temp <-> x <-> psize++;}// ***** 删 *****public E removeFirst() {if (size < 1) {throw new NoSuchElementException();}// 虚拟节点的存在是我们不用考虑空指针的问题Node<E> x = head.next;Node<E> temp = x.next;// head <-> x <-> temphead.next = temp;temp.prev = head;x.prev = null;x.next = null;// head <-> tempsize--;return x.val;}public E removeLast() {if (size < 1) {throw new NoSuchElementException();}Node<E> x = tail.prev;Node<E> temp = tail.prev.prev;// temp <-> x <-> tailtail.prev = temp;temp.next = tail;x.prev = null;x.next = null;// temp <-> tailsize--;return x.val;}public E remove(int index) {checkElementIndex(index);// 找到 index 对应的 NodeNode<E> x = getNode(index);Node<E> prev = x.prev;Node<E> next = x.next;// prev <-> x <-> nextprev.next = next;next.prev = prev;x.prev = x.next = null;// prev <-> nextsize--;return x.val;}// ***** 查 *****public E get(int index) {checkElementIndex(index);// 找到 index 对应的 NodeNode<E> p = getNode(index);return p.val;}public E getFirst() {if (size < 1) {throw new NoSuchElementException();}return head.next.val;}public E getLast() {if (size < 1) {throw new NoSuchElementException();}return tail.prev.val;}// ***** 改 *****public E set(int index, E val) {checkElementIndex(index);// 找到 index 对应的 NodeNode<E> p = getNode(index);E oldVal = p.val;p.val = val;return oldVal;}// ***** 其他工具函数 *****public int size() {return size;}public boolean isEmpty() {return size == 0;}private Node<E> getNode(int index) {checkElementIndex(index);Node<E> p = head.next;// TODO: 可以优化,通过 index 判断从 head 还是 tail 开始遍历for (int i = 0; i < index; i++) {p = p.next;}return p;}private boolean isElementIndex(int index) {return index >= 0 && index < size;}private boolean isPositionIndex(int index) {return index >= 0 && index <= size;}// 检查 index 索引位置是否可以存在元素private void checkElementIndex(int index) {if (!isElementIndex(index))throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);}// 检查 index 索引位置是否可以添加元素private void checkPositionIndex(int index) {if (!isPositionIndex(index))throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);}private void display() {System.out.println("size = " + size);for (Node<E> p = head.next; p != tail; p = p.next) {System.out.print(p.val + " <-> ");}System.out.println("null");System.out.println();}public static void main(String[] args) {MyLinkedList<Integer> list = new MyLinkedList<>();list.addLast(1);list.addLast(2);list.addLast(3);list.addFirst(0);list.add(2, 100);list.display();// size = 5// 0 <-> 1 <-> 100 <-> 2 -> 3 -> null}
}
  1. 单链表的代码实现
import java.util.NoSuchElementException;public class MyLinkedList2<E> {private static class Node<E> {E val;Node<E> next;Node(E val) {this.val = val;this.next = null;}}private Node<E> head;// 实际的尾部节点引用private Node<E> tail;private int size;public MyLinkedList2() {this.head = new Node<>(null);this.tail = head;this.size = 0;}public void addFirst(E e) {Node<E> newNode = new Node<>(e);newNode.next = head.next;head.next = newNode;if (size == 0) {tail = newNode;}size++;}public void addLast(E e) {Node<E> newNode = new Node<>(e);tail.next = newNode;tail = newNode;size++;}public void add(int index, E element) {checkPositionIndex(index);if (index == size) {addLast(element);return;}Node<E> prev = head;for (int i = 0; i < index; i++) {prev = prev.next;}Node<E> newNode = new Node<>(element);newNode.next = prev.next;prev.next = newNode;size++;}public E removeFirst() {if (isEmpty()) {throw new NoSuchElementException();}Node<E> first = head.next;head.next = first.next;if (size == 1) {tail = head;}size--;return first.val;}public E removeLast() {if (isEmpty()) {throw new NoSuchElementException();}Node<E> prev = head;while (prev.next != tail) {prev = prev.next;}E val = tail.val;prev.next = null;tail = prev;size--;return val;}public E remove(int index) {checkElementIndex(index);Node<E> prev = head;for (int i = 0; i < index; i++) {prev = prev.next;}Node<E> nodeToRemove = prev.next;prev.next = nodeToRemove.next;// 删除的是最后一个元素if (index == size - 1) {tail = prev;}size--;return nodeToRemove.val;}// ***** 查 *****public E getFirst() {if (isEmpty()) {throw new NoSuchElementException();}return head.next.val;}public E getLast() {if (isEmpty()) {throw new NoSuchElementException();}return getNode(size - 1).val;}public E get(int index) {checkElementIndex(index);Node<E> p = getNode(index);return p.val;}// ***** 改 *****public E set(int index, E element) {checkElementIndex(index);Node<E> p = getNode(index);E oldVal = p.val;p.val = element;return oldVal;}// ***** 其他工具函数 *****public int size() {return size;}public boolean isEmpty() {return size == 0;}private boolean isElementIndex(int index) {return index >= 0 && index < size;}private boolean isPositionIndex(int index) {return index >= 0 && index <= size;}// 检查 index 索引位置是否可以存在元素private void checkElementIndex(int index) {if (!isElementIndex(index))throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);}// 检查 index 索引位置是否可以添加元素private void checkPositionIndex(int index) {if (!isPositionIndex(index))throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);}// 返回 index 对应的 Node// 注意:请保证传入的 index 是合法的private Node<E> getNode(int index) {Node<E> p = head.next;for (int i = 0; i < index; i++) {p = p.next;}return p;}public static void main(String[] args) {MyLinkedList2<Integer> list = new MyLinkedList2<>();list.addFirst(1);list.addFirst(2);list.addLast(3);list.addLast(4);list.add(2, 5);System.out.println(list.removeFirst()); // 2System.out.println(list.removeLast()); // 4System.out.println(list.remove(1)); // 5System.out.println(list.getFirst()); // 1System.out.println(list.getLast()); // 3System.out.println(list.get(1)); // 3}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/883459.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

11.A星寻路算法

14.A星寻路算法 题目 迷宫寻路需求,在一个迷宫游戏中,有一些怪物攻击主角,现在希望小怪物,能自动绕过迷宫中的障碍物,寻找到主角的所在。 思路 A星寻路算法(A*search algorithm),是一种用于寻找有效路径的算法。 简单的场景举例(简化问题),看一看A星寻路算法的工作过程。…

人間になりたい。

さよならはエモーション 僕は行く ずっと涙こらえ こらえ 忘れてたエモーション 僕は行く ずっと深い霧の 霧の向こうへ『……组建过,那就好。』 属于我的 Crychic,就在那个寒假啊。 或许更早些,始于一次英语单元测同时爆炸了的三个人,经过一次精彩地赶在元旦零点钟声前分解…

【THM】Security Principles(安全原则)-学习

了解安全三元组以及常见的安全模型和原则。本文相关的TryHackMe实验房间链接:https://tryhackme.com/room/securityprinciples 本文相关内容:了解安全三元组以及常见的安全模型和原则。介绍 网络安全已成为一个流行词;每家公司都声称其网络产品或网络服务是安全的,但事实上…

小米 R3G 路由器刷机教程(Pandavan)

小米 R3G 路由器以其高性价比和稳定的性能备受用户青睐。然而,原厂固件的功能相对有限,难以满足高级用户的个性化需求。刷机不仅可以解锁路由器的潜能,还能通过第三方固件实现更丰富的功能,如 DNS 解析、KMS 服务器、USB 管理等。本文旨在为小米 R3G 路由器用户提供详细的刷…

windows知道服务器的内网IP地址如何查看服务器的计算机名称

windows知道服务器的内网IP地址如何查看服务器的计算机名称windows知道服务器的内网IP地址如何查看服务器的计算机名称 nbtstat百度百科 https://baike.baidu.com/item/nbtstat/7578115 windows在局域网内查看ip地址对应的计算机名或者根据计算机名查ip https://blog.csdn.net/…

C++ 使用MIDI库演奏《晴天》

那些在MIDI库里徘徊的十六分音符 终究没能拼成告白的主歌我把周杰伦的《晴天》写成C++的类在每个midiEvent里埋藏故事的小黄花调试器的断点比初恋更漫长而青春不过是一串未导出的cmake工程文件在堆栈溢出的夜晚终将明白有些旋律永远停在#pragma once的注释里有些人永远停在未定…

JUC并发—2.Thread源码分析及案例应用

大纲 1.什么是线程以及并发编程 2.微服务注册中心案例 3.以工作线程模式开启微服务的注册和心跳线程 4.微服务注册中心的服务注册功能 5.微服务注册中心的心跳续约功能 6.微服务的存活状态监控线程 7.以daemon模式运行微服务的存活监控线程 8.一般不常用到的ThreadGroup是什么 …

HashMap 的 put 方法源码分析(JDK 1.8)

一、HashMap 的 put 方法源码分析(JDK 1.8) 以下是 HashMap 的 put 方法的源码(JDK 1.8):hash(key) 方法 hash(key) 方法用于计算键的哈希值:如果键为 null,返回 0。否则,返回键的哈希码与高 16 位的异或结果(目的是减少哈希冲突)。putVal 方法 putVal 方法是 HashMa…

第二章笔记

2.1用二进制数表示计算机信息的原因 IC的所有引脚,只有直流电压0V或5V 两个状态。也就是说,IC的一个引脚,只能表示两个状态。 计算机处理信息的最小单位——位,就相当于二进制中的一位。位的英文bit是二进制数位(binary digit)的缩写。 二进制数的位数一般是8位、16位、3…

基金年结、结账、关账和开账

基金年结、结账、关账和开账是基金公司年底财务工作中的重要环节,不仅涉及资产、负债、所有者权益等七大要素的核算,还需要进行全面的账务处理和数据校验。本文将详细解读基金年结的背景、目的、概念以及具体流程,帮助大家深入了解这一复杂而关键的财务操作过程。其实年结不…

分组密码工作模式-CBC

CBC全称密文分组链接工作模式:是分组密码算法的一种工作模式,其特征是将当前的明文分组与前一密文分组进行异或运算后再进行加密得到当前的密文分组。 在CBC模式下,每个明文分组在加密之前,先与反馈至输入端的前一组密文分组按位异或后,再送至加密模块进行加密。其中,IV是…