* docs(ru): replace prose quotes with guillemets * docs(ru): replace prose semicolons with periods * docs(ru): align animation title forms * docs(ru): align figure and table references
37 KiB
Список
Список (list) - это абстрактное понятие структуры данных, обозначающее упорядоченную коллекцию элементов, которая поддерживает доступ к элементам, их изменение, добавление, удаление и обход, не требуя от пользователя учитывать ограничения по емкости. Список может быть реализован как на основе связного списка, так и на основе массива.
- Связный список естественным образом можно рассматривать как список: он поддерживает операции добавления, удаления, поиска и изменения элементов и может гибко расширяться динамически.
- Массив тоже поддерживает операции добавления, удаления, поиска и изменения элементов, но из-за неизменяемости длины его можно считать лишь списком с ограниченной длиной.
Когда список реализуется с помощью массива, неизменяемость длины снижает его практическую полезность. Причина в том, что мы обычно не можем заранее точно знать, сколько данных нужно хранить, а значит, трудно выбрать подходящую длину списка. Если длина слишком мала, она может не покрыть реальные потребности. Если слишком велика, будет зря расходоваться память.
Чтобы решить эту проблему, можно использовать динамический массив (dynamic array) для реализации списка. Он сохраняет все преимущества массива и при этом может динамически расширяться во время выполнения программы.
На практике списки из стандартных библиотек многих языков программирования реализованы именно на основе динамических массивов, например list в Python, ArrayList в Java, vector в C++ и List в C#. В дальнейшем обсуждении мы будем считать понятия «список» и «динамический массив» эквивалентными.
Основные операции со списком
Инициализация списка
Обычно используются два способа инициализации: без начальных значений и с начальными значениями:
=== "Python"
```python title="list.py"
# Инициализация списка
# Без начальных значений
nums1: list[int] = []
# С начальными значениями
nums: list[int] = [1, 3, 2, 5, 4]
```
=== "C++"
```cpp title="list.cpp"
/* Инициализация списка */
// Обрати внимание: в C++ vector соответствует описываемому здесь nums
// Без начальных значений
vector<int> nums1;
// С начальными значениями
vector<int> nums = { 1, 3, 2, 5, 4 };
```
=== "Java"
```java title="list.java"
/* Инициализация списка */
// Без начальных значений
List<Integer> nums1 = new ArrayList<>();
// С начальными значениями (обрати внимание: элементы массива должны использовать обертку Integer[] вместо int[])
Integer[] numbers = new Integer[] { 1, 3, 2, 5, 4 };
List<Integer> nums = new ArrayList<>(Arrays.asList(numbers));
```
=== "C#"
```csharp title="list.cs"
/* Инициализация списка */
// Без начальных значений
List<int> nums1 = [];
// С начальными значениями
int[] numbers = [1, 3, 2, 5, 4];
List<int> nums = [.. numbers];
```
=== "Go"
```go title="list_test.go"
/* Инициализация списка */
// Без начальных значений
nums1 := []int{}
// С начальными значениями
nums := []int{1, 3, 2, 5, 4}
```
=== "Swift"
```swift title="list.swift"
/* Инициализация списка */
// Без начальных значений
let nums1: [Int] = []
// С начальными значениями
var nums = [1, 3, 2, 5, 4]
```
=== "JS"
```javascript title="list.js"
/* Инициализация списка */
// Без начальных значений
const nums1 = [];
// С начальными значениями
const nums = [1, 3, 2, 5, 4];
```
=== "TS"
```typescript title="list.ts"
/* Инициализация списка */
// Без начальных значений
const nums1: number[] = [];
// С начальными значениями
const nums: number[] = [1, 3, 2, 5, 4];
```
=== "Dart"
```dart title="list.dart"
/* Инициализация списка */
// Без начальных значений
List<int> nums1 = [];
// С начальными значениями
List<int> nums = [1, 3, 2, 5, 4];
```
=== "Rust"
```rust title="list.rs"
/* Инициализация списка */
// Без начальных значений
let nums1: Vec<i32> = Vec::new();
// С начальными значениями
let nums: Vec<i32> = vec![1, 3, 2, 5, 4];
```
=== "C"
```c title="list.c"
// В C нет встроенного динамического массива
```
=== "Kotlin"
```kotlin title="list.kt"
/* Инициализация списка */
// Без начальных значений
var nums1 = listOf<Int>()
// С начальными значениями
var numbers = arrayOf(1, 3, 2, 5, 4)
var nums = numbers.toMutableList()
```
=== "Ruby"
```ruby title="list.rb"
# Инициализация списка
# Без начальных значений
nums1 = []
# С начальными значениями
nums = [1, 3, 2, 5, 4]
```
??? pythontutor "Визуализация выполнения"
https://pythontutor.com/render.html#code=%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%D0%98%D0%BD%D0%B8%D1%86%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%0A%20%20%20%20%23%20%D0%91%D0%B5%D0%B7%20%D0%BD%D0%B0%D1%87%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9%0A%20%20%20%20nums1%20%3D%20%5B%5D%0A%20%20%20%20%23%20%D0%A1%20%D0%BD%D0%B0%D1%87%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC%D0%B8%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D0%BC%D0%B8%0A%20%20%20%20nums%20%3D%20%5B1%2C%203%2C%202%2C%205%2C%204%5D&cumulative=false&curInstr=4&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false
Доступ к элементам
Поскольку в этом разделе список рассматривается как структура на основе динамического массива, доступ к элементам и их обновление можно выполнять за O(1) времени, что очень эффективно.
=== "Python"
```python title="list.py"
# Доступ к элементу
num: int = nums[1] # Доступ к элементу по индексу 1
# Обновление элемента
nums[1] = 0 # Обновить элемент по индексу 1 значением 0
```
=== "C++"
```cpp title="list.cpp"
/* Доступ к элементу */
int num = nums[1]; // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0; // Обновить элемент по индексу 1 значением 0
```
=== "Java"
```java title="list.java"
/* Доступ к элементу */
int num = nums.get(1); // Доступ к элементу по индексу 1
/* Обновление элемента */
nums.set(1, 0); // Обновить элемент по индексу 1 значением 0
```
=== "C#"
```csharp title="list.cs"
/* Доступ к элементу */
int num = nums[1]; // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0; // Обновить элемент по индексу 1 значением 0
```
=== "Go"
```go title="list_test.go"
/* Доступ к элементу */
num := nums[1] // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0 // Обновить элемент по индексу 1 значением 0
```
=== "Swift"
```swift title="list.swift"
/* Доступ к элементу */
let num = nums[1] // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0 // Обновить элемент по индексу 1 значением 0
```
=== "JS"
```javascript title="list.js"
/* Доступ к элементу */
const num = nums[1]; // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0; // Обновить элемент по индексу 1 значением 0
```
=== "TS"
```typescript title="list.ts"
/* Доступ к элементу */
const num: number = nums[1]; // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0; // Обновить элемент по индексу 1 значением 0
```
=== "Dart"
```dart title="list.dart"
/* Доступ к элементу */
int num = nums[1]; // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0; // Обновить элемент по индексу 1 значением 0
```
=== "Rust"
```rust title="list.rs"
/* Доступ к элементу */
let num: i32 = nums[1]; // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0; // Обновить элемент по индексу 1 значением 0
```
=== "C"
```c title="list.c"
// В C нет встроенного динамического массива
```
=== "Kotlin"
```kotlin title="list.kt"
/* Доступ к элементу */
val num = nums[1] // Доступ к элементу по индексу 1
/* Обновление элемента */
nums[1] = 0 // Обновить элемент по индексу 1 значением 0
```
=== "Ruby"
```ruby title="list.rb"
# Доступ к элементу
num = nums[1] # Доступ к элементу по индексу 1
# Обновление элемента
nums[1] = 0 # Обновить элемент по индексу 1 значением 0
```
??? pythontutor "Визуализация выполнения"
https://pythontutor.com/render.html#code=%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%D0%98%D0%BD%D0%B8%D1%86%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%0A%20%20%20%20nums%20%3D%20%5B1%2C%203%2C%202%2C%205%2C%204%5D%0A%0A%20%20%20%20%23%20%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C%20%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%20%D0%BA%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D1%83%0A%20%20%20%20num%20%3D%20nums%5B1%5D%20%20%23%20%D0%BE%D0%B1%D1%80%D0%B0%D1%82%D0%B8%D1%82%D1%8C%D1%81%D1%8F%20%D0%BA%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%201%20%D0%BF%D0%BE%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%0A%0A%20%20%20%20%23%20%D0%9E%D0%B1%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%0A%20%20%20%20nums%5B1%5D%20%3D%200%20%20%20%20%23%20%D0%9E%D0%B1%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%BF%D0%BE%20%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D1%83%201%20%D0%B4%D0%BE%200&cumulative=false&curInstr=3&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false
Вставка и удаление элементов
В отличие от массива список позволяет свободно добавлять и удалять элементы. Добавление элемента в конец списка имеет временную сложность O(1) , но операции вставки и удаления по-прежнему имеют ту же эффективность, что и у массива, то есть O(n) .
=== "Python"
```python title="list.py"
# Очистить список
nums.clear()
# Добавить элементы в конец
nums.append(1)
nums.append(3)
nums.append(2)
nums.append(5)
nums.append(4)
# Вставить элемент в середину
nums.insert(3, 6) # Вставить число 6 по индексу 3
# Удалить элемент
nums.pop(3) # Удалить элемент по индексу 3
```
=== "C++"
```cpp title="list.cpp"
/* Очистить список */
nums.clear();
/* Добавить элементы в конец */
nums.push_back(1);
nums.push_back(3);
nums.push_back(2);
nums.push_back(5);
nums.push_back(4);
/* Вставить элемент в середину */
nums.insert(nums.begin() + 3, 6); // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.erase(nums.begin() + 3); // Удалить элемент по индексу 3
```
=== "Java"
```java title="list.java"
/* Очистить список */
nums.clear();
/* Добавить элементы в конец */
nums.add(1);
nums.add(3);
nums.add(2);
nums.add(5);
nums.add(4);
/* Вставить элемент в середину */
nums.add(3, 6); // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.remove(3); // Удалить элемент по индексу 3
```
=== "C#"
```csharp title="list.cs"
/* Очистить список */
nums.Clear();
/* Добавить элементы в конец */
nums.Add(1);
nums.Add(3);
nums.Add(2);
nums.Add(5);
nums.Add(4);
/* Вставить элемент в середину */
nums.Insert(3, 6); // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.RemoveAt(3); // Удалить элемент по индексу 3
```
=== "Go"
```go title="list_test.go"
/* Очистить список */
nums = nil
/* Добавить элементы в конец */
nums = append(nums, 1)
nums = append(nums, 3)
nums = append(nums, 2)
nums = append(nums, 5)
nums = append(nums, 4)
/* Вставить элемент в середину */
nums = append(nums[:3], append([]int{6}, nums[3:]...)...) // Вставить число 6 по индексу 3
/* Удалить элемент */
nums = append(nums[:3], nums[4:]...) // Удалить элемент по индексу 3
```
=== "Swift"
```swift title="list.swift"
/* Очистить список */
nums.removeAll()
/* Добавить элементы в конец */
nums.append(1)
nums.append(3)
nums.append(2)
nums.append(5)
nums.append(4)
/* Вставить элемент в середину */
nums.insert(6, at: 3) // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.remove(at: 3) // Удалить элемент по индексу 3
```
=== "JS"
```javascript title="list.js"
/* Очистить список */
nums.length = 0;
/* Добавить элементы в конец */
nums.push(1);
nums.push(3);
nums.push(2);
nums.push(5);
nums.push(4);
/* Вставить элемент в середину */
nums.splice(3, 0, 6); // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.splice(3, 1); // Удалить элемент по индексу 3
```
=== "TS"
```typescript title="list.ts"
/* Очистить список */
nums.length = 0;
/* Добавить элементы в конец */
nums.push(1);
nums.push(3);
nums.push(2);
nums.push(5);
nums.push(4);
/* Вставить элемент в середину */
nums.splice(3, 0, 6); // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.splice(3, 1); // Удалить элемент по индексу 3
```
=== "Dart"
```dart title="list.dart"
/* Очистить список */
nums.clear();
/* Добавить элементы в конец */
nums.add(1);
nums.add(3);
nums.add(2);
nums.add(5);
nums.add(4);
/* Вставить элемент в середину */
nums.insert(3, 6); // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.removeAt(3); // Удалить элемент по индексу 3
```
=== "Rust"
```rust title="list.rs"
/* Очистить список */
nums.clear();
/* Добавить элементы в конец */
nums.push(1);
nums.push(3);
nums.push(2);
nums.push(5);
nums.push(4);
/* Вставить элемент в середину */
nums.insert(3, 6); // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.remove(3); // Удалить элемент по индексу 3
```
=== "C"
```c title="list.c"
// В C нет встроенного динамического массива
```
=== "Kotlin"
```kotlin title="list.kt"
/* Очистить список */
nums.clear();
/* Добавить элементы в конец */
nums.add(1);
nums.add(3);
nums.add(2);
nums.add(5);
nums.add(4);
/* Вставить элемент в середину */
nums.add(3, 6); // Вставить число 6 по индексу 3
/* Удалить элемент */
nums.remove(3); // Удалить элемент по индексу 3
```
=== "Ruby"
```ruby title="list.rb"
# Очистить список
nums.clear
# Добавить элементы в конец
nums << 1
nums << 3
nums << 2
nums << 5
nums << 4
# Вставить элемент в середину
nums.insert(3, 6) # Вставить число 6 по индексу 3
# Удалить элемент
nums.delete_at(3) # Удалить элемент по индексу 3
```
??? pythontutor "Визуализация выполнения"
https://pythontutor.com/render.html#code=%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%D0%A1%20%D0%BD%D0%B0%D1%87%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC%D0%B8%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F%D0%BC%D0%B8%0A%20%20%20%20nums%20%3D%20%5B1%2C%203%2C%202%2C%205%2C%204%5D%0A%20%20%20%20%0A%20%20%20%20%23%20%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%B8%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%0A%20%20%20%20nums.clear%28%29%0A%20%20%20%20%0A%20%20%20%20%23%20%D0%94%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20%D0%BA%D0%BE%D0%BD%D0%B5%D1%86%0A%20%20%20%20nums.append%281%29%0A%20%20%20%20nums.append%283%29%0A%20%20%20%20nums.append%282%29%0A%20%20%20%20nums.append%285%29%0A%20%20%20%20nums.append%284%29%0A%20%20%20%20%0A%20%20%20%20%23%20%D0%92%D1%81%D1%82%D0%B0%D0%B2%D0%B8%D1%82%D1%8C%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20%D1%81%D0%B5%D1%80%D0%B5%D0%B4%D0%B8%D0%BD%D1%83%0A%20%20%20%20nums.insert%283%2C%206%29%20%20%23%20%D0%92%D1%81%D1%82%D0%B0%D0%B2%D0%B8%D1%82%D1%8C%20%D1%87%D0%B8%D1%81%D0%BB%D0%BE%206%20%D0%BF%D0%BE%20%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D1%83%203%0A%20%20%20%20%0A%20%20%20%20%23%20%D0%A3%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%0A%20%20%20%20nums.pop%283%29%20%20%20%20%20%20%20%20%23%20%D0%A3%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%BF%D0%BE%20%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D1%83%203&cumulative=false&curInstr=3&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false
Обход списка
Как и массив, список можно обходить как по индексам, так и напрямую по элементам.
=== "Python"
```python title="list.py"
# Обход списка по индексам
count = 0
for i in range(len(nums)):
count += nums[i]
# Прямой обход элементов списка
for num in nums:
count += num
```
=== "C++"
```cpp title="list.cpp"
/* Обход списка по индексам */
int count = 0;
for (int i = 0; i < nums.size(); i++) {
count += nums[i];
}
/* Прямой обход элементов списка */
count = 0;
for (int num : nums) {
count += num;
}
```
=== "Java"
```java title="list.java"
/* Обход списка по индексам */
int count = 0;
for (int i = 0; i < nums.size(); i++) {
count += nums.get(i);
}
/* Прямой обход элементов списка */
for (int num : nums) {
count += num;
}
```
=== "C#"
```csharp title="list.cs"
/* Обход списка по индексам */
int count = 0;
for (int i = 0; i < nums.Count; i++) {
count += nums[i];
}
/* Прямой обход элементов списка */
count = 0;
foreach (int num in nums) {
count += num;
}
```
=== "Go"
```go title="list_test.go"
/* Обход списка по индексам */
count := 0
for i := 0; i < len(nums); i++ {
count += nums[i]
}
/* Прямой обход элементов списка */
count = 0
for _, num := range nums {
count += num
}
```
=== "Swift"
```swift title="list.swift"
/* Обход списка по индексам */
var count = 0
for i in nums.indices {
count += nums[i]
}
/* Прямой обход элементов списка */
count = 0
for num in nums {
count += num
}
```
=== "JS"
```javascript title="list.js"
/* Обход списка по индексам */
let count = 0;
for (let i = 0; i < nums.length; i++) {
count += nums[i];
}
/* Прямой обход элементов списка */
count = 0;
for (const num of nums) {
count += num;
}
```
=== "TS"
```typescript title="list.ts"
/* Обход списка по индексам */
let count = 0;
for (let i = 0; i < nums.length; i++) {
count += nums[i];
}
/* Прямой обход элементов списка */
count = 0;
for (const num of nums) {
count += num;
}
```
=== "Dart"
```dart title="list.dart"
/* Обход списка по индексам */
int count = 0;
for (var i = 0; i < nums.length; i++) {
count += nums[i];
}
/* Прямой обход элементов списка */
count = 0;
for (var num in nums) {
count += num;
}
```
=== "Rust"
```rust title="list.rs"
// Обход списка по индексам
let mut _count = 0;
for i in 0..nums.len() {
_count += nums[i];
}
// Прямой обход элементов списка
_count = 0;
for num in &nums {
_count += num;
}
```
=== "C"
```c title="list.c"
// В C нет встроенного динамического массива
```
=== "Kotlin"
```kotlin title="list.kt"
/* Обход списка по индексам */
var count = 0
for (i in nums.indices) {
count += nums[i]
}
/* Прямой обход элементов списка */
for (num in nums) {
count += num
}
```
=== "Ruby"
```ruby title="list.rb"
# Обход списка по индексам
count = 0
for i in 0...nums.length
count += nums[i]
end
# Прямой обход элементов списка
count = 0
for num in nums
count += num
end
```
??? pythontutor "Визуализация выполнения"
https://pythontutor.com/render.html#code=%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%D0%98%D0%BD%D0%B8%D1%86%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%0A%20%20%20%20nums%20%3D%20%5B1%2C%203%2C%202%2C%205%2C%204%5D%0A%20%20%20%20%0A%20%20%20%20%23%20%D0%9E%D0%B1%D1%85%D0%BE%D0%B4%D0%B8%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20%D0%BF%D0%BE%20%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D0%B0%D0%BC%0A%20%20%20%20count%20%3D%200%0A%20%20%20%20for%20i%20in%20range%28len%28nums%29%29%3A%0A%20%20%20%20%20%20%20%20count%20%2B%3D%20nums%5Bi%5D%0A%0A%20%20%20%20%23%20%D0%9D%D0%B5%D0%BF%D0%BE%D1%81%D1%80%D0%B5%D0%B4%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%20%D0%BE%D0%B1%D1%85%D0%BE%D0%B4%D0%B8%D1%82%D1%8C%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D1%8B%20%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0%0A%20%20%20%20for%20num%20in%20nums%3A%0A%20%20%20%20%20%20%20%20count%20%2B%3D%20num&cumulative=false&curInstr=3&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false
Конкатенация списков
Создав новый список nums1 , мы можем присоединить его к хвосту исходного списка.
=== "Python"
```python title="list.py"
# Конкатенация двух списков
nums1: list[int] = [6, 8, 7, 10, 9]
nums += nums1 # Присоединить список nums1 к концу nums
```
=== "C++"
```cpp title="list.cpp"
/* Конкатенация двух списков */
vector<int> nums1 = { 6, 8, 7, 10, 9 };
// Присоединить список nums1 к концу nums
nums.insert(nums.end(), nums1.begin(), nums1.end());
```
=== "Java"
```java title="list.java"
/* Конкатенация двух списков */
List<Integer> nums1 = new ArrayList<>(Arrays.asList(new Integer[] { 6, 8, 7, 10, 9 }));
nums.addAll(nums1); // Присоединить список nums1 к концу nums
```
=== "C#"
```csharp title="list.cs"
/* Конкатенация двух списков */
List<int> nums1 = [6, 8, 7, 10, 9];
nums.AddRange(nums1); // Присоединить список nums1 к концу nums
```
=== "Go"
```go title="list_test.go"
/* Конкатенация двух списков */
nums1 := []int{6, 8, 7, 10, 9}
nums = append(nums, nums1...) // Присоединить список nums1 к концу nums
```
=== "Swift"
```swift title="list.swift"
/* Конкатенация двух списков */
let nums1 = [6, 8, 7, 10, 9]
nums.append(contentsOf: nums1) // Присоединить список nums1 к концу nums
```
=== "JS"
```javascript title="list.js"
/* Конкатенация двух списков */
const nums1 = [6, 8, 7, 10, 9];
nums.push(...nums1); // Присоединить список nums1 к концу nums
```
=== "TS"
```typescript title="list.ts"
/* Конкатенация двух списков */
const nums1: number[] = [6, 8, 7, 10, 9];
nums.push(...nums1); // Присоединить список nums1 к концу nums
```
=== "Dart"
```dart title="list.dart"
/* Конкатенация двух списков */
List<int> nums1 = [6, 8, 7, 10, 9];
nums.addAll(nums1); // Присоединить список nums1 к концу nums
```
=== "Rust"
```rust title="list.rs"
/* Конкатенация двух списков */
let nums1: Vec<i32> = vec![6, 8, 7, 10, 9];
nums.extend(nums1);
```
=== "C"
```c title="list.c"
// В C нет встроенного динамического массива
```
=== "Kotlin"
```kotlin title="list.kt"
/* Конкатенация двух списков */
val nums1 = intArrayOf(6, 8, 7, 10, 9).toMutableList()
nums.addAll(nums1) // Присоединить список nums1 к концу nums
```
=== "Ruby"
```ruby title="list.rb"
# Конкатенация двух списков
nums1 = [6, 8, 7, 10, 9]
nums += nums1
```
??? pythontutor "Визуализация выполнения"
https://pythontutor.com/render.html#code=%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%D0%98%D0%BD%D0%B8%D1%86%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%0A%20%20%20%20nums%20%3D%20%5B1%2C%203%2C%202%2C%205%2C%204%5D%0A%20%20%20%20%0A%20%20%20%20%23%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B8%D1%82%D1%8C%20%D0%B4%D0%B2%D0%B0%20%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0%0A%20%20%20%20nums1%20%3D%20%5B6%2C%208%2C%207%2C%2010%2C%209%5D%0A%20%20%20%20nums%20%2B%3D%20nums1%20%20%23%20%D0%9F%D1%80%D0%B8%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B8%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%20nums1%20%D0%BA%20nums&cumulative=false&curInstr=3&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false
Сортировка списка
После сортировки списка мы сможем применять алгоритмы «двоичный поиск» и «два указателя», которые очень часто встречаются в задачах по массивам.
=== "Python"
```python title="list.py"
# Отсортировать список
nums.sort() # После сортировки элементы списка идут по возрастанию
```
=== "C++"
```cpp title="list.cpp"
/* Отсортировать список */
sort(nums.begin(), nums.end()); // После сортировки элементы списка идут по возрастанию
```
=== "Java"
```java title="list.java"
/* Отсортировать список */
Collections.sort(nums); // После сортировки элементы списка идут по возрастанию
```
=== "C#"
```csharp title="list.cs"
/* Отсортировать список */
nums.Sort(); // После сортировки элементы списка идут по возрастанию
```
=== "Go"
```go title="list_test.go"
/* Отсортировать список */
sort.Ints(nums) // После сортировки элементы списка идут по возрастанию
```
=== "Swift"
```swift title="list.swift"
/* Отсортировать список */
nums.sort() // После сортировки элементы списка идут по возрастанию
```
=== "JS"
```javascript title="list.js"
/* Отсортировать список */
nums.sort((a, b) => a - b); // После сортировки элементы списка идут по возрастанию
```
=== "TS"
```typescript title="list.ts"
/* Отсортировать список */
nums.sort((a, b) => a - b); // После сортировки элементы списка идут по возрастанию
```
=== "Dart"
```dart title="list.dart"
/* Отсортировать список */
nums.sort(); // После сортировки элементы списка идут по возрастанию
```
=== "Rust"
```rust title="list.rs"
/* Отсортировать список */
nums.sort(); // После сортировки элементы списка идут по возрастанию
```
=== "C"
```c title="list.c"
// В C нет встроенного динамического массива
```
=== "Kotlin"
```kotlin title="list.kt"
/* Отсортировать список */
nums.sort() // После сортировки элементы списка идут по возрастанию
```
=== "Ruby"
```ruby title="list.rb"
# Отсортировать список
nums = nums.sort { |a, b| a <=> b } # После сортировки элементы списка идут по возрастанию
```
??? pythontutor "Визуализация выполнения"
https://pythontutor.com/render.html#code=%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%D0%98%D0%BD%D0%B8%D1%86%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%0A%20%20%20%20nums%20%3D%20%5B1%2C%203%2C%202%2C%205%2C%204%5D%0A%20%20%20%20%0A%20%20%20%20%23%20%D0%9E%D1%82%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%0A%20%20%20%20nums.sort%28%29%20%20%23%20%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%2C%20%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D1%8B%20%D0%BF%D0%BE%20%D0%B2%D0%BE%D0%B7%D1%80%D0%B0%D1%81%D1%82%D0%B0%D0%BD%D0%B8%D1%8E&cumulative=false&curInstr=3&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false
Реализация списка
Во многих языках программирования списки встроены в стандартную библиотеку, например в Java, C++, Python и других языках. Их реализация довольно сложна, а настройки параметров тщательно продуманы: начальная емкость, коэффициент расширения и так далее. Если это интересно, стоит заглянуть в исходный код.
Чтобы лучше понять принцип работы списка, попробуем реализовать его упрощенную версию, в которой есть три ключевых аспекта проектирования.
- Начальная емкость: выбрать разумную начальную емкость внутреннего массива. В этом примере мы берем 10.
- Учет количества элементов: объявить переменную
size, которая будет хранить текущее число элементов в списке и обновляться в реальном времени при вставке и удалении элементов. С помощью этой переменной можно определять конец списка и понимать, требуется ли расширение. - Механизм расширения: если при вставке элементов емкость списка исчерпана, нужно выполнить расширение. Для этого сначала создается больший массив с учетом коэффициента расширения, а затем все элементы текущего массива по порядку переносятся в новый. В этом примере мы считаем, что каждый раз массив расширяется в 2 раза.
[file]{my_list}-[class]{my_list}-[func]{}