347 lines
11 KiB
Markdown
347 lines
11 KiB
Markdown
|
---
|
|||
|
title: Linked Lists
|
|||
|
localeTitle: 链接列表
|
|||
|
---
|
|||
|
## 链接列表
|
|||
|
|
|||
|
#### 链表是一种简单的_线性访问_数据结构。
|
|||
|
|
|||
|
链表是一种简单的数据结构,但它可用于实现更复杂的数据结构,如队列,堆栈等。链接列表有三种类型:
|
|||
|
|
|||
|
1. 简单链接列表
|
|||
|
2. 双重链接列表(或双端链接列表)
|
|||
|
3. 圆形链接列表(环形缓冲区)
|
|||
|
|
|||
|
链接列表| (介绍) 与数组一样,Linked List是一种线性数据结构。与数组不同,链表元素不存储在连续的位置;使用Javascript(对下一个节点的引用)使用指针或类似链接元素。
|
|||
|
|
|||
|
如果您想了解链接列表,有助于理解**数组** 。
|
|||
|
|
|||
|
回顾一下,数组传统上是一种**静态** **线性**数据结构,支持恒定时间随机访问。插入和删除并不总是恒定的时间。
|
|||
|
|
|||
|
阵列的优点 1)动态尺寸 2)易于插入/删除
|
|||
|
|
|||
|
\`\`\` static = size在创建时固定 线性=作为单个块线性存储在存储器中
|
|||
|
```
|
|||
|
#### Arrays have the following disadvantages:-
|
|||
|
1. Arrays are static structures and therefore cannot be easily extended or reduced to fit the data set.
|
|||
|
2. Arrays are also expensive to maintain new insertions and deletions.
|
|||
|
|
|||
|
Linked Lists address some of the limitations of arrays. Unlike an array, where all the elements are stored in a contiguous block of memory, in a linked list each element is a separate object and has a **link** to the next element in sequence. This allows a linked list to start with space for only one element, and grow to accomodate an arbitrary number of elements by allocating memory as and when needed.
|
|||
|
|
|||
|
Deleting elements is also simply handled by manipulating links.
|
|||
|
|
|||
|
Once you understand the Simple Linked List (which from here on will be referred as **'List'**), you can move on to the Doubly Linked List.
|
|||
|
|
|||
|
A List as illustrated below is made up of the following components:-
|
|||
|
```
|
|||
|
|
|||
|
```
|
|||
|
head
|
|||
|
|
|
|||
|
|
|
|||
|
+---+---+ +---+---+ +----+------+
|
|||
|
| 1 | o----->| 2 | o-----> | 3 | φ |
|
|||
|
+---+---+ +---+---+ +----+------+
|
|||
|
|
|
|||
|
|
|
|||
|
tail
|
|||
|
```
|
|||
|
|
|||
|
```
|
|||
|
| Node | Significance |
|
|||
|
| ----------|-------------|
|
|||
|
| HEAD | Beginning of the List|
|
|||
|
| Node(s) | Dynamically allocated self-referential block contain 1 Data element and a link to the next node |
|
|||
|
| TAIL | End of the List |
|
|||
|
|
|||
|
Most common operations available on List are,
|
|||
|
1. AddFirst - Inserts an element at the front of the List.
|
|||
|
2. AddLast - Inserts an element at the tail of the List.
|
|||
|
3. InsertAfter - Inserts an element after an existing element in the List.
|
|||
|
4. InsertBefore - Inserts an element before an existing element in the List.
|
|||
|
5. Remove - Remove an existing element from the List.
|
|||
|
6. Access / Peek - Access an existing element from the List.
|
|||
|
7. Size / Count - Returns the number of elements currently present in the List.
|
|||
|
8. IsEmpty - Check whether the List is empty or not.
|
|||
|
|
|||
|
#### Implementation of a Simple Linked List in C++
|
|||
|
```
|
|||
|
|
|||
|
CPP
|
|||
|
|
|||
|
# 包括
|
|||
|
|
|||
|
使用命名空间std;
|
|||
|
|
|||
|
结构编号 { int num; struct Number \* tail; };
|
|||
|
|
|||
|
typedef struct Number N;
|
|||
|
|
|||
|
班级名单 { 私人的: N _头,_结束; int count;
|
|||
|
```
|
|||
|
public:
|
|||
|
void display();
|
|||
|
void insertBefore(int);
|
|||
|
List();
|
|||
|
```
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
List :: List() { 头= NULL; 结束= NULL; 计数= 0; }
|
|||
|
|
|||
|
void List :: insertBefore(int data) { N \*节点; node = new N; 节点 - > NUM =数据; 节点 - >尾= NULL;
|
|||
|
```
|
|||
|
if(!head){
|
|||
|
head=end=node;
|
|||
|
}
|
|||
|
|
|||
|
else{
|
|||
|
node->tail=head;
|
|||
|
head=node;
|
|||
|
}
|
|||
|
|
|||
|
count++;
|
|||
|
```
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void List :: display() { cout <<“list中的节点数=”<< count << endl; N \*节点; 节点=头; 而(节点) {
|
|||
|
```
|
|||
|
cout<<node->num<<endl;
|
|||
|
node=node->tail;
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
} int main() { 清单l1;
|
|||
|
```
|
|||
|
l1.insertBefore(10);
|
|||
|
l1.insertBefore(20);
|
|||
|
l1.insertBefore(30);
|
|||
|
l1.insertBefore(40);
|
|||
|
l1.insertBefore(50);
|
|||
|
l1.display();
|
|||
|
|
|||
|
return 0;
|
|||
|
```
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
#### OUTPUT
|
|||
|
```
|
|||
|
|
|||
|
列表中的节点数= 5 50 40 三十 20 10
|
|||
|
```
|
|||
|
#### Explanation
|
|||
|
```
|
|||
|
|
|||
|
CPP
|
|||
|
|
|||
|
结构编号 { int num; struct Number \* tail;
|
|||
|
|
|||
|
};
|
|||
|
```
|
|||
|
Declaration of a structure(node) with 2 data members
|
|||
|
* `num` holds the integer data value
|
|||
|
* `*tail` pointer points to the next node in the List
|
|||
|
```
|
|||
|
|
|||
|
CPP 班级名单 { 私人的: N _头,_结束; int count;
|
|||
|
```
|
|||
|
public:
|
|||
|
void display();
|
|||
|
void insertBefore(int);
|
|||
|
List();
|
|||
|
```
|
|||
|
|
|||
|
};
|
|||
|
```
|
|||
|
The List class declares the Linked List.
|
|||
|
* `*head` points to the first node in the List
|
|||
|
* `*end` points to the last node in the List
|
|||
|
* `count` holds the value for number of nodes in the list
|
|||
|
* `display()` is used to print the complete list on the console
|
|||
|
* `insertBefore()` is used to insert a new node
|
|||
|
* `List()` is a defualt constructor
|
|||
|
```
|
|||
|
|
|||
|
CPP List :: List() { 头= NULL; 结束= NULL; 计数= 0; }
|
|||
|
```
|
|||
|
The default constructor is used to initialize the data members of the List class with default values
|
|||
|
```
|
|||
|
|
|||
|
CPP void List :: insertBefore(int data) { N \*节点; node = new N; 节点 - > NUM =数据; 节点 - >尾= NULL;
|
|||
|
```
|
|||
|
if(!head){
|
|||
|
head=end=node;
|
|||
|
}
|
|||
|
|
|||
|
else{
|
|||
|
node->tail=head;
|
|||
|
head=node;
|
|||
|
}
|
|||
|
|
|||
|
count++;
|
|||
|
```
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
* A new node is created.
|
|||
|
* `num` is assigned the value of `data`.
|
|||
|
* `tail` is pointing to Null.
|
|||
|
* The `if(!head)` condition is true only when there are no elements in the List.
|
|||
|
* When this is the case, `head` and `end` are both pointing to the newly created node.
|
|||
|
* Control will move to the `else` section, when there is at least one node in the list.
|
|||
|
* In this case, `tail` pointer in the newly created node is made to point to the `head`(first) node.
|
|||
|
* The `head` pointer then points to the newly created node to make it the first node in the list.
|
|||
|
* `count` is incremented by 1 as each new node is added.
|
|||
|
```
|
|||
|
|
|||
|
CPP void List :: display() { N \*节点; 节点=头; 而(节点) { COUT < NUM <
|
|||
|
```
|
|||
|
The display function is used to run through the list and print the total number of nodes and values of `num` on the console.
|
|||
|
|
|||
|
#### Applications
|
|||
|
* Base Data Structure for Vector, Array, Queue, Stack, etc
|
|||
|
* Polynomial Representation
|
|||
|
* Ring Buffer
|
|||
|
|
|||
|
Drawbacks:
|
|||
|
1) Random access is not allowed. We have to access elements sequentially starting from the first node. So we cannot do binary search with linked lists.
|
|||
|
2) Extra memory space for a pointer is required with each element of the list
|
|||
|
|
|||
|
|
|||
|
Types:
|
|||
|
1) (Singly) linked lists contain nodes which have a data field as well as a 'next' field, which points to the next node in line of nodes. Operations that can be performed on singly linked lists include insertion, deletion and traversal.
|
|||
|
|
|||
|
2) (Doubly) In a 'doubly linked list', each node contains, besides the next-node link, a second link field pointing to the 'previous' node in the sequence. The two links may be called 'forward('s') and 'backwards', or 'next' and 'prev'('previous').
|
|||
|
|
|||
|
Example in Javascript:
|
|||
|
```
|
|||
|
|
|||
|
function LinkedList(){ this.head = null; this.tail = null; }
|
|||
|
```
|
|||
|
// Node has three properties value, next, prev
|
|||
|
|
|||
|
function Node (value, next, prev) {
|
|||
|
|
|||
|
this.value = value;
|
|||
|
|
|||
|
// A 'pointer' referencing to the next Node (if present) otherwise null
|
|||
|
|
|||
|
this.next = next;
|
|||
|
|
|||
|
// A 'pointer' referencing the previous Node, otherwise null
|
|||
|
|
|||
|
this.prev = prev;
|
|||
|
}
|
|||
|
|
|||
|
LinkedList.prototype.addToHead = function(value) {
|
|||
|
|
|||
|
let newNode = new Node(value, this.head, null);
|
|||
|
|
|||
|
if (this.head) this.head.prev = newNode;
|
|||
|
|
|||
|
else this.tail = newNode;
|
|||
|
|
|||
|
this.head = newNode;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
```
|
|||
|
Now Execute code
|
|||
|
```
|
|||
|
|
|||
|
让LL = new LinkedList();
|
|||
|
```
|
|||
|
LL.addToHead(100);
|
|||
|
|
|||
|
LL.addToHead(200);
|
|||
|
|
|||
|
console.log(LL);
|
|||
|
```
|
|||
|
|
|||
|
```
|
|||
|
Representation in C:
|
|||
|
A linked list is represented by a pointer to the first node of the linked list. The first node is called head. If the linked list is empty, then value of head is NULL.
|
|||
|
Each node in a list consists of at least two parts:
|
|||
|
1) data
|
|||
|
2) pointer to the next node
|
|||
|
In C, we can represent a node using structures. Below is an example of a linked list node with an integer data.
|
|||
|
In Java, LinkedList can be represented as a class and a Node as a separate class. The LinkedList class contains a reference of Node class type
|
|||
|
```
|
|||
|
|
|||
|
C //链表节点 struct Node { int数据; struct Node \* next; };
|
|||
|
```
|
|||
|
# Linked List with three elements
|
|||
|
```
|
|||
|
|
|||
|
C //一个简单的C程序来介绍 //一个链表
|
|||
|
|
|||
|
# 包括
|
|||
|
|
|||
|
# 包括
|
|||
|
|
|||
|
struct Node { int数据; struct Node \* next; };
|
|||
|
|
|||
|
//程序创建一个简单的链接 //列出3个节点 int main() { struct Node \* head = NULL; struct Node \* second = NULL; struct Node \* third = NULL;
|
|||
|
|
|||
|
//在堆中分配3个节点
|
|||
|
head =(struct Node _)malloc(sizeof(struct Node)); second =(struct Node_ )malloc(sizeof(struct Node)); third =(struct Node \*)malloc(sizeof(struct Node));
|
|||
|
|
|||
|
/ \*动态分配了三个块。 我们指向这三个块作为第一,第二和第三块
|
|||
|
排在第二位 | | | | | | + --- + ----- + + ---- + ---- + + ---- + ---- + | #| #| | #| #| | #| #| + --- + ----- + + ---- + ---- + + ---- + ---- +
|
|||
|
|
|||
|
#代表任何随机值。 数据是随机的,因为我们还没有分配任何东西\* /
|
|||
|
|
|||
|
head-> data = 1; //在第一个节点中分配数据 head-> next = second; //将第一个节点与第二个节点链接
|
|||
|
|
|||
|
/ \*数据已分配给第一个块的数据部分(块 头部指出)。并且第一个块的下一个指针指向 第二。所以他们都是相互关联的。
|
|||
|
```
|
|||
|
head second third
|
|||
|
| | |
|
|||
|
| | |
|
|||
|
+---+---+ +----+----+ +-----+----+
|
|||
|
| 1 | o----->| # | # | | # | # |
|
|||
|
+---+---+ +----+----+ +-----+----+
|
|||
|
```
|
|||
|
|
|||
|
\* /
|
|||
|
|
|||
|
second-> data = 2; //将数据分配给第二个节点 second-> next = third; //将第二个节点与第三个节点链接
|
|||
|
|
|||
|
/ \*数据已分配给第二个块的数据部分(由块指向的块) 第二)。并且第二个块的下一个指针指向第三个块。
|
|||
|
因此所有三个块都是链接的。
|
|||
|
```
|
|||
|
head second third
|
|||
|
| | |
|
|||
|
| | |
|
|||
|
+---+---+ +---+---+ +----+----+
|
|||
|
| 1 | o----->| 2 | o-----> | # | # |
|
|||
|
+---+---+ +---+---+ +----+----+ */
|
|||
|
```
|
|||
|
|
|||
|
第三 - > data = 3; //将数据分配给第三个节点 third-> next = NULL;
|
|||
|
|
|||
|
/ \*数据已分配给第三个块的数据部分(块指向 第三)。并且第三个块的下一个指针为NULL以指示 链接列表在这里终止。
|
|||
|
```
|
|||
|
We have the linked list ready.
|
|||
|
|
|||
|
head
|
|||
|
|
|
|||
|
|
|
|||
|
+---+---+ +---+---+ +----+------+
|
|||
|
| 1 | o----->| 2 | o-----> | 3 | NULL |
|
|||
|
+---+---+ +---+---+ +----+------+
|
|||
|
|
|||
|
|
|||
|
Note that only head is sufficient to represent the whole list. We can
|
|||
|
traverse the complete list by following next pointers. */
|
|||
|
```
|
|||
|
|
|||
|
返回0; } \`\`\`
|
|||
|
|
|||
|
#### 更多信息:
|
|||
|
|
|||
|
* [链接列表简介](http://www.geeksforgeeks.org/linked-list-set-1-introduction/)
|
|||
|
* [链接列表(YouTube视频)](https://www.youtube.com/watch?v=njTh_OwMljA)
|