# Список Список (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 nums1; // С начальными значениями vector nums = { 1, 3, 2, 5, 4 }; ``` === "Java" ```java title="list.java" /* Инициализация списка */ // Без начальных значений List nums1 = new ArrayList<>(); // С начальными значениями (обратите внимание, что тип элементов массива должен быть Integer[] — обёрткой int[]) Integer[] numbers = new Integer[] { 1, 3, 2, 5, 4 }; List nums = new ArrayList<>(Arrays.asList(numbers)); ``` === "C#" ```csharp title="list.cs" /* Инициализация списка */ // Без начальных значений List nums1 = []; // С начальными значениями int[] numbers = [1, 3, 2, 5, 4]; List 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 nums1 = []; // С начальными значениями List nums = [1, 3, 2, 5, 4]; ``` === "Rust" ```rust title="list.rs" /* Инициализация списка */ // Без начальных значений let nums1: Vec = Vec::new(); // С начальными значениями let nums: Vec = vec![1, 3, 2, 5, 4]; ``` === "C" ```c title="list.c" // C не предоставляет встроенный динамический массив ``` === "Kotlin" ```kotlin title="list.kt" /* Инициализация списка */ // Без начальных значений var nums1 = listOf() // С начальными значениями 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%E5%88%9D%E5%A7%8B%E5%8C%96%E5%88%97%E8%A1%A8%0A%20%20%20%20%23%20%E6%97%A0%E5%88%9D%E5%A7%8B%E5%80%BC%0A%20%20%20%20nums1%20%3D%20%5B%5D%0A%20%20%20%20%23%20%E6%9C%89%E5%88%9D%E5%A7%8B%E5%80%BC%0A%20%20%20%20nums%20%3D%20%5B1,%203,%202,%205,%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%E5%88%9D%E5%A7%8B%E5%8C%96%E5%88%97%E8%A1%A8%0A%20%20%20%20nums%20%3D%20%5B1,%203,%202,%205,%204%5D%0A%0A%20%20%20%20%23%20%E8%AE%BF%E9%97%AE%E5%85%83%E7%B4%A0%0A%20%20%20%20num%20%3D%20nums%5B1%5D%20%20%23%20%E8%AE%BF%E9%97%AE%E7%B4%A2%E5%BC%95%201%20%E5%A4%84%E7%9A%84%E5%85%83%E7%B4%A0%0A%0A%20%20%20%20%23%20%E6%9B%B4%E6%96%B0%E5%85%83%E7%B4%A0%0A%20%20%20%20nums%5B1%5D%20%3D%200%20%20%20%20%23%20%E5%B0%86%E7%B4%A2%E5%BC%95%201%20%E5%A4%84%E7%9A%84%E5%85%83%E7%B4%A0%E6%9B%B4%E6%96%B0%E4%B8%BA%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%E6%9C%89%E5%88%9D%E5%A7%8B%E5%80%BC%0A%20%20%20%20nums%20%3D%20%5B1,%203,%202,%205,%204%5D%0A%20%20%20%20%0A%20%20%20%20%23%20%E6%B8%85%E7%A9%BA%E5%88%97%E8%A1%A8%0A%20%20%20%20nums.clear%28%29%0A%20%20%20%20%0A%20%20%20%20%23%20%E5%9C%A8%E5%B0%BE%E9%83%A8%E6%B7%BB%E5%8A%A0%E5%85%83%E7%B4%A0%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%E5%9C%A8%E4%B8%AD%E9%97%B4%E6%8F%92%E5%85%A5%E5%85%83%E7%B4%A0%0A%20%20%20%20nums.insert%283,%206%29%20%20%23%20%E5%9C%A8%E7%B4%A2%E5%BC%95%203%20%E5%A4%84%E6%8F%92%E5%85%A5%E6%95%B0%E5%AD%97%206%0A%20%20%20%20%0A%20%20%20%20%23%20%E5%88%A0%E9%99%A4%E5%85%83%E7%B4%A0%0A%20%20%20%20nums.pop%283%29%20%20%20%20%20%20%20%20%23%20%E5%88%A0%E9%99%A4%E7%B4%A2%E5%BC%95%203%20%E5%A4%84%E7%9A%84%E5%85%83%E7%B4%A0&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 =