freeCodeCamp/guide/chinese/miscellaneous/data-structure-linked-list/index.md

445 lines
9.5 KiB
Markdown
Raw Normal View History

---
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` 。
\`
**时间复杂度O1**
1. 删除
从列表中删除现有元素。
\`
删除开头
* * *
* 获取`head`指向的节点为Temp。
* 点`head`到温度的`next` 。
* Temp节点使用的可用内存。
在中间/结尾删除
* * *
节点X后删除。
* 获取`X`指向的节点为Temp。
* 点X `next`着Temp的`next` 。
* Temp节点使用的可用内存。
\`
**时间复杂度O1**
1. 遍历
穿越列表。
\`
穿越
* * *
* 获取`head`指向的节点为Current。
* 检查Current是否为空并显示它。
* 点电流为当前的`next` ,并移动到上面的步骤。
\`
**时间复杂度On//这里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中可用垃圾收集器自动收集空间。