链表简介(Java实现)
链表是一个线性数据结构,包含一个元素序列,这样每个元素都可以引用序列中的下一个元素。
链接列表中的每个元素称为"节点"。
每个节点都包含一个数据元素和一个下一个Node,它指向链表中的下一个节点。
在链接列表中,我们可以根据需要创建任意数量的节点。
为什么我们需要一个链表?
尽管您可能早先已经看过Arrays数据结构,但它们也是线性数据结构,但是它们具有某些局限性,例如:
它们本质上是静态的,因此它们的大小无法更改。
他们需要连续的内存来存储其值。
解决这些限制链接列表提供以下功能:
动态内存分配,即编译器在运行时完成内存分配。
每个单独的节点可以具有任何内存块,并且通过该块的地址链接到其他节点,因此不需要连续的内存块。
链表的一般实现
链表
链接列表类包含一个私有类Node和一个Node对象类(称为Head)作为其属性之一。
Node头指向链接列表的开始。
每个节点都包含一个数据元素和一个下一个节点,该节点指向链接列表中的下一个节点。
最后的节点指向空。
在较新的变体中,我们还有一个尾节点元素,它可以帮助我们减少易于执行的操作的时间复杂性。
链表操作
链表实现必须具有以下通用方法。
getFirst:它返回第一个节点上存在的数据(如果有的话,否则抛出异常)。
它仅返回" if(this。
Size!= 0!)"提供的" this.head.data",即,如果"链接"列表的大小不为零。getLast:返回最后一个节点上存在的数据(如果有的话,否则抛出异常)。
它仅返回" if(this。
Size!= 0!)"提供的" this.tail.data",即,如果"链接"列表的大小不为零。getAt:它使用一个整数索引作为参数,如果索引有效(即如果index> = 0并且index <链接列表的大小),则返回该索引处存在的元素的数据。
getNodeAt:它将一个整数索引作为参数,如果索引有效(即如果index> = 0且index <链接列表的大小),则返回该索引处的Node。
addLast:接受链接列表类型的输入,然后将其追加到链接列表的最后一个位置,从而将大小增加" +1",并将"尾部"指向新添加的Node。
addFirst:它接受链接列表类型的输入,然后将其追加到链接列表的第一位置,从而将大小增加" +1",并将" head"指向新添加的Node。
addAt:它接受链表的类型的输入,并且还使用整数索引(使其等于'k')作为参数,然后将其(数据)附加在链表的第k个位置,从而将大小增加" +1"。
如果要添加的元素是" First"或者" Last",则分别调用" addFirst"或者" addLast"。removeFirst:删除链接列表的第一个元素(假设列表不是一个空列表,其中抛出异常),并将" head"指向第二个元素(如果有的话),并通过' 1'。
同样,它返回删除的数据。removeLast:删除链接列表的最后一个元素(假设列表不是一个空列表,其中抛出异常),并将" tail"移动到最后一个第二个元素(如果有的话),并减小大小'1'。
同样,它返回删除的数据。removeAt:它以整数索引(比如说k)作为参数,并且如果索引有效(即,如果index> = 0且index <链表的大小),则移除链表的'kth'元素(前提是链表是而不是一个空列表,它会引发异常)并将大小减小
1。
同样,它返回删除的数据。
如果要删除的元素是" First"或者" Last",则分别调用" removeFirst"或者" removeLast"。display:此方法通过从指向" head"的指针开始直到指向" null"的指针遍历,来打印整个Linked列表。
Java中的链表实现
package com.theitroad.ds;
public class LinkedList {
private class Node {
int data;
Node next;
}
private Node head;
private Node tail;
private int size;
public int size() {
return this.size;
}
public int getFirst() throws Exception {
if (this.size == 0) {
throw new Exception("LL is Empty.");
}
return this.head.data;
}
public int getLast() throws Exception {
if (this.size == 0) {
throw new Exception("LL is Empty.");
}
return this.tail.data;
}
public int getAt(int idx) throws Exception {
if (this.size == 0) {
throw new Exception("LL is Empty.");
}
if (idx < 0 || idx >= this.size) {
throw new Exception("Invalid Index.");
}
Node temp = this.head;
for (int i = 1; i <= idx; i++) {
temp = temp.next;
}
return temp.data;
}
private Node getNodeAt(int idx) throws Exception {
if (this.size == 0) {
throw new Exception("LL is Empty.");
}
if (idx < 0 || idx >= this.size) {
throw new Exception("Invalid Index.");
}
Node temp = this.head;
for (int i = 1; i <= idx; i++) {
temp = temp.next;
}
return temp;
}
public void addLast(int item) {
//create
Node nn = new Node();
nn.data = item;
nn.next = null;
//attach
if (this.size > 0)
this.tail.next = nn;
//dm update
if (this.size == 0) {
this.head = nn;
this.tail = nn;
this.size += 1;
} else {
this.tail = nn;
this.size += 1;
}
}
public void addFirst(int item) {
//create
Node nn = new Node();
nn.data = item;
nn.next = null;
//attach
nn.next = this.head;
//dm update
if (this.size == 0) {
this.head = nn;
this.tail = nn;
this.size++;
} else {
this.head = nn;
this.size++;
}
}
public void addAt(int item, int idx) throws Exception {
if (idx < 0 || idx > this.size) {
throw new Exception("Invalid Index.");
}
if (idx == 0) {
addFirst(item);
} else if (idx == this.size) {
addLast(item);
} else {
//create
Node nn = new Node();
nn.data = item;
nn.next = null;
//attach
Node nm1 = getNodeAt(idx - 1);
Node np1 = nm1.next;
nm1.next = nn;
nn.next = np1;
//dm
this.size++;
}
}
public int removeFirst() throws Exception {
if (this.size == 0) {
throw new Exception("LL is empty.");
}
Node temp = this.head;
if (this.size == 1) {
this.head = null;
this.tail = null;
this.size = 0;
} else {
this.head = this.head.next;
this.size--;
}
return temp.data;
}
public int removeLast() throws Exception {
if (this.size == 0) {
throw new Exception("LL is empty.");
}
Node temp = this.tail;
if (this.size == 1) {
this.head = null;
this.tail = null;
this.size = 0;
} else {
Node sm2 = getNodeAt(this.size - 2);
sm2.next = null;
this.tail = sm2;
this.size--;
}
return temp.data;
}
public int removeAt(int idx) throws Exception {
if (this.size == 0) {
throw new Exception("LL is empty.");
}
if (idx < 0 || idx >= this.size) {
throw new Exception("Invalid Index.");
}
if (idx == 0) {
return removeFirst();
} else if (idx == this.size - 1) {
return removeLast();
} else {
Node nm1 = getNodeAt(idx - 1);
Node n = nm1.next;
Node np1 = n.next;
nm1.next = np1;
this.size--;
return n.data;
}
}
public void display() {
System.out.println("----------------------");
Node temp = this.head;
while (temp != null) {
System.out.print(temp.data + " ");
temp = temp.next;
}
System.out.println(".");
System.out.println("----------------------");
}
public static void main(String[] args) throws Exception {
LinkedList list = new LinkedList();
list.addLast(10);
list.addLast(20);
list.addLast(30);
list.addLast(40);
//this will display the list
list.display();
//first element i.e.10 should be printed
System.out.println(list.getFirst());
//last element i.e.40 should be printed
System.out.println(list.getLast());
//element at 3rd index i.e.40 should be printed
System.out.println(list.getAt(3));
//a memory address of a node should be printed
System.out.println(list.getNodeAt(3));
//10 should be removed and printed
System.out.println(list.removeFirst());
//40 should be removed and printed
System.out.println(list.removeLast());
//list without 10 and 40 should be printed
list.display();
//100 should be added at first
list.addFirst(100);
list.display();
//30 should be removed
list.removeAt(2);
//300 should be added at 2nd index
list.addAt(300, 2);
list.display();
}
}
注意:Java提供了LinkedList的实现。
对于实际编程,请使用官方实现。
<p><a href="https://www.theitroad.local/13386/java-linkedlist-linkedlist-java">Java LinkedList – LinkedList In Java</a></p>
链表操作时间复杂度
| Operations | Time Complexity |
|---|---|
| getFirst | O(1) |
| getLast | O(1) {注意:这是因为我们也有'tail'指针,否则应该是O(n)} |
| getAt | O(n) |
| getNodeAt | O(n) |
| addLast | O(1) {注意:这是因为我们也有'tail'指针,否则应该是O(n)} |
| addFirst | O(1) |
| addAt | O(n) |
| removeFirst | O(1) |
| removeLast | O(1) {注意:这是因为我们也有'tail'指针,否则应该是O(n)} |
| removeAt | O(n) |
| Display | O(n) |

