Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Итоговый конспект Тельнов.docx
Скачиваний:
10
Добавлен:
07.04.2023
Размер:
7.75 Mб
Скачать

12.Язык Си: программный стек. Пример работы стека.

Программный стек - часть памяти компьютера, которая используется

для размещения автоматических переменных и обмена данными между функциями.

Рассмотрим следующий фрагмент кода:

void main(void) { // определение функции main

long a; // три переменные

char *b, c; // с автоматическим классом памяти

…………...

f(a, b, c); // вызов некоторой функции f

……………

} // конец определения функции main

void f(long x, char* y, char z) { // определение функции f

char d, *pd; // две переменные

…………… // с автоматическим классом памяти

} // конец определения функции f

Рисунок, поясняющий работу программного стека:

13. Линейные списки. Операции с линейными списками.

Множество узлов, объединенных с помощью ссылок (направленный граф)

Каждый узел устроен так:

Списки

Линейный односвязный

Двунаправленный (двусвязный)

Циклический список(кольца)

Линейные списки служат для представления в компьютере абстрактных структур данных(последовательностей, множеств, графов и др.).

Описание узла линейного списка:

typedef struct node {

OBJECT* ptr;

node* next;

} L, *Lp;

Lp first = NULL;

Пустой список

Lp first = NULL;

Список из одного элемента

продвижение вперед на 1 элемент

if (p) p = p -> next;

или

if (p != NULL) p = p-> next;

Операции с линейными списками

Итеративный обход списка в прямом направлении

Lp p = first;

while (p != NULL){

R(p -> ptr); // обработка объекта в узле

p = p -> next;

}

Рекурсивный обход списка в прямом направлении

void w1(Lp p) {

if (p != NULL) R(p -> ptr); // обработка объекта в узле

w1(p -> next);

}

Рекурсивный обход списка в обратном направлении

void w2(Lp p){

if ( p != NULL) w2(p->next);

R(p -> ptr); // обработка объекта в узле

}

Вставка узла в начало списка

Lp q = new L; // здесь q - указатель на новый узел списка

q -> next = first; // бывший первый узел станет вторым

first = q; // новый узел становится первым узлом списка

Удаление из начала списка

if(first != NULL) first = first -> next;

Вставка узла в произвольное место списка(список не должен быть пуст)

Lp q = new L; // q - указатель на новый узел списка

q -> next = p -> next; // здесь p - указатель на произвольный узел списка

p -> next = q; // узел q вставляется после узла p

Описание узла двусвязного списка:

typedef struct node {

OBJECT* ptr;

node* next;

node* back;

} L, *Lp;

Поиск в списке.

Пусть задан некий <образец> для поиск.

Lp p = first;

while ((p != NULL) && (*p -> ptr != <образец>)) p = p -> next;

if (p == NULL) {<искомого элемента в списке нет>}

else {<p есть указатель на нужный узел списка>}

Удаление узла из произвольного места списка:

// пусть p - указатель на произвольный узел списка

if (p != NULL && p -> next != NULL)

p -> next = p -> next -> next; // удаляется узел, следующий за p

14 Hash-таблицы

Hash-таблицы с цепочками. Функция хеширования h(<Object>) служит для вычисления индекса в массиве указателей. Объект <Object> встраивается в линейный список. Адрес начала списка – в соответствующем элемента массива.

Hash-таблица с открытой адресацией. Адрес объекта <Object> - в соответствующем элементе массива указателей. Возможны коллизии, если получается одинаковый результат хеширования для двух и более различных объектов. Для разрешения коллизий (т.е. для поиска свободного элемента в массиве указателей) применяются специальные алгоритмы