Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие_2_изд_испр.doc
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
2.27 Mб
Скачать

15.6.2. Однонаправленный список

Эта структура позволяет установить связи между составляющими ее элементами и осуществлять переходы от одного элемента к другому в соответствии с некоторым порядком. Элементы представляют собой структуры и могут образовывать массив либо располагаться в "куче". Например, с помощью списка можно выполнить сортировку элементов по значению одного из элементов структуры, не перемещая данные в памяти. Однако при этом требуется дополнительная память для размещения указателя на последующий (или предыдущий) элемент списка. Схематически список изобразить следующим способом.

П ример. Сортировка массива методом вставки в список.

typedef struct zap{ // Строение элемента списка

struct {...} dan; // Хранимая информация

short key; // Ключ сортировки

struct zap *p; // Указатель на следующий элемент списка

} Zap;

/* Процедура сортировки */

Zap* sort(Zap *set, // Указатель на голову списка

short n){ // Число элементов списка

Zap *head, // "Голова" списка

*current, // Текущий элемент

*insert, // Вставляемый элемент

*prev; // Предыдущий элемент

short i, k;

head = set; head->p = NULL;

for(i = 1; i < n; i++){

current = head; insert = set + i ;

/* Поиск места вставки */

for(k = 0; k < i && insert->key >= current->key; k++){

prev = current; current = current->p;

}

/* Вставка */

if(k == 0){ /* 1-й элемент */

head = insert;

}else{

prev->p=insert;

}

if(k < i){ /* Не последний элемент */

insert->p = current;

}else{ /* Последний элемент */

insert->p = NULL;

}

} // End i

return head;

} // End sort

/* Обработка списка в вызывающей процедуре */

tek = sort(s, n);

for(i = 0; i < n; i++){

/* Использование dan((tek->dan).<имя>) */

....................................................

tek = tek->p;

}

15.7. Ссылки и многомерные массивы

Для решения одних и тех же задач можно использовать многомерные массивы и массивы указателей. Для простоты сравнения возьмем двумерный массив и одномерный массив указателей. Пусть имеем следующие определения:

short a[10][10];

short *b[10];

и пусть оба массива используются аналогичным образом, т.е. a[5][5] и b[5][5] допустимые обращения к одному и тому же целому значению. Тогда под массив a будет выделена память размером в 100 целых значений (200 байтов), а под массив b – размером в 10 указателей типа short. Если каждая ссылка массива b указывает на массив из 10 целых, то потребная память для решения составит: 100 целых + 10 указателей на short. Кроме того, необходимо будет динамически выделять память под массив. Однако, не требуется вычислять адрес элемента двумерного массива, а можно обратиться прямо по ссылке.

Второе преимущество: каждый элемент массива ссылок может указывать на на массив, количество элементов которого может быть произвольным, т.е. с его помощью можно реализовать так называемые непрямоугольные массивы, содержащие разное число элементов в младших измерениях. Обычно это используют при работе с массивами строк (string). См. пример "Инициализация массива ссылок".

Пример. Вывод сообщений в окна.

#include <conio.h>

#define Screen BLACK

void message(short nom, // Номер сообщения

short reg){ // Режим: 1-вывод сообщения, 0-очистить окно

static struct mes{ // Описание сообщения

short beg_x, // Начальная позиция окна по x

beg_y, // Начальная позиция окна по y

end_x, // Конечная позиция окна по x

end_y, // Конечная позиция окна по y

regim; // Режим вывода текста: 'r' – с разрядкой, 'p' - плотный

char *text; // Текст сообщения

} def[ ]={ // Инициализация списка сообщений

28, 2, 54, 4, 'r', "ВВОД ДАННЫХ",

19, 12, 61, 14, 'p', "Имя файла входных данных",

.

.

.

19, 12, 61, 14, 'r', "ВВОД ДАННЫХ ЗАКОНЧЕН"

};

struct mes *p; // Указатель на элемент списка

p = &def[nom-1];

if(reg){ // Вывод сообщения в окно

init_window(p->beg_x, p->beg_y, p->end_x, p->end_y,

BLACK, LIGHTGRAY, 1);

out_text(2, 2, 200, p->regim, p->text);

}else{ /* Очистка окна */

clear_window(p->beg_x, p->beg_y, p->end_x, p->end_y, Screen);

}

} /* End message */