mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-13 07:46:06 +00:00
build
This commit is contained in:
@@ -4,23 +4,23 @@ comments: true
|
||||
|
||||
# 3.2 Базовые типы данных
|
||||
|
||||
Когда мы говорим о данных в компьютере, нам приходят на ум текст, изображения, видео, звук, 3D-модели и многие другие формы. Хотя эти данные организованы по-разному, все они состоят из различных базовых типов данных.
|
||||
Когда речь заходит о данных в компьютере, мы в первую очередь вспоминаем текст, изображения, видео, звук, 3D-модели и многие другие формы представления информации. Хотя способы организации этих данных различаются, все они строятся из базовых типов данных.
|
||||
|
||||
**Базовые типы данных - это типы, с которыми CPU может работать напрямую**; в алгоритмах они используются непосредственно и в основном включают следующее.
|
||||
**Базовые типы данных - это типы, которые процессор может обрабатывать непосредственно**. В алгоритмах они используются напрямую и в основном включают следующее.
|
||||
|
||||
- Целочисленные типы `byte` , `short` , `int` , `long` .
|
||||
- Типы с плавающей точкой `float` , `double` , используемые для представления дробных чисел.
|
||||
- Символьный тип `char` , используемый для представления букв, знаков препинания и даже эмодзи в разных языках.
|
||||
- Логический тип `bool` , используемый для представления суждений "да" и "нет".
|
||||
|
||||
**Базовые типы данных хранятся в компьютере в двоичной форме**. Один двоичный разряд равен $1$ биту. В подавляющем большинстве современных операционных систем $1$ байт (byte) состоит из $8$ битов (bit).
|
||||
**Базовые типы данных хранятся в компьютере в двоичной форме**. Один двоичный разряд равен $1$ биту. В большинстве современных операционных систем $1$ байт (byte) состоит из $8$ битов (bit).
|
||||
|
||||
Диапазон значений базовых типов данных зависит от объема занимаемого ими пространства. Ниже в качестве примера используется Java.
|
||||
|
||||
- Целочисленный тип `byte` занимает $1$ байт = $8$ бит и может представлять $2^{8}$ чисел.
|
||||
- Целочисленный тип `int` занимает $4$ байта = $32$ бита и может представлять $2^{32}$ чисел.
|
||||
|
||||
В таблице 3-1 перечислены объем памяти, диапазон значений и значения по умолчанию для различных базовых типов данных в Java. Заучивать эту таблицу наизусть не нужно; достаточно иметь общее представление и при необходимости обращаться к ней.
|
||||
В таблице 3-1 перечислены объем памяти, диапазон значений и значения по умолчанию для различных базовых типов данных в Java. Эту таблицу не нужно заучивать наизусть; достаточно иметь общее представление и при необходимости обращаться к ней.
|
||||
|
||||
<p align="center"> Таблица 3-1 Объем памяти и диапазоны значений базовых типов данных </p>
|
||||
|
||||
@@ -39,36 +39,36 @@ comments: true
|
||||
|
||||
</div>
|
||||
|
||||
Обрати внимание: приведенная выше таблица относится именно к базовым типам данных Java. В каждом языке программирования определения типов свои, поэтому объем памяти, диапазон значений и значения по умолчанию могут различаться.
|
||||
Обрати внимание: приведенная выше таблица относится именно к базовым типам данных Java. В каждом языке программирования свои определения типов, поэтому объем памяти, диапазон значений и значения по умолчанию могут различаться.
|
||||
|
||||
- В Python целочисленный тип `int` может иметь произвольный размер, ограниченный только доступной памятью; тип `float` использует двойную точность 64 бита; типа `char` нет, а одиночный символ на деле является строкой `str` длины 1.
|
||||
- В C и C++ размер базовых типов данных явно не зафиксирован и зависит от реализации и платформы. таблица 3-1 соответствует модели данных LP64 [data model](https://en.cppreference.com/w/cpp/language/types#Properties), применяемой в 64-битных Unix-системах, включая Linux и macOS.
|
||||
- В Python целочисленный тип `int` может иметь произвольный размер, ограниченный только доступной памятью; тип `float` является 64-битным числом двойной точности; типа `char` нет, а отдельный символ на деле является строкой `str` длины 1.
|
||||
- В C и C++ размер базовых типов данных явно не зафиксирован и зависит от реализации и платформы. таблица 3-1 соответствует модели данных LP64 [data model](https://en.cppreference.com/w/cpp/language/types#Properties), используемой в 64-битных Unix-системах, включая Linux и macOS.
|
||||
- Размер символа `char` в C и C++ составляет 1 байт, а в большинстве других языков программирования зависит от конкретного способа кодирования символов; подробнее это рассматривается в разделе "Кодирование символов".
|
||||
- Хотя для представления логического значения достаточно 1 бита ( $0$ или $1$ ), в памяти оно обычно хранится как 1 байт. Это связано с тем, что современные CPU обычно используют 1 байт как минимальную адресуемую единицу памяти.
|
||||
|
||||
Какова же связь между базовыми типами данных и структурами данных? Мы знаем, что структуры данных - это способы организации и хранения данных в компьютере. Подлежащее в этой фразе - "структура", а не "данные".
|
||||
Какова же связь между базовыми типами данных и структурами данных? Мы знаем, что структура данных - это способ организации и хранения данных в компьютере. Подлежащее в этой фразе - "структура", а не "данные".
|
||||
|
||||
Если мы хотим представить "ряд чисел", то естественно подумаем об использовании массива. Это связано с тем, что линейная структура массива может выразить отношения соседства и порядка между числами, а вот то, что именно хранится внутри - целые `int` , вещественные `float` или символы `char` , - к "структуре данных" отношения не имеет.
|
||||
Если мы хотим представить "ряд чисел", то естественно подумаем об использовании массива. Это связано с тем, что линейная структура массива может выразить отношения соседства и порядка между числами, а то, что именно хранится внутри - целые `int` , вещественные `float` или символы `char` , - к "структуре данных" отношения не имеет.
|
||||
|
||||
Иными словами, **базовые типы данных задают "тип содержимого" данных, а структуры данных задают "способ организации" данных**. Например, в следующем коде мы используем одну и ту же структуру данных (массив) для хранения и представления различных базовых типов данных, включая `int` , `float` , `char` , `bool` и т.д.
|
||||
|
||||
=== "Python"
|
||||
|
||||
```python title=""
|
||||
# Инициализируем массивы с использованием разных базовых типов данных
|
||||
# Инициализируем массивы с использованием различных базовых типов данных
|
||||
numbers: list[int] = [0] * 5
|
||||
decimals: list[float] = [0.0] * 5
|
||||
# В Python символы на деле являются строками длины 1
|
||||
# В Python символы фактически являются строками длины 1
|
||||
characters: list[str] = ['0'] * 5
|
||||
bools: list[bool] = [False] * 5
|
||||
# Списки Python могут свободно хранить разные базовые типы данных и ссылки на объекты
|
||||
# Списки Python могут свободно хранить различные базовые типы данных и ссылки на объекты
|
||||
data = [0, 0.0, 'a', False, ListNode(0)]
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
|
||||
```cpp title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
int numbers[5];
|
||||
float decimals[5];
|
||||
char characters[5];
|
||||
@@ -78,7 +78,7 @@ comments: true
|
||||
=== "Java"
|
||||
|
||||
```java title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
int[] numbers = new int[5];
|
||||
float[] decimals = new float[5];
|
||||
char[] characters = new char[5];
|
||||
@@ -88,7 +88,7 @@ comments: true
|
||||
=== "C#"
|
||||
|
||||
```csharp title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
int[] numbers = new int[5];
|
||||
float[] decimals = new float[5];
|
||||
char[] characters = new char[5];
|
||||
@@ -98,7 +98,7 @@ comments: true
|
||||
=== "Go"
|
||||
|
||||
```go title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
var numbers = [5]int{}
|
||||
var decimals = [5]float64{}
|
||||
var characters = [5]byte{}
|
||||
@@ -108,7 +108,7 @@ comments: true
|
||||
=== "Swift"
|
||||
|
||||
```swift title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
let numbers = Array(repeating: 0, count: 5)
|
||||
let decimals = Array(repeating: 0.0, count: 5)
|
||||
let characters: [Character] = Array(repeating: "a", count: 5)
|
||||
@@ -118,14 +118,14 @@ comments: true
|
||||
=== "JS"
|
||||
|
||||
```javascript title=""
|
||||
// Массивы JavaScript могут свободно хранить разные базовые типы данных и объекты
|
||||
// Массивы JavaScript могут свободно хранить различные базовые типы данных и объекты
|
||||
const array = [0, 0.0, 'a', false];
|
||||
```
|
||||
|
||||
=== "TS"
|
||||
|
||||
```typescript title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
const numbers: number[] = [];
|
||||
const characters: string[] = [];
|
||||
const bools: boolean[] = [];
|
||||
@@ -134,7 +134,7 @@ comments: true
|
||||
=== "Dart"
|
||||
|
||||
```dart title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
List<int> numbers = List.filled(5, 0);
|
||||
List<double> decimals = List.filled(5, 0.0);
|
||||
List<String> characters = List.filled(5, 'a');
|
||||
@@ -144,7 +144,7 @@ comments: true
|
||||
=== "Rust"
|
||||
|
||||
```rust title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
let numbers: Vec<i32> = vec![0; 5];
|
||||
let decimals: Vec<f32> = vec![0.0; 5];
|
||||
let characters: Vec<char> = vec!['0'; 5];
|
||||
@@ -154,7 +154,7 @@ comments: true
|
||||
=== "C"
|
||||
|
||||
```c title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
int numbers[10];
|
||||
float decimals[10];
|
||||
char characters[10];
|
||||
@@ -164,7 +164,7 @@ comments: true
|
||||
=== "Kotlin"
|
||||
|
||||
```kotlin title=""
|
||||
// Инициализируем массивы с использованием разных базовых типов данных
|
||||
// Инициализируем массивы с использованием различных базовых типов данных
|
||||
val numbers = IntArray(5)
|
||||
val decinals = FloatArray(5)
|
||||
val characters = CharArray(5)
|
||||
@@ -174,7 +174,7 @@ comments: true
|
||||
=== "Ruby"
|
||||
|
||||
```ruby title=""
|
||||
# Списки Ruby могут свободно хранить разные базовые типы данных и ссылки на объекты
|
||||
# Списки Ruby могут свободно хранить различные базовые типы данных и ссылки на объекты
|
||||
data = [0, 0.0, 'a', false, ListNode(0)]
|
||||
```
|
||||
|
||||
|
||||
@@ -4,35 +4,35 @@ comments: true
|
||||
|
||||
# 3.4 Кодирование символов *
|
||||
|
||||
В компьютере все данные хранятся в двоичной форме, и символ `char` не является исключением. Чтобы представлять символы, нам нужно определить "набор символов", задающий взаимно-однозначное соответствие между каждым символом и двоичным числом. Имея такой набор, компьютер может преобразовывать двоичные числа в символы простым поиском по таблице.
|
||||
В компьютере все данные хранятся в виде двоичных чисел, и символьный тип данных `char` не является исключением. Для представления символов необходимо задать "таблицу символов", которая устанавливает взаимно-однозначное соответствие между каждым символом и двоичным числом. С помощью этой таблицы компьютер может преобразовывать двоичные числа в символы.
|
||||
|
||||
## 3.4.1 Набор символов ASCII
|
||||
## 3.4.1 Таблица символов ASCII
|
||||
|
||||
<u>Код ASCII</u> - это самый ранний набор символов; его полное название - American Standard Code for Information Interchange (американский стандартный код обмена информацией). Он использует 7 двоичных битов (нижние 7 битов одного байта) для представления одного символа и способен представлять не более 128 различных символов. Как показано на рисунке 3-6, ASCII включает заглавные и строчные английские буквы, цифры 0 ~ 9, некоторые знаки препинания и некоторые управляющие символы (например перевод строки и табуляцию).
|
||||
<u>Код ASCII</u> - это самая ранняя таблица символов; ее полное название - American Standard Code for Information Interchange (американский стандартный код обмена информацией). Для представления символов в ней используются 7 двоичных битов (нижние 7 битов одного байта), что позволяет закодировать до 128 различных символов. Как показано на рисунке 3-6, ASCII включает заглавные и строчные буквы английского алфавита, цифры 0 ~ 9, некоторые знаки препинания, а также некоторые управляющие символы (например перевод строки и табуляцию).
|
||||
|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> Рисунок 3-6 Таблица ASCII </p>
|
||||
|
||||
Однако **код ASCII может представлять только английский язык**. С глобализацией компьютерных технологий появился набор символов <u>EASCII</u>, способный покрывать больше языков. Он расширяет 7-битную основу ASCII до 8 битов и может представлять 256 различных символов.
|
||||
Однако **код ASCII может представлять только английский язык**. С развитием компьютерных технологий появилась таблица символов <u>EASCII</u>, способная охватывать больше языков. Она расширяет 7-битную основу ASCII до 8 битов и может представлять 256 различных символов.
|
||||
|
||||
Во всем мире постепенно появились разные наборы EASCII, подходящие для разных регионов. Первые 128 символов в этих наборах одинаковы и соответствуют ASCII, а последние 128 символов определяются по-разному, чтобы удовлетворять потребностям разных языков.
|
||||
Во всем мире постепенно появились разные таблицы EASCII, подходящие для разных регионов. Первые 128 символов в этих таблицах одинаковы и соответствуют ASCII, а последние 128 символов определяются по-разному, чтобы удовлетворять потребностям разных языков.
|
||||
|
||||
## 3.4.2 Набор символов GBK
|
||||
## 3.4.2 Таблица символов GBK
|
||||
|
||||
Позже люди обнаружили, что **кода EASCII все равно недостаточно для количества символов во многих языках**. Например, китайских иероглифов существует почти сто тысяч, а в повседневном использовании нужны тысячи. В 1980 году Государственное управление стандартов Китая выпустило набор символов <u>GB2312</u>, включающий 6763 иероглифа, что в основном удовлетворило потребности компьютерной обработки китайского текста.
|
||||
Позже люди обнаружили, что **кодов EASCII все равно недостаточно для количества символов во многих языках**. Например, китайских иероглифов существует почти сто тысяч, а в повседневном употреблении нужны тысячи. В 1980 году Государственное управление стандартов Китая выпустило таблицу символов <u>GB2312</u>, включающую 6763 иероглифа, что в основном удовлетворило потребности компьютерной обработки китайского текста.
|
||||
|
||||
Однако GB2312 не умеет работать с некоторыми редкими иероглифами и традиционными формами письма. Набор символов <u>GBK</u> - это расширение GB2312, содержащее в общей сложности 21886 иероглифов. В схеме кодирования GBK символы ASCII представляются одним байтом, а китайские иероглифы - двумя байтами.
|
||||
Однако GB2312 не умеет работать с некоторыми редкими иероглифами и традиционными формами письма. Таблица символов <u>GBK</u> представляет собой расширение GB2312 и в общей сложности содержит 21886 иероглифов. В схеме кодирования GBK символы ASCII представляются одним байтом, а китайские иероглифы - двумя байтами.
|
||||
|
||||
## 3.4.3 Набор символов Unicode
|
||||
## 3.4.3 Таблица символов Unicode
|
||||
|
||||
С бурным развитием компьютерной техники наборы символов и стандарты кодирования начали стремительно множиться, и это породило множество проблем. С одной стороны, такие наборы обычно определяли символы только для конкретных языков и не могли нормально работать в многоязычной среде. С другой стороны, для одного и того же языка существовало несколько стандартов кодирования; если две машины использовали разные стандарты, при обмене информацией возникали кракозябры.
|
||||
С бурным развитием компьютерной техники таблицы символов и стандарты кодирования начали стремительно множиться, и это породило множество проблем. С одной стороны, такие таблицы обычно определяли символы только для конкретных языков и не могли нормально работать в многоязычной среде. С другой стороны, для одного и того же языка существовало несколько стандартов кодирования; если две машины использовали разные стандарты, при обмене информацией возникали искажения текста.
|
||||
|
||||
Исследователи той эпохи задумались: **если создать достаточно полный набор символов, который включит все языки и знаки мира, разве это не решит проблемы межъязыковой среды и искаженного текста**? Под влиянием этой идеи и появился большой и всеобъемлющий набор символов Unicode.
|
||||
Исследователи той эпохи задумались: **если создать достаточно полную таблицу символов, которая включит все языки и знаки мира, разве это не решит проблемы многоязычной среды и искаженного текста**? Под влиянием этой идеи и появилась большая и всеобъемлющая таблица символов Unicode.
|
||||
|
||||
<u>Unicode</u> по-китайски называется "единый код" и теоретически способен вместить более миллиона символов. Его цель - собрать символы со всего мира в единый набор символов, предоставить универсальный стандарт для обработки и отображения текстов на разных языках и уменьшить количество проблем с искажением текста, вызванных различиями стандартов кодирования.
|
||||
<u>Unicode</u> по-китайски называется "единый код" и теоретически способен вместить более миллиона символов. Его цель - собрать символы со всего мира в единую таблицу символов, предоставить универсальный стандарт для обработки и отображения текстов на разных языках и уменьшить количество проблем с искажением текста, вызванных различиями стандартов кодирования.
|
||||
|
||||
С момента публикации в 1991 году Unicode непрерывно расширялся, добавляя новые языки и символы. По состоянию на сентябрь 2022 года Unicode уже включал 149186 символов, в том числе буквы разных языков, знаки, а также эмодзи. В огромном наборе символов Unicode часто используемые символы занимают 2 байта, а некоторые редкие символы - 3 байта и даже 4 байта.
|
||||
С момента публикации в 1991 году Unicode непрерывно расширялся, добавляя новые языки и символы. По состоянию на сентябрь 2022 года Unicode уже включал 149186 символов, в том числе буквы разных языков, знаки, а также эмодзи. В огромной таблице символов Unicode часто используемые символы занимают 2 байта, а некоторые редкие символы - 3 байта и даже 4 байта.
|
||||
|
||||
Unicode - это универсальный набор символов, который по сути просто присваивает каждому символу номер (так называемую "кодовую точку"), **но не определяет, как именно хранить эти кодовые точки в компьютере**. Тут неизбежно возникает вопрос: если в одном тексте одновременно встречаются кодовые точки Unicode разной длины, как система должна разбирать символы? Например, если дан код длиной 2 байта, как понять, является ли это одним 2-байтовым символом или двумя 1-байтовыми?
|
||||
|
||||
|
||||
@@ -4,21 +4,21 @@ comments: true
|
||||
|
||||
# 3.1 Классификация структур данных
|
||||
|
||||
К распространенным структурам данных относятся массивы, связные списки, стеки, очереди, хеш-таблицы, деревья, кучи и графы; их можно классифицировать по двум измерениям: "логическая структура" и "физическая структура".
|
||||
К распространенным структурам данных относятся массивы, связные списки, стеки, очереди, хеш-таблицы, деревья, кучи и графы. Их можно классифицировать по двум измерениям: логической структуре и физической структуре.
|
||||
|
||||
## 3.1.1 Логическая структура: линейная и нелинейная
|
||||
|
||||
**Логическая структура раскрывает логические связи между элементами данных**. В массивах и связных списках данные располагаются в определенном порядке, отражая линейные отношения между элементами; в деревьях данные иерархически располагаются сверху вниз, проявляя производные отношения между "предками" и "потомками"; графы состоят из вершин и ребер и отражают сложные сетевые связи.
|
||||
**Логическая структура раскрывает логические отношения между элементами данных**. В массивах и связных списках данные расположены в определенном порядке, что отражает линейные отношения между элементами. В деревьях данные расположены по уровням сверху вниз, что демонстрирует отношения "предок" и "потомок". Графы состоят из вершин и ребер, отражая сложные сетевые отношения.
|
||||
|
||||
Как показано на рисунке 3-1, логические структуры можно разделить на два больших класса: "линейные" и "нелинейные". Линейные структуры более интуитивны и означают, что данные логически выстроены в линию; нелинейные структуры, напротив, располагаются нелинейно.
|
||||
Как показано на рисунке 3-1, логические структуры делятся на две большие категории: линейные и нелинейные. Линейные структуры более интуитивны, поскольку в них данные расположены линейно и логически связаны. Нелинейные структуры, напротив, представляют собой нелинейное расположение элементов данных.
|
||||
|
||||
- **Линейные структуры данных**: массивы, связные списки, стеки, очереди, хеш-таблицы; между элементами существует отношение "один к одному".
|
||||
- **Линейные структуры данных**: массивы, связные списки, стеки, очереди, хеш-таблицы, в которых элементы связаны отношением "один к одному".
|
||||
- **Нелинейные структуры данных**: деревья, кучи, графы, хеш-таблицы.
|
||||
|
||||
Нелинейные структуры данных можно дополнительно разделить на древовидные и сетевые.
|
||||
|
||||
- **Древовидные структуры**: деревья, кучи, хеш-таблицы; между элементами существует отношение "один ко многим".
|
||||
- **Сетевые структуры**: графы; между элементами существует отношение "многие ко многим".
|
||||
- **Древовидные структуры**: деревья, кучи, хеш-таблицы, в которых элементы связаны отношением "один ко многим".
|
||||
- **Сетевые структуры**: графы, в которых элементы связаны отношением "многие ко многим".
|
||||
|
||||
{ class="animation-figure" }
|
||||
|
||||
@@ -26,9 +26,9 @@ comments: true
|
||||
|
||||
## 3.1.2 Физическая структура: непрерывная и разрозненная
|
||||
|
||||
**Во время выполнения алгоритма обрабатываемые данные в основном хранятся в памяти**. На рисунке 3-2 показана планка памяти компьютера, где каждый черный блок содержит некоторый участок памяти. Мы можем представить память как огромную таблицу Excel, в которой каждая ячейка способна хранить данные определенного размера.
|
||||
**Во время выполнения программы обрабатываемые данные в основном хранятся в памяти**. На рисунке 3-2 показан модуль оперативной памяти компьютера, где каждый черный блок содержит определенный участок памяти. Память можно представить как огромную таблицу Excel, в которой каждая ячейка способна хранить данные определенного размера.
|
||||
|
||||
**Система обращается к данным по адресу памяти соответствующей позиции**. Как показано на рисунке 3-2, компьютер по определенному правилу присваивает каждой ячейке в этой таблице номер, чтобы у каждого участка памяти был уникальный адрес. Имея эти адреса, программа может получать доступ к данным, находящимся в памяти.
|
||||
**Система обращается к данным по адресам памяти соответствующих позиций**. Как показано на рисунке 3-2, компьютер по определенным правилам присваивает каждой ячейке в этой таблице номер, чтобы каждый участок памяти имел уникальный адрес. Благодаря этим адресам программа получает доступ к данным, находящимся в памяти.
|
||||
|
||||
{ class="animation-figure" }
|
||||
|
||||
@@ -38,20 +38,20 @@ comments: true
|
||||
|
||||
Стоит отметить, что сравнение памяти с таблицей Excel - это упрощенная аналогия; реальный механизм работы памяти гораздо сложнее и включает такие понятия, как адресное пространство, управление памятью, кэш-механизмы, виртуальная и физическая память.
|
||||
|
||||
Память - общий ресурс для всех программ. Когда некоторый участок памяти занят одной программой, другие программы обычно не могут использовать его одновременно. **Поэтому при проектировании структур данных и алгоритмов память является важным фактором**. Например, пиковое потребление памяти алгоритмом не должно превышать доступную свободную память системы; если непрерывного крупного блока памяти недостаточно, выбранная структура данных должна уметь храниться в разрозненных областях памяти.
|
||||
Память - общий ресурс для всех программ. Когда некоторый участок памяти занят одной программой, другие программы обычно не могут использовать его одновременно. **Поэтому при проектировании структур данных и алгоритмов память занимает важное место**. Например, пиковое потребление памяти алгоритмом не должно превышать объем доступной свободной памяти системы; если не хватает непрерывных крупных участков памяти, выбранная структура данных должна уметь размещаться в разрозненных областях памяти.
|
||||
|
||||
Как показано на рисунке 3-3, **физическая структура отражает способ хранения данных в памяти компьютера**; ее можно разделить на хранение в непрерывном пространстве (массивы) и хранение в разрозненном пространстве (связные списки). Физическая структура на нижнем уровне определяет способы доступа к данным, их обновления, вставки и удаления; эти два типа физических структур взаимно дополняют друг друга по временной и пространственной эффективности.
|
||||
Как показано на рисунке 3-3, **физическая структура отражает способ хранения данных в памяти компьютера**. Ее можно разделить на хранение в непрерывном пространстве (массивы) и хранение в разрозненном пространстве (связные списки). Физическая структура на низком уровне определяет способы доступа к данным, их обновления, вставки и удаления. Эти два типа физических структур взаимно дополняют друг друга по временной и пространственной эффективности.
|
||||
|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> Рисунок 3-3 Хранение в непрерывном и разрозненном пространстве </p>
|
||||
|
||||
Стоит отметить, что **все структуры данных реализуются на основе массивов, связных списков или их комбинации**. Например, стеки и очереди можно реализовать как с помощью массивов, так и с помощью связных списков; а реализация хеш-таблицы может одновременно содержать массивы и связные списки.
|
||||
Стоит отметить, что **все структуры данных реализуются на основе массивов, связных списков или их комбинации**. Например, стек и очередь можно реализовать как с помощью массивов, так и с помощью связных списков; реализация хеш-таблицы также может одновременно включать массивы и связные списки.
|
||||
|
||||
- **Можно реализовать на основе массивов**: стеки, очереди, хеш-таблицы, деревья, кучи, графы, матрицы, тензоры (массивы размерности $\geq 3$ ) и т.д.
|
||||
- **Можно реализовать на основе связных списков**: стеки, очереди, хеш-таблицы, деревья, кучи, графы и т.д.
|
||||
|
||||
После инициализации длину связного списка все еще можно изменять во время выполнения программы, поэтому его также называют "динамической структурой данных". Длина массива после инициализации неизменна, поэтому его также называют "статической структурой данных". Стоит заметить, что массив может менять длину за счет повторного выделения памяти, тем самым приобретая определенную "динамичность".
|
||||
После инициализации длину связного списка все еще можно изменять во время выполнения программы, поэтому его также называют "динамической структурой данных". Длина массива после инициализации неизменна, поэтому его также называют "статической структурой данных". Стоит отметить, что массив может изменять длину за счет повторного выделения памяти, тем самым приобретая определенную "динамичность".
|
||||
|
||||
!!! tip
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ icon: material/shape-outline
|
||||
|
||||
!!! abstract
|
||||
|
||||
Структуры данных подобны прочному и разнообразному каркасу.
|
||||
Структуры данных подобны прочному и многообразному каркасу.
|
||||
|
||||
Они задают план упорядоченной организации данных, а алгоритмы на этой основе обретают жизнь.
|
||||
Они задают схему упорядоченной организации данных, на основе которой оживают алгоритмы.
|
||||
|
||||
## Содержание главы
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ comments: true
|
||||
|
||||
## 3.3.1 Прямой, обратный и дополнительный коды
|
||||
|
||||
В таблице из предыдущего раздела мы заметили, что все целочисленные типы могут представлять на одно отрицательное число больше, чем положительных. Например, диапазон `byte` равен $[-128, 127]$ . Это явление выглядит не слишком интуитивно, и его внутренняя причина связана с прямым, обратным и дополнительным кодами.
|
||||
В таблице из предыдущего раздела можно заметить, что все целочисленные типы могут представлять на одно отрицательное число больше, чем положительных. Например, диапазон `byte` равен $[-128, 127]$ . Это выглядит не слишком интуитивно, и внутренняя причина связана с прямым, обратным и дополнительным кодами.
|
||||
|
||||
Прежде всего нужно отметить, что **числа хранятся в компьютере в форме "дополнительного кода"**. Прежде чем разбирать причины такого решения, сначала дадим определения всем трем способам представления.
|
||||
Прежде всего нужно отметить, что **числа хранятся в компьютере в виде "дополнительного кода"**. Прежде чем разбирать причины такого решения, сначала дадим определения всем трем способам представления.
|
||||
|
||||
- **Прямой код**: старший бит двоичного представления числа рассматривается как знаковый, где $0$ означает положительное число, а $1$ - отрицательное; остальные биты представляют значение числа.
|
||||
- **Обратный код**: для положительного числа обратный код совпадает с прямым; для отрицательного числа он получается инверсией всех битов прямого кода, кроме знакового бита.
|
||||
@@ -71,7 +71,7 @@ $$
|
||||
|
||||
Остается последний вопрос: диапазон типа `byte` равен $[-128, 127]$ , откуда берется лишнее отрицательное число $-128$ ? Мы замечаем, что у всех целых чисел из интервала $[-127, +127]$ есть соответствующие прямой, обратный и дополнительный коды, а прямой и дополнительный коды можно преобразовывать друг в друга.
|
||||
|
||||
Однако **дополнительный код $1000 \; 0000$ является исключением: у него нет соответствующего прямого кода**. Согласно правилу преобразования, прямой код для этого дополнительного кода должен быть равен $0000 \; 0000$ . Это, очевидно, противоречие, потому что такой прямой код обозначает число $0$ , а его дополнительный код должен совпадать с ним самим. Компьютер просто определяет, что этот особый дополнительный код $1000 \; 0000$ представляет число $-128$ . На самом деле результат вычисления $(-1) + (-127)$ в дополнительном коде как раз и равен $-128$ .
|
||||
Однако **дополнительный код $1000 \; 0000$ является исключением: у него нет соответствующего прямого кода**. Согласно правилу преобразования, прямой код для этого дополнительного кода должен быть равен $0000 \; 0000$ . Это очевидное противоречие, потому что такой прямой код обозначает число $0$ , а его дополнительный код должен совпадать с ним самим. Компьютер просто определяет, что этот особый дополнительный код $1000 \; 0000$ представляет число $-128$ . На самом деле результат вычисления $(-1) + (-127)$ в дополнительном коде как раз и равен $-128$ .
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
@@ -84,11 +84,11 @@ $$
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
Ты, вероятно, уже заметил, что все приведенные выше вычисления были операциями сложения. Это намекает на важный факт: **аппаратные схемы внутри компьютера в основном проектируются на основе операций сложения**. Причина в том, что сложение по сравнению с другими операциями (например умножением, делением и вычитанием) проще реализуется на аппаратном уровне, легче распараллеливается и выполняется быстрее.
|
||||
Ты, вероятно, уже заметил, что все приведенные выше вычисления были операциями сложения. Это указывает на важный факт: **аппаратные схемы внутри компьютера в основном проектируются на основе операций сложения**. Причина в том, что сложение по сравнению с другими операциями (например умножением, делением и вычитанием) проще реализуется на аппаратном уровне, легче распараллеливается и выполняется быстрее.
|
||||
|
||||
Обрати внимание: это не означает, что компьютер умеет только складывать. **Комбинируя сложение с некоторыми базовыми логическими операциями, компьютер может реализовать и другие математические операции**. Например, вычитание $a - b$ можно преобразовать в сложение $a + (-b)$ ; умножение и деление можно свести к многократному сложению или вычитанию.
|
||||
|
||||
Теперь можно подвести итог, почему компьютеры используют дополнительный код: с представлением в дополнительном коде компьютер может использовать одни и те же схемы и операции для сложения положительных и отрицательных чисел, без необходимости проектировать специальные аппаратные схемы для вычитания, и без особой обработки неоднозначности положительного и отрицательного нуля. Это значительно упрощает аппаратную архитектуру и повышает эффективность вычислений.
|
||||
Теперь можно подвести итог, почему компьютеры используют дополнительный код: с представлением в дополнительном коде компьютер может использовать одни и те же схемы и операции для сложения положительных и отрицательных чисел, без необходимости проектировать специальные аппаратные схемы для вычитания и без особой обработки неоднозначности положительного и отрицательного нуля. Это значительно упрощает аппаратную архитектуру и повышает эффективность вычислений.
|
||||
|
||||
Идея дополнительного кода очень изящна; из-за ограничений по объему мы на этом остановимся. Если тебе интересно, стоит изучить эту тему глубже.
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@ comments: true
|
||||
|
||||
### 1. Ключевые выводы
|
||||
|
||||
- Структуры данных можно классифицировать с двух точек зрения: логической структуры и физической структуры. Логическая структура описывает логические связи между элементами данных, а физическая структура описывает способ хранения данных в памяти компьютера.
|
||||
- К распространенным логическим структурам относятся линейные, древовидные и сетевые. Обычно мы делим структуры данных по логической структуре на линейные (массивы, связные списки, стеки, очереди) и нелинейные (деревья, графы, кучи). Реализация хеш-таблицы может одновременно включать линейные и нелинейные структуры данных.
|
||||
- Во время работы программы данные хранятся в памяти компьютера. У каждого участка памяти есть собственный адрес, и программа обращается к данным именно по этим адресам.
|
||||
- Физическая структура в основном делится на хранение в непрерывном пространстве (массивы) и хранение в разрозненном пространстве (связные списки). Все структуры данных реализуются на основе массивов, связных списков или их комбинации.
|
||||
- К базовым типам данных в компьютере относятся целые `byte` , `short` , `int` , `long` , числа с плавающей точкой `float` , `double` , символы `char` и логический тип `bool` . Их диапазон значений определяется объемом занимаемого пространства и способом представления.
|
||||
- Структуры данных можно классифицировать с точки зрения логической и физической структуры. Логическая структура описывает логические отношения между элементами данных, а физическая структура описывает способ хранения данных в памяти компьютера.
|
||||
- К распространенным логическим структурам относятся линейные, древовидные и сетевые. Обычно структуры данных делятся на линейные (массивы, связные списки, стеки, очереди) и нелинейные (деревья, графы, кучи). Реализация хеш-таблицы может включать как линейные, так и нелинейные структуры данных.
|
||||
- При выполнении программы данные хранятся в памяти компьютера. Каждый участок памяти имеет соответствующий адрес, с помощью которого программа получает доступ к данным.
|
||||
- Физическая структура делится на хранение в непрерывном пространстве (массивы) и хранение в разрозненном пространстве (связные списки). Все структуры данных реализуются на основе массивов, связных списков или их комбинации.
|
||||
- Базовые типы данных в компьютере включают целые `byte` , `short` , `int` , `long` , числа с плавающей точкой `float` , `double` , символы `char` и логический тип `bool` . Их диапазон значений зависит от объема занимаемого пространства и способа представления.
|
||||
- Прямой код, обратный код и дополнительный код - это три способа кодирования чисел в компьютере, между которыми можно выполнять взаимные преобразования. В прямом коде старший бит целого числа является знаковым, а остальные биты представляют значение числа.
|
||||
- Целые числа в компьютере хранятся в виде дополнительного кода. В таком представлении компьютер может одинаково обрабатывать сложение положительных и отрицательных чисел, не проектируя специальную аппаратную схему отдельно для вычитания, и при этом не возникает неоднозначности положительного и отрицательного нуля.
|
||||
- Кодирование числа с плавающей точкой состоит из 1 бита знака, 8 битов экспоненты и 23 битов мантиссы. Благодаря наличию экспоненты диапазон значений у чисел с плавающей точкой намного больше, чем у целых, но расплачиваться за это приходится точностью.
|
||||
- Целые числа в компьютере хранятся в виде дополнительного кода. В таком представлении компьютер может одинаково обрабатывать сложение положительных и отрицательных чисел без специальной аппаратной схемы для вычитания, и при этом исчезает неоднозначность положительного и отрицательного нуля.
|
||||
- Кодирование числа с плавающей точкой состоит из 1 бита знака, 8 битов экспоненты и 23 битов мантиссы. Благодаря наличию экспоненты диапазон значений у чисел с плавающей точкой намного больше, чем у целых, но это достигается ценой потери точности.
|
||||
- ASCII - это самый ранний набор английских символов длиной 1 байт, включающий в общей сложности 127 символов. Набор GBK - распространенный китайский набор символов, включающий более двадцати тысяч иероглифов. Unicode стремится предоставить единый полный стандарт набора символов, включающий символы всех языков мира, чтобы решить проблемы искаженного текста, вызванные несовместимыми способами кодирования.
|
||||
- UTF-8 - самый популярный способ кодирования Unicode, обладающий очень хорошей универсальностью. Это кодировка переменной длины, хорошо расширяемая и эффективно использующая память. UTF-16 и UTF-32 относятся к кодировкам фиксированной длины. При кодировании китайского текста UTF-16 занимает меньше места, чем UTF-8. Такие языки программирования, как Java и C#, по умолчанию используют UTF-16.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user