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

445 lines
13 KiB
Markdown
Raw Normal View History

2018-10-12 20:00:59 +00:00
---
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 ----
| + ----- + - + + ----- + - + + ----- + - + |
| |
* * *
\`
**заявка**
Задача тайм-решетки, решаемая операционной системой.
В среде с временным разделением операционная система должна поддерживать список существующих пользователей и должна попеременно разрешать каждому пользователю использовать небольшую часть времени процессора, по одному пользователю за раз. Операционная система выберет пользователя, позволит ему использовать небольшое количество процессорного времени, а затем перейти к следующему пользователю.
Для этого приложения не должно быть указателей NULL, если нет абсолютно никакого запроса на процессорное время, то есть список пуст.
## Основные операции
1. вставка
Чтобы добавить новый элемент в список.
\`
Вставка в начале
* * *
* Создайте новый узел с данными.
* Наведите новый узел `next` со старой `head` .
* Направьте `head` на этот новый узел.
Вставка в середине / конце
* * *
Вставка после узла X.
* Создайте новый узел с данными.
* Наведите новый узел `next` со старым X `next` .
* Точка X находится `next` с этим новым узлом.
\`
**Сложность времени: O (1)**
1. делеция
Чтобы удалить существующий элемент из списка.
\`
Исключение в начале
* * *
* Возьмите узел, указанный `head` как Temp.
* Направьте `head` на `next` .
* Свободная память, используемая узлом Temp.
Удаление в середине / конце
* * *
Удаление после узла X.
* Получите узел, обозначенный `X` как Temp.
* Точка Икс `next` с Temp - х `next` .
* Свободная память, используемая узлом Temp.
\`
**Сложность времени: O (1)**
1. Пересекая
Перемещение по списку.
\`
пересечение
* * *
* Возьмите узел, указанный `head` как Текущий.
* Проверьте, не текут ли ток и отобразите его.
* Направьте ток в ток - х `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` and `prev` ).
2. Случайный доступ в связанном списке невозможен. Мы должны последовательно обращаться к узлам.
3. Это сложнее, чем массив. Если язык автоматически поддерживает привязку массива, массивы будут служить вам лучше.
#### Заметка
Мы должны использовать free () в C и удалять на C ++ для освобождения пространства, используемого удаленным узлом, тогда как в Python и Java свободное пространство автоматически собирается сборщиком мусора.