445 lines
9.5 KiB
Markdown
445 lines
9.5 KiB
Markdown
---
|
||
title: Data Structure Linked List
|
||
localeTitle: 数据结构链表
|
||
---
|
||
就像用花朵制作的花环一样,链表由节点组成。我们称这个特殊花环上的每朵花都是一个节点。并且每个节点指向该列表中的下一个节点以及它具有数据(这里是花的类型)。
|
||
|
||
## 类型
|
||
|
||
1. 单链表
|
||
|
||
单链表包含具有`data`字段和`next`字段的节点,该字段指向序列中的下一个节点。可以在单链表上执行的操作是插入,删除和遍历。
|
||
|
||
\`
|
||
```
|
||
Singly Link List
|
||
```
|
||
|
||
* * *
|
||
```
|
||
head
|
||
|
|
||
|
|
||
+-----+--+ +-----+--+ +-----+------+
|
||
| 1 |o-----> | 2 |o-----> | 3 | NULL |
|
||
+-----+--+ +-----+--+ +-----+------+
|
||
```
|
||
|
||
\`
|
||
|
||
应用
|
||
|
||
CPython的内部实现,框架和评估变量保存在堆栈中。
|
||
|
||
为此我们需要迭代前向aur得到头部,因此单独使用链表。
|
||
|
||
1. 双重链表
|
||
|
||
双向链表包含具有`data`字段的节点, `next`字段和指向序列中前一节点的另一个链接字段`prev` 。
|
||
|
||
\`
|
||
|
||
双重链表
|
||
|
||
* * *
|
||
```
|
||
head
|
||
|
|
||
|
|
||
+------+-----+--+ +--+-----+--+ +-----+------+
|
||
| | |o------> | |o------> | | |
|
||
| NULL | 1 | | 2 | | 3 | NULL |
|
||
| | | <------o| | <------o| | |
|
||
+------+-----+--+ +--+-----+--+ +-----+------+
|
||
```
|
||
|
||
\`
|
||
|
||
应用
|
||
|
||
浏览器缓存,允许您点击BACK和FORWARD按钮。在这里,我们需要维护一个双向链表, `URLs`作为数据字段,以允许双向访问。要转到上一个URL,我们将使用`prev`字段,并转到下一页,我们将使用`next`字段。
|
||
|
||
1. 循环链表
|
||
|
||
循环链表是单链表,其中最后一个节点, `next`字段指向序列中的第一个节点。
|
||
|
||
\`
|
||
|
||
循环链表
|
||
|
||
* * *
|
||
```
|
||
head
|
||
|
|
||
|
|
||
+-----+--+ +-----+--+ +-----+--+
|
||
```
|
||
|
||
\- > | 1 | o -----> | 2 | o -----> | 3 | o ----
|
||
| + ----- + - + + ----- + - + + ----- + - + |
|
||
| |
|
||
|
||
* * *
|
||
|
||
\`
|
||
|
||
**应用**
|
||
|
||
分时问题由操作系统解决。
|
||
|
||
在分时环境中,操作系统必须维护当前用户的列表,并且必须允许每个用户一次使用一小部分CPU时间,一个用户。操作系统将选择一个用户,让他/她使用少量的CPU时间,然后转到下一个用户。
|
||
|
||
对于这个应用程序,应该没有NULL指针,除非绝对没有人请求CPU时间,即列表为空。
|
||
|
||
## 基本操作
|
||
|
||
1. 插入
|
||
|
||
要向列表中添加新元素。
|
||
|
||
\`
|
||
|
||
插入开头
|
||
|
||
* * *
|
||
|
||
* 使用给定数据创建新节点。
|
||
* 将新节点指向旧`head` `next` 。
|
||
* 点`head`到这个新的节点。
|
||
|
||
插入中间/结尾
|
||
|
||
* * *
|
||
|
||
在节点X之后插入。
|
||
|
||
* 使用给定数据创建新节点。
|
||
* 指向新节点的`next`老X的`next` 。
|
||
* 点X在此新节点`next` 。
|
||
\`
|
||
|
||
**时间复杂度:O(1)**
|
||
|
||
1. 删除
|
||
|
||
从列表中删除现有元素。
|
||
|
||
\`
|
||
|
||
删除开头
|
||
|
||
* * *
|
||
|
||
* 获取`head`指向的节点为Temp。
|
||
* 点`head`到温度的`next` 。
|
||
* Temp节点使用的可用内存。
|
||
|
||
在中间/结尾删除
|
||
|
||
* * *
|
||
|
||
节点X后删除。
|
||
|
||
* 获取`X`指向的节点为Temp。
|
||
* 点X `next`着Temp的`next` 。
|
||
* Temp节点使用的可用内存。
|
||
\`
|
||
|
||
**时间复杂度:O(1)**
|
||
|
||
1. 遍历
|
||
|
||
穿越列表。
|
||
|
||
\`
|
||
|
||
穿越
|
||
|
||
* * *
|
||
|
||
* 获取`head`指向的节点为Current。
|
||
* 检查Current是否为空并显示它。
|
||
* 点电流为当前的`next` ,并移动到上面的步骤。
|
||
\`
|
||
|
||
**时间复杂度:O(n)//这里n是链接列表的大小**
|
||
|
||
## 履行
|
||
|
||
### 单链表的C ++实现
|
||
```
|
||
// Header files
|
||
#include <iostream>
|
||
|
||
struct node
|
||
{
|
||
int data;
|
||
struct node *next;
|
||
};
|
||
|
||
// Head pointer always points to first element of the linked list
|
||
struct node *head = NULL;
|
||
```
|
||
|
||
#### 在每个节点中打印数据
|
||
```
|
||
// Display the list
|
||
void printList()
|
||
{
|
||
struct node *ptr = head;
|
||
|
||
// Start from the beginning
|
||
while(ptr != NULL)
|
||
{
|
||
std::cout << ptr->data << " ";
|
||
ptr = ptr->next;
|
||
}
|
||
|
||
std::cout << std::endl;
|
||
}
|
||
```
|
||
|
||
#### 插入开头
|
||
```
|
||
// Insert link at the beginning
|
||
void insertFirst(int data)
|
||
{
|
||
// Create a new node
|
||
struct node *new_node = new struct node;
|
||
|
||
new_node->data = data;
|
||
|
||
// Point it to old head
|
||
new_node->next = head;
|
||
|
||
// Point head to new node
|
||
head = new_node;
|
||
|
||
std::cout << "Inserted successfully" << std::endl;
|
||
}
|
||
```
|
||
|
||
#### 删除开头
|
||
```
|
||
// Delete first item
|
||
void deleteFirst()
|
||
{
|
||
// Save reference to head
|
||
struct node *temp = head;
|
||
|
||
// Point head to head's next
|
||
head = head->next;
|
||
|
||
// Free memory used by temp
|
||
temp = NULL:
|
||
delete temp;
|
||
|
||
std::cout << "Deleted successfully" << std::endl;
|
||
}
|
||
```
|
||
|
||
#### 尺寸
|
||
```
|
||
// Find no. of nodes in link list
|
||
void size()
|
||
{
|
||
int length = 0;
|
||
struct node *current;
|
||
|
||
for(current = head; current != NULL; current = current->next)
|
||
{
|
||
length++;
|
||
}
|
||
|
||
std::cout << "Size of Linked List is " << length << std::endl;
|
||
}
|
||
```
|
||
|
||
#### 搜索
|
||
```
|
||
// Find node with given data
|
||
void find(int data){
|
||
|
||
// Start from the head
|
||
struct node* current = head;
|
||
|
||
// If list is empty
|
||
if(head == NULL)
|
||
{
|
||
std::cout << "List is empty" << std::endl;
|
||
return;
|
||
}
|
||
|
||
// Traverse through list
|
||
while(current->data != data){
|
||
|
||
// If it is last node
|
||
if(current->next == NULL){
|
||
std::cout << "Not Found" << std::endl;
|
||
return;
|
||
}
|
||
else{
|
||
// Go to next node
|
||
current = current->next;
|
||
}
|
||
}
|
||
|
||
// If data found
|
||
std::cout << "Found" << std::endl;
|
||
}
|
||
```
|
||
|
||
#### 节点后删除
|
||
```
|
||
// Delete a node with given data
|
||
void del(int data){
|
||
|
||
// Start from the first node
|
||
struct node* current = head;
|
||
struct node* previous = NULL;
|
||
|
||
// If list is empty
|
||
if(head == NULL){
|
||
std::cout << "List is empty" << std::endl;
|
||
return ;
|
||
}
|
||
|
||
// Navigate through list
|
||
while(current->data != data){
|
||
|
||
// If it is last node
|
||
if(current->next == NULL){
|
||
std::cout << "Element not found" << std::endl;
|
||
return ;
|
||
}
|
||
else {
|
||
// Store reference to current node
|
||
previous = current;
|
||
// Move to next node
|
||
current = current->next;
|
||
}
|
||
|
||
}
|
||
|
||
// Found a match, update the node
|
||
if(current == head) {
|
||
// Change head to point to next node
|
||
head = head->next;
|
||
}
|
||
else {
|
||
// Skip the current node
|
||
previous->next = current->next;
|
||
}
|
||
|
||
// Free space used by deleted node
|
||
current = NULL;
|
||
delete current;
|
||
std::cout << "Deleted succesfully" << std::endl;
|
||
}
|
||
```
|
||
|
||
![:rocket:](https://forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=3 ":火箭:") [运行代码](https://repl.it/CXVt/1)
|
||
|
||
### 单链表的Python实现
|
||
```
|
||
class Node(object):
|
||
# Constructor
|
||
def __init__(self, data=None, next=None):
|
||
self.data = data
|
||
self.next = next
|
||
|
||
# Function to get data
|
||
def get_data(self):
|
||
return self.data
|
||
|
||
# Function to get next node
|
||
def get_next(self):
|
||
return self.next
|
||
|
||
# Function to set next field
|
||
def set_next(self, new_next):
|
||
self.next = new_next
|
||
class LinkedList(object):
|
||
def __init__(self, head=None):
|
||
self.head = head
|
||
```
|
||
|
||
#### 插入
|
||
```
|
||
# Function to insert data
|
||
def insert(self, data):
|
||
# new_node is a object of class Node
|
||
new_node = Node(data)
|
||
new_node.set_next(self.head)
|
||
self.head = new_node
|
||
print("Node with data " + str(data) + " is created succesfully")
|
||
```
|
||
|
||
#### 尺寸
|
||
```
|
||
# Function to get size
|
||
def size(self):
|
||
current = self.head
|
||
count = 0
|
||
while current:
|
||
count += 1
|
||
current = current.get_next()
|
||
print("Size of link list is " + str(count))
|
||
```
|
||
|
||
#### 搜索
|
||
```
|
||
# Function to search a data
|
||
def search(self, data):
|
||
current = self.head
|
||
found = False
|
||
while current and found is False:
|
||
if current.get_data() == data:
|
||
found = True
|
||
else:
|
||
current = current.get_next()
|
||
if current is None:
|
||
print("Node with data " + str(data) + " is not present")
|
||
else:
|
||
print("Node with data " + str(data) + " is found")
|
||
```
|
||
|
||
#### 节点后删除
|
||
```
|
||
# Function to delete a node with data
|
||
def delete(self, data):
|
||
current = self.head
|
||
previous = None
|
||
found = False
|
||
while current and found is False:
|
||
if current.get_data() == data:
|
||
found = True
|
||
else:
|
||
previous = current
|
||
current = current.get_next()
|
||
if current is None:
|
||
print("Node with data " + str(data) + " is not in list")
|
||
elif previous is None:
|
||
self.head = current.get_next()
|
||
print("Node with data " + str(data) + " is deleted successfully")
|
||
else:
|
||
previous.set_next(current.get_next())
|
||
print("Node with data " + str(data) + " is deleted successfully")
|
||
```
|
||
|
||
![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":火箭:") [运行代码](https://repl.it/CVq3/2)
|
||
|
||
**好处**
|
||
|
||
1. 链表是一种动态数据结构,可以在程序运行时增长和收缩,分配和释放内存。
|
||
2. 节点的插入和删除很容易在任何位置的链表中实现。
|
||
|
||
**缺点**
|
||
|
||
1. 由于指针使用的内存( `next`和`prev` ),它们使用的内存比数组多。
|
||
2. 链表中无法随机访问。我们必须按顺序访问节点。
|
||
3. 它比数组更复杂。如果一种语言自动支持数组绑定检查,Arrays会更好地为您服务。
|
||
|
||
#### 注意
|
||
|
||
我们必须在C中使用free()并在C ++中删除以释放已删除节点使用的空间,而在Python和Java中,可用垃圾收集器自动收集空间。 |