Подумайте о типичной иллюстрации связанного списка:
node node node
+------+------+ +------+------+ +------+------+
| data | next | --> | data | next | --> | data | next | --> ...
+------+------+ +------+------+ +------+------+
Каждый элемент в списке - это узел определенного типа, и этот узел содержит next
член, которыйявно указывает на следующий узел в списке.В C это обычно преобразуется в тип struct
, такой как
struct node
{
T data; // for some type T
struct node *next;
};
IOW, каждый struct node
имеет член next
, который указывает на другой объект типа struct node
- не int
,не void
и т. д., поэтому мы не объявляем next
как int *
, или void *
, или как угодно.
Однако ...
В зависимости от того, как вы реализуете свой список, вы можете использовать что-то отличное от struct node *
в качестве элемента next
.Обычно, когда мы реализуем список, мы динамически распределяем каждый узел, используя malloc
, как нам это нужно.Однако, если вы знаете, что ваш список никогда не станет больше, чем какое-либо известное, достаточно маленькое значение, вы можете выделить array из struct node
в качестве своей "кучи", и ваш член next
может бытьзначение индекса массива:
struct node
{
T data;
int next; // holds the *index* of the next element
} heap[SOME_SIZE];
Затем вы инициализируете свою «кучу», чтобы каждый элемент явно указывал на следующий в массиве:
for ( int i = 0; i < SOME_SIZE-1; i++ )
{
heap[i].next = i+1;
}
heap[SOME_SIZE-1].next = -1; // use -1 to indicate "null"
Теперь все, что вам нужно, этопара целых чисел, одно для указания на первый доступный элемент в массиве, а другое для указания на начало вашего списка:
int avail = 0; // initially points to the first element in the "heap"
int head = -1; // initially "null"
«Выделение» узла затем просто становится вопросом поискаПервый свободный узел в «куче»:
int node = avail; // get the index of the next available node in the "heap";
avail = heap[avail].next; // update avail to point to the next available node
«Освобождение» узла означает просто добавление этого индекса обратно в начало списка avail
:
heap[node].next = avail; // set this node point to the first free element
avail = node; // make this node the first free element;
Помните,node
и avail
не являются объектами узлов, они просто являются индексами в массиве объектов узлов.
Обычно мы так не делаем, потому что next
концептуально проще указывать непосредственно на другой объект struct node
, а не быть индексом в массиве.Мы все еще можем использовать массив фиксированного размера в качестве нашей «кучи», мы просто используем адрес каждого элемента вместо его индекса.