Уровни описания структур данных: от математики до байтов
Для чего введены уровни описания структур данных
Чтобы отделить суть данных от деталей реализации. Сначала можно продумать логику программы на абстрактном уровне, не привязываясь ни к машине, ни к языку, - а уже потом спуститься вниз и выбрать самый эффективный способ хранения. Каждую структуру в этом курсе - стек, очередь, список, дерево - мы будем разбирать именно по этим трем этажам.
Три уровня
- Функциональная спецификация - внешнее, формальное математическое определение типа: множество возможных значений, допустимые операции и отношения. Ни слова о языке программирования или машине. Пример: вектор - упорядоченный набор элементов с операциями доступа по индексу.
- Логическое описание - отображение спецификации на средства
выбранного языка. Есть в языке готовый подходящий тип (
int, массив) - используем его; нет - конструируем свой из базовых (structв C). - Физическое представление - конкретное размещение данных
в оперативной памяти. Два основных вида:
- Сплошное (непрерывное) - данные лежат друг за другом одним блоком. Адрес элемента вычисляется по формуле, доступ - O(1). Подходит, когда размер известен заранее (массивы).
- Цепное (связное) - данные разбиты на части, разбросанные по памяти и связанные указателями. Размер меняется легко, но доступ медленнее (списки, деревья).
Эта развилка уже встречалась в уроке про статические и динамические объекты: сплошное представление тяготеет к статике, цепное строится на ссылках и динамической памяти.
Пример: "Сотрудник" двумя способами
Логическое описание - конструируем тип из базовых через struct;
физическое представление - на выбор, сплошное или цепное:
Структура "Сотрудник": код целиком
#include <stdlib.h>
/* Логическое описание: новый тип из базовых */
typedef struct {
int id;
double salary;
} Employee;
int main(void) {
/* Физическое СПЛОШНОЕ представление:
100 сотрудников лежат в памяти подряд */
Employee array[100];
array[0].id = 1;
array[0].salary = 50000.0;
/* Физическое ЦЕПНОЕ представление:
узлы разбросаны по куче и связаны указателями */
typedef struct Node {
Employee data;
struct Node* next; /* ссылка на следующий узел */
} Node;
Node* head = (Node*)malloc(sizeof(Node));
head->data.id = 2;
head->data.salary = 60000.0;
head->next = NULL;
free(head);
return 0;
}
Коротко: главное
- Структура данных описывается на трех уровнях абстракции.
- Функциональная спецификация: множество значений + операции; не зависит от языка и машины.
- Логическое описание: реализация средствами языка (готовый тип или свой struct).
- Физическое представление: сплошное (подряд, доступ O(1), размер фиксирован) или цепное (указатели, гибкий размер, доступ медленнее).
- Разделение уровней позволяет думать о логике отдельно от деталей хранения.
Проверьте себя
Вы решаете, хранить элементы одним непрерывным блоком или связать разбросанные узлы указателями. На каком уровне описания вы находитесь?