链表代码实现
几个关键点
下面我会分别用双链表和单链给出一个简单的 MyLinkedList
代码实现,包含了基本的增删查改功能。这里给出几个关键点,等会你看代码的时候可以着重注意一下。
关键点一、同时持有头尾节点的引用
在力扣做题时,一般题目给我们传入的就是单链表的头指针。但是在实际开发中,用的都是双链表,而双链表一般会同时持有头尾节点的引用。
因为在软件开发中,在容器尾部添加元素是个非常高频的操作,双链表持有尾部节点的引用,就可以在 的时间复杂度内完成尾部添加元素的操作。
对于单链表来说,持有尾部节点的引用也有优化效果。比如你要在单链表尾部添加元素,如果没有尾部节点的引用,你就需要遍历整个链表找到尾部节点,时间复杂度是 ;如果有尾部节点的引用,就可以在 的时间复杂度内完成尾部添加元素的操作。
细心的读者可能会说,即便如此,如果删除一次单链表的尾结点,那么之前尾结点的引用就失效了,还是需要遍历一遍链表找到尾结点。
是的,但你再仔细想想,删除单链表尾结点的时候,是不是也得遍历到倒数第二个节点(尾结点的前驱),才能通过指针操作把尾结点删掉?那么这个时候,你不就可以顺便把尾结点的引用给更新了吗?
关键点二、虚拟头尾节点
在上一篇文章 链表基础 中我提到过「虚拟头尾节点」技巧,它的原理很简单,就是在创建双链表时就创建一个虚拟头节点和一个虚拟尾节点,无论双链表是否为空,这两个节点都存在。这样就不会出现空指针的问题,可以避免很多边界情况的处理。
举例来说,假设虚拟头尾节点分别是 dummyHead
和 dummyTail
,那么一条空的双链表长这样:
dummyHead <-> dummyTail
如果你添加 1,2,3
几个元素,那么链表长这样:
dummyHead <-> 1 <-> 2 <-> 3 <-> dummyTail
你以前要把在头部插入元素、在尾部插入元素和在中间插入元素几种情况分开讨论,现在有了头尾虚拟节点,无论链表是否为空,都只需要考虑在中间插入元素的情况就可以了,这样代码会简洁很多。
当然,虚拟头结点会多占用一点内存空间,但是比起给你解决的麻烦,这点空间消耗是划算的。
对于单链表,虚拟头结点有一定的简化作用,但虚拟尾节点没有太大作用。
虚拟节点是内部实现,对外不可见
虚拟节点是你内部实现数据结构的技巧,对外是不可见的。比如按照索引获取元素的 get(index)
方法,都是从真实节点开始计算索引,而不是从虚拟节点开始计算。
关键点三、内存泄露?
在前文 动态数组实现 中,我提到了删除元素时,要注意内存泄露的问题。那么在链表中,删除元素会不会也有内存泄露的问题呢?
尤其是这样的写法,你觉得有没有问题:
// 假设单链表头结点 head = 1 -> 2 -> 3 -> 4 -> 5
// 删除单链表头结点
head = head.next;
// 此时 head = 2 -> 3 -> 4 -> 5
细心的读者可能认为这样写会有内存泄露的问题,因为原来的那个头结点 1
的 next
指针没有断开,依然指向着节点 2
。
但实际上这样写是 OK 的,因为 Java 的垃圾回收的判断机制是看这个对象是否被别人引用,而并不会 care 这个对象是否还引用着别人。
那个节点 1
的 next
指针确实还指向着节点 2
,但是并没有别的指针引用节点 1
了,所以节点 1
最终会被垃圾回收器回收释放。所以说这个场景和数组中删除元素的场景是不一样的,你可以再仔细思考一下。
不过呢,删除节点时,最好还是把被删除节点的指针都置为 null,这是个好习惯,不会有什么代价,还可能避免一些潜在的问题。所以在下面的实现中,无论是否有必要,我都会把被删除节点上的指针置为 null。
如何验证你的实现?
你可以借助力扣第 707 题「设计链表」来验证自己的实现是否正确。
双链表代码实现
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 <-> tail
temp.next = x;
x.prev = temp;
x.next = tail;
tail.prev = x;
// temp <-> x <-> tail
size++;
}
public void addFirst(E e) {
Node<E> x = new Node<>(e);
Node<E> temp = head.next;
// head <-> temp
temp.prev = x;
x.next = temp;
head.next = x;
x.prev = head;
// head <-> x <-> temp
size++;
}
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size) {
addLast(element);
return;
}
// 找到 index 对应的 Node
Node<E> p = getNode(index);
Node<E> temp = p.prev;
// temp <-> p
// 新要插入的 Node
Node<E> x = new Node<>(element);
p.prev = x;
temp.next = x;
x.prev = temp;
x.next = p;
// temp <-> x <-> p
size++;
}
// ***** 删 *****
public E removeFirst() {
if (size < 1) {
throw new NoSuchElementException();
}
// 虚拟节点的存在是我们不用考虑空指针的问题
Node<E> x = head.next;
Node<E> temp = x.next;
// head <-> x <-> temp
head.next = temp;
temp.prev = head;
x.prev = null;
x.next = null;
// head <-> temp
size--;
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 <-> tail
tail.prev = temp;
temp.next = tail;
x.prev = null;
x.next = null;
// temp <-> tail
size--;
return x.val;
}
public E remove(int index) {
checkElementIndex(index);
// 找到 index 对应的 Node
Node<E> x = getNode(index);
Node<E> prev = x.prev;
Node<E> next = x.next;
// prev <-> x <-> next
prev.next = next;
next.prev = prev;
x.prev = x.next = null;
// prev <-> next
size--;
return x.val;
}
// ***** 查 *****
public E get(int index) {
checkElementIndex(index);
// 找到 index 对应的 Node
Node<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 对应的 Node
Node<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
}
}
#include <iostream>
#include <stdexcept>
template<typename E>
class MyLinkedList {
// 虚拟头尾节点
struct Node {
E val;
Node* next;
Node* prev;
Node(E value) : val(value), next(nullptr), prev(nullptr) {}
};
Node* head;
Node* tail;
int size;
public:
// 构造函数初始化虚拟头尾节点
MyLinkedList() {
head = new Node(E());
tail = new Node(E());
head->next = tail;
tail->prev = head;
size = 0;
}
// ***** 增 *****
void addLast(E e) {
Node* x = new Node(e);
Node* temp = tail->prev;
// temp <-> tail
temp->next = x;
x->prev = temp;
x->next = tail;
tail->prev = x;
// temp <-> x <-> tail
size++;
}
void addFirst(E e) {
Node* x = new Node(e);
Node* temp = head->next;
// head <-> temp
temp->prev = x;
x->next = temp;
head->next = x;
x->prev = head;
// head <-> x <-> temp
size++;
}
void add(int index, E element) {
checkPositionIndex(index);
if (index == size) {
addLast(element);
return;
}
// 找到 index 对应的 Node
Node* p = getNode(index);
Node* temp = p->prev;
// temp <-> p
// 新要插入的 Node
Node* x = new Node(element);
p->prev = x;
temp->next = x;
x->prev = temp;
x->next = p;
// temp <-> x <-> p
size++;
}
// ***** 删 *****
E removeFirst() {
if (size < 1) {
throw std::out_of_range("No elements to remove");
}
// 虚拟节点的存在是我们不用考虑空指针的问题
Node* x = head->next;
Node* temp = x->next;
// head <-> x <-> temp
head->next = temp;
temp->prev = head;
delete x;
// head <-> temp
size--;
return temp->val;
}
E removeLast() {
if (size < 1) {
throw std::out_of_range("No elements to remove");
}
Node* x = tail->prev;
Node* temp = tail->prev->prev;
// temp <-> x <-> tail
tail->prev = temp;
temp->next = tail;
delete x;
// temp <-> tail
size--;
return temp->val;
}
E remove(int index) {
checkElementIndex(index);
// 找到 index 对应的 Node
Node* x = getNode(index);
Node* prev = x->prev;
Node* next = x->next;
// prev <-> x <-> next
prev->next = next;
next->prev = prev;
delete x;
// prev <-> next
size--;
return next->val;
}
// ***** 查 *****
E get(int index) {
checkElementIndex(index);
// 找到 index 对应的 Node
Node* p = getNode(index);
return p->val;
}
E getFirst() {
if (size < 1) {
throw std::out_of_range("No elements in the list");
}
return head->next->val;
}
E getLast() {
if (size < 1) {
throw std::out_of_range("No elements in the list");
}
return tail->prev->val;
}
// ***** 改 *****
E set(int index, E val) {
checkElementIndex(index);
// 找到 index 对应的 Node
Node* p = getNode(index);
E oldVal = p->val;
p->val = val;
return oldVal;
}
// ***** 其他工具函数 *****
int getSize() const {
return size;
}
bool isEmpty() const {
return size == 0;
}
private:
Node* getNode(int index) {
checkElementIndex(index);
Node* p = head->next;
// TODO: 可以优化,通过 index 判断从 head 还是 tail 开始遍历
for (int i = 0; i < index; i++) {
p = p->next;
}
return p;
}
bool isElementIndex(int index) const {
return index >= 0 && index < size;
}
bool isPositionIndex(int index) const {
return index >= 0 && index <= size;
}
// 检查 index 索引位置是否可以存在元素
void checkElementIndex(int index) const {
if (!isElementIndex(index))
throw std::out_of_range("Index: " + std::to_string(index) + ", Size: " + std::to_string(size));
}
// 检查 index 索引位置是否可以添加元素
void checkPositionIndex(int index) const {
if (!isPositionIndex(index))
throw std::out_of_range("Index: " + std::to_string(index) + ", Size: " + std::to_string(size));
}
public:
void display() {
std::cout << "size = " << size << std::endl;
for (Node* p = head->next; p != tail; p = p->next) {
std::cout << p->val << " <-> ";
}
std::cout << "null" << std::endl;
std::cout << std::endl;
}
~MyLinkedList() {
while (size > 0) {
removeFirst();
}
delete head;
delete tail;
}
};
int main() {
MyLinkedList<int> list;
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
return 0;
}
class Node:
def __init__(self, val):
self.val = val
self.next = None
self.prev = None
class MyLinkedList:
# 虚拟头尾节点
def __init__(self):
self.head = Node(None)
self.tail = Node(None)
self.head.next = self.tail
self.tail.prev = self.head
self.size = 0
# ***** 增 *****
def add_last(self, e):
x = Node(e)
temp = self.tail.prev
# temp <-> tail
temp.next = x
x.prev = temp
x.next = self.tail
self.tail.prev = x
# temp <-> x <-> tail
self.size += 1
def add_first(self, e):
x = Node(e)
temp = self.head.next
# head <-> temp
temp.prev = x
x.next = temp
self.head.next = x
x.prev = self.head
# head <-> x <-> temp
self.size += 1
def add(self, index, element):
self.check_position_index(index)
if index == self.size:
self.add_last(element)
return
# 找到 index 对应的 Node
p = self.get_node(index)
temp = p.prev
# temp <-> p
# 新要插入的 Node
x = Node(element)
p.prev = x
temp.next = x
x.prev = temp
x.next = p
# temp <-> x <-> p
self.size += 1
# ***** 删 *****
def remove_first(self):
if self.size < 1:
raise IndexError("No elements to remove")
# 虚拟节点的存在是我们不用考虑空指针的问题
x = self.head.next
temp = x.next
# head <-> x <-> temp
self.head.next = temp
temp.prev = self.head
# head <-> temp
self.size -= 1
return x.val
def remove_last(self):
if self.size < 1:
raise IndexError("No elements to remove")
x = self.tail.prev
temp = x.prev
# temp <-> x <-> tail
self.tail.prev = temp
temp.next = self.tail
# temp <-> tail
self.size -= 1
return x.val
def remove(self, index):
self.check_element_index(index)
# 找到 index 对应的 Node
x = self.get_node(index)
prev = x.prev
next = x.next
# prev <-> x <-> next
prev.next = next
next.prev = prev
self.size -= 1
return x.val
# ***** 查 *****
def get(self, index):
self.check_element_index(index)
# 找到 index 对应的 Node
p = self.get_node(index)
return p.val
def get_first(self):
if self.size < 1:
raise IndexError("No elements in the list")
return self.head.next.val
def get_last(self):
if self.size < 1:
raise IndexError("No elements in the list")
return self.tail.prev.val
# ***** 改 *****
def set(self, index, val):
self.check_element_index(index)
# 找到 index 对应的 Node
p = self.get_node(index)
old_val = p.val
p.val = val
return old_val
# ***** 其他工具函数 *****
def size(self):
return self.size
def is_empty(self):
return self.size == 0
def get_node(self, index):
self.check_element_index(index)
p = self.head.next
# TODO: 可以优化,通过 index 判断从 head 还是 tail 开始遍历
for _ in range(index):
p = p.next
return p
def is_element_index(self, index):
return 0 <= index < self.size
def is_position_index(self, index):
return 0 <= index <= self.size
# 检查 index 索引位置是否可以存在元素
def check_element_index(self, index):
if not self.is_element_index(index):
raise IndexError(f"Index: {index}, Size: {self.size}")
# 检查 index 索引位置是否可以添加元素
def check_position_index(self, index):
if not self.is_position_index(index):
raise IndexError(f"Index: {index}, Size: {self.size}")
def display(self):
print(f"size = {self.size}")
p = self.head.next
while p != self.tail:
print(f"{p.val} <-> ", end="")
p = p.next
print("null\n")
if __name__ == "__main__":
list = MyLinkedList()
list.add_last(1)
list.add_last(2)
list.add_last(3)
list.add_first(0)
list.add(2, 100)
list.display()
# size = 5
# 0 <-> 1 <-> 100 <-> 2 <-> 3 <-> null
class Node {
constructor(val) {
this.val = val;
this.next = null;
this.prev = null;
}
}
class MyLinkedList {
// 虚拟头尾节点
constructor() {
this.head = new Node(null);
this.tail = new Node(null);
this.head.next = this.tail;
this.tail.prev = this.head;
this.size = 0;
}
// ***** 增 *****
addLast(e) {
const x = new Node(e);
const temp = this.tail.prev;
// temp <-> tail
temp.next = x;
x.prev = temp;
x.next = this.tail;
this.tail.prev = x;
// temp <-> x <-> tail
this.size++;
}
addFirst(e) {
const x = new Node(e);
const temp = this.head.next;
// head <-> temp
temp.prev = x;
x.next = temp;
this.head.next = x;
x.prev = this.head;
// head <-> x <-> temp
this.size++;
}
add(index, element) {
this.checkPositionIndex(index);
if (index === this.size) {
this.addLast(element);
return;
}
// 找到 index 对应的 Node
const p = this.getNode(index);
const temp = p.prev;
// temp <-> p
// 新要插入的 Node
const x = new Node(element);
p.prev = x;
temp.next = x;
x.prev = temp;
x.next = p;
// temp <-> x <-> p
this.size++;
}
// ***** 删 *****
removeFirst() {
if (this.size < 1) {
throw new Error("No elements to remove");
}
// 虚拟节点的存在是我们不用考虑空指针的问题
const x = this.head.next;
const temp = x.next;
// head <-> x <-> temp
this.head.next = temp;
temp.prev = this.head;
// head <-> temp
this.size--;
return x.val;
}
removeLast() {
if (this.size < 1) {
throw new Error("No elements to remove");
}
const x = this.tail.prev;
const temp = x.prev;
// temp <-> x <-> tail
this.tail.prev = temp;
temp.next = this.tail;
// temp <-> tail
this.size--;
return x.val;
}
remove(index) {
this.checkElementIndex(index);
// 找到 index 对应的 Node
const x = this.getNode(index);
const prev = x.prev;
const next = x.next;
// prev <-> x <-> next
prev.next = next;
next.prev = prev;
this.size--;
return x.val;
}
// ***** 查 *****
get(index) {
this.checkElementIndex(index);
// 找到 index 对应的 Node
const p = this.getNode(index);
return p.val;
}
getFirst() {
if (this.size < 1) {
throw new Error("No elements in the list");
}
return this.head.next.val;
}
getLast() {
if (this.size < 1) {
throw new Error("No elements in the list");
}
return this.tail.prev.val;
}
// ***** 改 *****
set(index, val) {
this.checkElementIndex(index);
// 找到 index 对应的 Node
const p = this.getNode(index);
const oldVal = p.val;
p.val = val;
return oldVal;
}
// ***** 其他工具函数 *****
size() {
return this.size;
}
isEmpty() {
return this.size === 0;
}
getNode(index) {
this.checkElementIndex(index);
let p = this.head.next;
// TODO: 可以优化,通过 index 判断从 head 还是 tail 开始遍历
for (let i = 0; i < index; i++) {
p = p.next;
}
return p;
}
isElementIndex(index) {
return index >= 0 && index < this.size;
}
isPositionIndex(index) {
return index >= 0 && index <= this.size;
}
// 检查 index 索引位置是否可以存在元素
checkElementIndex(index) {
if (!this.isElementIndex(index)) {
throw new Error(`Index: ${index}, Size: ${this.size}`);
}
}
// 检查 index 索引位置是否可以添加元素
checkPositionIndex(index) {
if (!this.isPositionIndex(index)) {
throw new Error(`Index: ${index}, Size: ${this.size}`);
}
}
display() {
console.log(`size = ${this.size}`);
let p = this.head.next;
let str = "";
while (p !== this.tail) {
str += `${p.val} <-> `;
p = p.next;
}
console.log(str + "null\n");
}
}
// Testing the MyLinkedList class
const 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
package main
import (
"errors"
"fmt"
)
type Node struct {
val interface{}
next *Node
prev *Node
}
type MyLinkedList struct {
head *Node
tail *Node
size int
}
// 虚拟头尾节点
func NewMyLinkedList() *MyLinkedList {
head := &Node{}
tail := &Node{}
head.next = tail
tail.prev = head
return &MyLinkedList{head: head, tail: tail, size: 0}
}
// ***** 增 *****
func (list *MyLinkedList) AddLast(e interface{}) {
x := &Node{val: e}
temp := list.tail.prev
// temp <-> tail
temp.next = x
x.prev = temp
x.next = list.tail
list.tail.prev = x
// temp <-> x <-> tail
list.size++
}
func (list *MyLinkedList) AddFirst(e interface{}) {
x := &Node{val: e}
temp := list.head.next
// head <-> temp
temp.prev = x
x.next = temp
list.head.next = x
x.prev = list.head
// head <-> x <-> temp
list.size++
}
func (list *MyLinkedList) Add(index int, element interface{}) {
list.checkPositionIndex(index)
if index == list.size {
list.AddLast(element)
return
}
// 找到 index 对应的 Node
p := list.getNode(index)
temp := p.prev
// temp <-> p
// 新要插入的 Node
x := &Node{val: element}
p.prev = x
temp.next = x
x.prev = temp
x.next = p
// temp <-> x <-> p
list.size++
}
// ***** 删 *****
func (list *MyLinkedList) RemoveFirst() (interface{}, error) {
if list.size < 1 {
return nil, errors.New("no elements to remove")
}
// 虚拟节点的存在是我们不用考虑空指针的问题
x := list.head.next
temp := x.next
// head <-> x <-> temp
list.head.next = temp
temp.prev = list.head
// head <-> temp
list.size--
return x.val, nil
}
func (list *MyLinkedList) RemoveLast() (interface{}, error) {
if list.size < 1 {
return nil, errors.New("no elements to remove")
}
x := list.tail.prev
temp := x.prev
// temp <-> x <-> tail
list.tail.prev = temp
temp.next = list.tail
// temp <-> tail
list.size--
return x.val, nil
}
func (list *MyLinkedList) Remove(index int) (interface{}, error) {
list.checkElementIndex(index)
// 找到 index 对应的 Node
x := list.getNode(index)
prev := x.prev
next := x.next
// prev <-> x <-> next
prev.next = next
next.prev = prev
list.size--
return x.val, nil
}
// ***** 查 *****
func (list *MyLinkedList) Get(index int) (interface{}, error) {
list.checkElementIndex(index)
// 找到 index 对应的 Node
p := list.getNode(index)
return p.val, nil
}
func (list *MyLinkedList) GetFirst() (interface{}, error) {
if list.size < 1 {
return nil, errors.New("no elements in the list")
}
return list.head.next.val, nil
}
func (list *MyLinkedList) GetLast() (interface{}, error) {
if list.size < 1 {
return nil, errors.New("no elements in the list")
}
return list.tail.prev.val, nil
}
// ***** 改 *****
func (list *MyLinkedList) Set(index int, val interface{}) (interface{}, error) {
list.checkElementIndex(index)
// 找到 index 对应的 Node
p := list.getNode(index)
oldVal := p.val
p.val = val
return oldVal, nil
}
// ***** 其他工具函数 *****
func (list *MyLinkedList) Size() int {
return list.size
}
func (list *MyLinkedList) IsEmpty() bool {
return list.size == 0
}
func (list *MyLinkedList) getNode(index int) *Node {
list.checkElementIndex(index)
p := list.head.next
// TODO: 可以优化,通过 index 判断从 head 还是 tail 开始遍历
for i := 0; i < index; i++ {
p = p.next
}
return p
}
func (list *MyLinkedList) isElementIndex(index int) bool {
return index >= 0 && index < list.size
}
func (list *MyLinkedList) isPositionIndex(index int) bool {
return index >= 0 && index <= list.size
}
// 检查 index 索引位置是否可以存在元素
func (list *MyLinkedList) checkElementIndex(index int) {
if !list.isElementIndex(index) {
panic(fmt.Sprintf("Index: %d, Size: %d", index, list.size))
}
}
// 检查 index 索引位置是否可以添加元素
func (list *MyLinkedList) checkPositionIndex(index int) {
if !list.isPositionIndex(index) {
panic(fmt.Sprintf("Index: %d, Size: %d", index, list.size))
}
}
func (list *MyLinkedList) Display() {
fmt.Printf("size = %d\n", list.size)
p := list.head.next
for p != list.tail {
fmt.Printf("%v <-> ", p.val)
p = p.next
}
fmt.Println("null\n")
}
func main() {
list := NewMyLinkedList()
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
}
单链表代码实现
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()); // 2
System.out.println(list.removeLast()); // 4
System.out.println(list.remove(1)); // 5
System.out.println(list.getFirst()); // 1
System.out.println(list.getLast()); // 3
System.out.println(list.get(1)); // 3
}
}
#include <iostream>
#include <stdexcept>
template <typename E>
class MyLinkedList2 {
private:
// 节点结构
struct Node {
E val;
Node* next;
Node(E value) : val(value), next(nullptr) {}
};
Node* head;
// 实际的尾部节点引用
Node* tail;
int size_;
public:
MyLinkedList2() {
head = new Node(E());
tail = head;
size_ = 0;
}
void addFirst(E e) {
Node* newNode = new Node(e);
newNode->next = head->next;
head->next = newNode;
if (size_ == 0) {
tail = newNode;
}
size_++;
}
void addLast(E e) {
Node* newNode = new Node(e);
tail->next = newNode;
tail = newNode;
size_++;
}
void add(int index, E element) {
checkPositionIndex(index);
if (index == size_) {
addLast(element);
return;
}
Node* prev = head;
for (int i = 0; i < index; i++) {
prev = prev->next;
}
Node* newNode = new Node(element);
newNode->next = prev->next;
prev->next = newNode;
size_++;
}
E removeFirst() {
if (isEmpty()) {
throw std::out_of_range("No elements to remove");
}
Node* first = head->next;
head->next = first->next;
if (size_ == 1) {
tail = head;
}
size_--;
E val = first->val;
delete first;
return val;
}
E removeLast() {
if (isEmpty()) {
throw std::out_of_range("No elements to remove");
}
Node* prev = head;
while (prev->next != tail) {
prev = prev->next;
}
E val = tail->val;
delete tail;
prev->next = nullptr;
tail = prev;
size_--;
return val;
}
E remove(int index) {
checkElementIndex(index);
Node* prev = head;
for (int i = 0; i < index; i++) {
prev = prev->next;
}
Node* nodeToRemove = prev->next;
prev->next = nodeToRemove->next;
// 删除的是最后一个元素
if (index == size_ - 1) {
tail = prev;
}
size_--;
E val = nodeToRemove->val;
delete nodeToRemove;
return val;
}
// ***** 查 *****
E getFirst() {
if (isEmpty()) {
throw std::out_of_range("No elements in the list");
}
return head->next->val;
}
E getLast() {
if (isEmpty()) {
throw std::out_of_range("No elements in the list");
}
return getNode(size_ - 1)->val;
}
E get(int index) {
checkElementIndex(index);
Node* p = getNode(index);
return p->val;
}
// ***** 改 *****
E set(int index, E element) {
checkElementIndex(index);
Node* p = getNode(index);
E oldVal = p->val;
p->val = element;
return oldVal;
}
// ***** 其他工具函数 *****
int size() {
return size_;
}
bool isEmpty() {
return size_ == 0;
}
private:
bool isElementIndex(int index) {
return index >= 0 && index < size_;
}
bool isPositionIndex(int index) {
return index >= 0 && index <= size_;
}
// 检查 index 索引位置是否可以存在元素
void checkElementIndex(int index) {
if (!isElementIndex(index)) {
throw std::out_of_range("Index: " + std::to_string(index) + ", size_: " + std::to_string(size_));
}
}
// 检查 index 索引位置是否可以添加元素
void checkPositionIndex(int index) {
if (!isPositionIndex(index)) {
throw std::out_of_range("Index: " + std::to_string(index) + ", size_: " + std::to_string(size_));
}
}
// 返回 index 对应的 Node
// 注意:请保证传入的 index 是合法的
Node* getNode(int index) {
Node* p = head->next;
for (int i = 0; i < index; i++) {
p = p->next;
}
return p;
}
};
int main() {
MyLinkedList2<int> list;
list.addFirst(1);
list.addFirst(2);
list.addLast(3);
list.addLast(4);
list.add(2, 5);
std::cout << list.removeFirst() << std::endl; // 2
std::cout << list.removeLast() << std::endl; // 4
std::cout << list.remove(1) << std::endl; // 5
std::cout << list.getFirst() << std::endl; // 1
std::cout << list.getLast() << std::endl; // 3
std::cout << list.get(1) << std::endl; // 3
return 0;
}
class MyLinkedList2:
class Node:
def __init__(self, val):
self.val = val
self.next = None
def __init__(self):
self.head = self.Node(None)
self.tail = self.head
self.size = 0
def add_first(self, e):
new_node = self.Node(e)
new_node.next = self.head.next
self.head.next = new_node
if self.size == 0:
self.tail = new_node
self.size += 1
def add_last(self, e):
new_node = self.Node(e)
self.tail.next = new_node
self.tail = new_node
self.size += 1
def add(self, index, element):
self.check_position_index(index)
if index == self.size:
self.add_last(element)
return
prev = self.head
for i in range(index):
prev = prev.next
new_node = self.Node(element)
new_node.next = prev.next
prev.next = new_node
self.size += 1
def remove_first(self):
if self.is_empty():
raise Exception("NoSuchElementException")
first = self.head.next
self.head.next = first.next
if self.size == 1:
self.tail = self.head
self.size -= 1
return first.val
def remove_last(self):
if self.is_empty():
raise Exception("NoSuchElementException")
prev = self.head
while prev.next != self.tail:
prev = prev.next
val = self.tail.val
prev.next = None
self.tail = prev
self.size -= 1
return val
def remove(self, index):
self.check_element_index(index)
prev = self.head
for i in range(index):
prev = prev.next
node_to_remove = prev.next
prev.next = node_to_remove.next
# 删除的是最后一个元素
if index == self.size - 1:
self.tail = prev
self.size -= 1
return node_to_remove.val
# ***** 查 *****
def get_first(self):
if self.is_empty():
raise Exception("NoSuchElementException")
return self.head.next.val
def get_last(self):
if self.is_empty():
raise Exception("NoSuchElementException")
return self.get_node(self.size - 1).val
def get(self, index):
self.check_element_index(index)
p = self.get_node(index)
return p.val
# ***** 改 *****
def set(self, index, element):
self.check_element_index(index)
p = self.get_node(index)
old_val = p.val
p.val = element
return old_val
# ***** 其他工具函数 *****
def size(self):
return self.size
def is_empty(self):
return self.size == 0
def is_element_index(self, index):
return 0 <= index < self.size
def is_position_index(self, index):
return 0 <= index <= self.size
# 检查 index 索引位置是否可以存在元素
def check_element_index(self, index):
if not self.is_element_index(index):
raise IndexError(f"Index: {index}, Size: {self.size}")
# 检查 index 索引位置是否可以添加元素
def check_position_index(self, index):
if not self.is_position_index(index):
raise IndexError(f"Index: {index}, Size: {self.size}")
# 返回 index 对应的 Node
# 注意:请保证传入的 index 是合法的
def get_node(self, index):
p = self.head.next
for i in range(index):
p = p.next
return p
if __name__ == "__main__":
list = MyLinkedList2()
list.add_first(1)
list.add_first(2)
list.add_last(3)
list.add_last(4)
list.add(2, 5)
print(list.remove_first()) # 2
print(list.remove_last()) # 4
print(list.remove(1)) # 5
print(list.get_first()) # 1
print(list.get_last()) # 3
print(list.get(1)) # 3
// 节点类
class Node {
constructor(val) {
this.val = val;
this.next = null;
}
}
class MyLinkedList2 {
constructor() {
this.head = new Node(null);
this.tail = this.head;
this.size = 0;
}
addFirst(e) {
const newNode = new Node(e);
newNode.next = this.head.next;
this.head.next = newNode;
if (this.size === 0) {
this.tail = newNode;
}
this.size++;
}
addLast(e) {
const newNode = new Node(e);
this.tail.next = newNode;
this.tail = newNode;
this.size++;
}
add(index, element) {
this.checkPositionIndex(index);
if (index === this.size) {
this.addLast(element);
return;
}
let prev = this.head;
for (let i = 0; i < index; i++) {
prev = prev.next;
}
const newNode = new Node(element);
newNode.next = prev.next;
prev.next = newNode;
this.size++;
}
removeFirst() {
if (this.isEmpty()) {
throw new Error("NoSuchElementException");
}
const first = this.head.next;
this.head.next = first.next;
if (this.size === 1) {
this.tail = this.head;
}
this.size--;
return first.val;
}
removeLast() {
if (this.isEmpty()) {
throw new Error("NoSuchElementException");
}
let prev = this.head;
while (prev.next !== this.tail) {
prev = prev.next;
}
const val = this.tail.val;
prev.next = null;
this.tail = prev;
this.size--;
return val;
}
remove(index) {
this.checkElementIndex(index);
let prev = this.head;
for (let i = 0; i < index; i++) {
prev = prev.next;
}
const nodeToRemove = prev.next;
prev.next = nodeToRemove.next;
// 删除的是最后一个元素
if (index === this.size - 1) {
this.tail = prev;
}
this.size--;
return nodeToRemove.val;
}
// ***** 查 *****
getFirst() {
if (this.isEmpty()) {
throw new Error("NoSuchElementException");
}
return this.head.next.val;
}
getLast() {
if (this.isEmpty()) {
throw new Error("NoSuchElementException");
}
return this.getNode(this.size - 1).val;
}
get(index) {
this.checkElementIndex(index);
const p = this.getNode(index);
return p.val;
}
// ***** 改 *****
set(index, element) {
this.checkElementIndex(index);
const p = this.getNode(index);
const oldVal = p.val;
p.val = element;
return oldVal;
}
// ***** 其他工具函数 *****
size() {
return this.size;
}
isEmpty() {
return this.size === 0;
}
isElementIndex(index) {
return index >= 0 && index < this.size;
}
isPositionIndex(index) {
return index >= 0 && index <= this.size;
}
// 检查 index 索引位置是否可以存在元素
checkElementIndex(index) {
if (!this.isElementIndex(index)) {
throw new Error(`Index: ${index}, Size: ${this.size}`);
}
}
// 检查 index 索引位置是否可以添加元素
checkPositionIndex(index) {
if (!this.isPositionIndex(index)) {
throw new Error(`Index: ${index}, Size: ${this.size}`);
}
}
// 返回 index 对应的 Node
// 注意:请保证传入的 index 是合法的
getNode(index) {
let p = this.head.next;
for (let i = 0; i < index; i++) {
p = p.next;
}
return p;
}
}
// 示例使用
const list = new MyLinkedList2();
list.addFirst(1);
list.addFirst(2);
list.addLast(3);
list.addLast(4);
list.add(2, 5);
console.log(list.removeFirst()); // 2
console.log(list.removeLast()); // 4
console.log(list.remove(1)); // 5
console.log(list.getFirst()); // 1
console.log(list.getLast()); // 3
console.log(list.get(1)); // 3
package main
import (
"errors"
"fmt"
)
// Node 节点结构
type Node[E any] struct {
val E
next *Node[E]
}
// MyLinkedList2 链表结构
type MyLinkedList2[E any] struct {
head *Node[E]
// 实际的尾部节点引用
tail *Node[E]
size_ int
}
// NewMyLinkedList2 创建一个新的链表
func NewMyLinkedList2[E any]() *MyLinkedList2[E] {
head := &Node[E]{}
return &MyLinkedList2[E]{head: head, tail: head, size_: 0}
}
// addFirst 在头部添加元素
func (list *MyLinkedList2[E]) addFirst(e E) {
newNode := &Node[E]{val: e}
newNode.next = list.head.next
list.head.next = newNode
if list.size_ == 0 {
list.tail = newNode
}
list.size_++
}
// addLast 在尾部添加元素
func (list *MyLinkedList2[E]) addLast(e E) {
newNode := &Node[E]{val: e}
list.tail.next = newNode
list.tail = newNode
list.size_++
}
// add 在指定索引处添加元素
func (list *MyLinkedList2[E]) add(index int, element E) error {
if index < 0 || index > list.size_ {
return errors.New("index out of bounds")
}
if index == list.size_ {
list.addLast(element)
return nil
}
prev := list.head
for i := 0; i < index; i++ {
prev = prev.next
}
newNode := &Node[E]{val: element}
newNode.next = prev.next
prev.next = newNode
list.size_++
return nil
}
// removeFirst 移除头部元素
func (list *MyLinkedList2[E]) removeFirst() (E, error) {
if list.isEmpty() {
return *new(E), errors.New("no elements to remove")
}
first := list.head.next
list.head.next = first.next
if list.size_ == 1 {
list.tail = list.head
}
list.size_--
return first.val, nil
}
// removeLast 移除尾部元素
func (list *MyLinkedList2[E]) removeLast() (E, error) {
if list.isEmpty() {
return *new(E), errors.New("no elements to remove")
}
prev := list.head
for prev.next != list.tail {
prev = prev.next
}
val := list.tail.val
prev.next = nil
list.tail = prev
list.size_--
return val, nil
}
// remove 在指定索引处移除元素
func (list *MyLinkedList2[E]) remove(index int) (E, error) {
if index < 0 || index >= list.size_ {
return *new(E), errors.New("index out of bounds")
}
prev := list.head
for i := 0; i < index; i++ {
prev = prev.next
}
nodeToRemove := prev.next
prev.next = nodeToRemove.next
// 删除的是最后一个元素
if index == list.size_-1 {
list.tail = prev
}
list.size_--
return nodeToRemove.val, nil
}
// getFirst 获取头部元素
func (list *MyLinkedList2[E]) getFirst() (E, error) {
if list.isEmpty() {
return *new(E), errors.New("no elements in the list")
}
return list.head.next.val, nil
}
// getLast 获取尾部元素
func (list *MyLinkedList2[E]) getLast() (E, error) {
if list.isEmpty() {
return *new(E), errors.New("no elements in the list")
}
return list.getNode(list.size_ - 1).val, nil
}
// get 获取指定索引的元素
func (list *MyLinkedList2[E]) get(index int) (E, error) {
if index < 0 || index >= list.size_ {
return *new(E), errors.New("index out of bounds")
}
return list.getNode(index).val, nil
}
// set 更新指定索引的元素
func (list *MyLinkedList2[E]) set(index int, element E) (E, error) {
if index < 0 || index >= list.size_ {
return *new(E), errors.New("index out of bounds")
}
node := list.getNode(index)
oldVal := node.val
node.val = element
return oldVal, nil
}
// size 获取链表大小
func (list *MyLinkedList2[E]) size() int {
return list.size_
}
// isEmpty 检查链表是否为空
func (list *MyLinkedList2[E]) isEmpty() bool {
return list.size_ == 0
}
// getNode 返回指定索引的节点
func (list *MyLinkedList2[E]) getNode(index int) *Node[E] {
p := list.head.next
for i := 0; i < index; i++ {
p = p.next
}
return p
}
func main() {
list := NewMyLinkedList2[int]()
list.addFirst(1)
list.addFirst(2)
list.addLast(3)
list.addLast(4)
list.add(2, 5)
if val, err := list.removeFirst(); err == nil {
fmt.Println(val) // 2
}
if val, err := list.removeLast(); err == nil {
fmt.Println(val) // 4
}
if val, err := list.remove(1); err == nil {
fmt.Println(val) // 5
}
if val, err := list.getFirst(); err == nil {
fmt.Println(val) // 1
}
if val, err := list.getLast(); err == nil {
fmt.Println(val) // 3
}
if val, err := list.get(1); err == nil {
fmt.Println(val) // 3
}
}