
- •1.Послідовний, зв’язний, індексний та розсіяний способи збереження таблиці. Пошук в таблицях при різних способах збереження.
- •2. Пошук в таблицях з використанням хеш-функцій.
- •3. Розв’язання колізій в хеш-таблиці
- •4) Метод сортування масивів вставкою та його покращенні методи.
- •5) Сортування методом обміну
- •6) Метод сортування масивів вибором та його покращенні методи
- •8. Стисле зберігання лінійних списків.
- •9. Індексне зберігання лінійних списків.
- •13. Застосування стеків у програмуванні.
- •14. Рекурсія це один із способів обчислювального процесу.
8. Стисле зберігання лінійних списків.
9. Індексне зберігання лінійних списків.
При зберіганні великих об’ємів інформації у формі лінійних списків небажано зберігати елементи з однаковим значенням, тому використають різні методи стискання списків.
Стисле зберігання лінійних списків
Нехай маємо лінійний список A k1 , k2 , ... , kn , і нехай деяка кількість вузлів має однакове значення v. Разом з ним будемо розглядати підсписок A k1 , k 2 ,..., kn , де ki – пара
(i, ki )(до кожного елементу додається порядковий номер вузла). А тепер одержимо із списку
A підсписок A так, щоб до нього не входили елементи
m n . Список A можна зберігати послідовно або зв’язано. Стислим зберіганням списку A є
будь-який метод зберігання A , в якому не записується елементи зі значенням v.
Приклад. Нехай задано список A A, 1, 1, 5, 8, K , 1, C, 9, 1 (i, v) : A wk1 , wk 2 ,..., wk m ,
10.
11.
12. Формирование очереди
Опишем предикат, который позволяет вводить последовательно все элементы в очередь. Пусть vvod (N, L) - предикат, реализующий формирование очереди, N - количество элементов очереди, L - заполняемая очередь.
Предикат, выполняющий формирование очереди, выглядит следующим образом:
vvod (0, []).
vvod (N, L):-
readint (X),
N1=N-1,
vvod (N1, LL),
L = [X|LL].
Первое предложение является граничным условием, т.е. оно говорит, что необходимо прекратить ввод в том случае, когда список пуст и количество элементов очереди равно нулю.
Второе предложение задает ввод головы списка: вводится очередной компонент очереди, количество элементов уменьшается на единицу и происходит рекурсивный вызов предиката, формирующего хвост списка.
Когда выполнится граничное условие, из стека последовательно извлекаются введенные элементы в обратном порядке и добавляются в конец очереди.
Добавление компоненты в конец очереди
Опишем предикат, который позволяет добавлять элементы в конец очереди. Пусть add_in_end (S1, S2, S3) - предикат, реализующий добавление компоненты, S1 - очередь, к которой добавляем, S2 - список, содержащий добавляемый элемент (перед вызовом предиката необходимо добавляемый элемент поместить в список S2), S3 - очередь с добавленным элементом.
Предикат, выполняющий добавление компоненты, выглядит следующим образом:
add_in_end ([], S, S).
add_in_end ([X|S1], S2, [X| S3]):-
add_in_end (S1, S2, S3).
Первое предложение является граничным условием: когда первый список пуст, то второй и третий списки представляют собой один и тот же список.
Если первый список не пуст, то его можно разделить на голову и хвост. Затем рекурсивно вызываем предикат добавления элемента, взяв в качестве первого аргумента хвост списка.
Когда выполнится граничное условие, в третьем списке будет содержаться только один элемент - тот, который нужно было добавить. Затем из стека в обратном порядке последовательно извлекаются элементы, каждый из которых был головой первого списка. При этом только что извлеченный элемент становится первым также в третьей очереди и т. д.
Удаление первой компоненты очереди
Удаление компоненты происходит очень просто: очередь разбивается на голову и хвост, а затем в качестве новой очереди берется только хвост.
Spisok = [_|S1].
Spisok - очередь из которой удаляем, S1 - новая очередь.
Стек — динамическая структура данных, представляющая из себя упорядоченный набор элементов, в которой добавление новых элементов и удаление существующих производится с одного конца, называемого вершиной стека.
По определению, элементы извлекаются из стека в порядке, обратном их добавлению в эту структуру, т.е. действует принцип "последний пришёл — первый ушёл".
Наиболее наглядным примером организации стека служит детская пирамидка, где добавление и снятие колец осуществляется как раз согласно определению стека.
Стек можно организовать на базе любой структуры данных, где возможно хранение нескольких однотипных элементов и где можно реализовать определение стека: линейный массив, типизированный файл, однонаправленный или двунаправленный список. В нашем случае наиболее подходящим для реализации стека является однонаправленный список, причём в качестве вершины стека выберем начало этого списка.
Выделим типовые операции над стеком и его элементами:
добавление элемента в стек;
удаление элемента из стека;
проверка, пуст ли стек;
просмотр элемента в вершине стека без удаления;
очистка стека.
Реализуем эти операции, используя разработанный ранее модуль для однонаправленных списков (см. материал "Динамические структуры данных: списки").
{ Turbo Pascal, файл STACK.PAS } Unit Stack; Interface Uses Spisok; Procedure V_Stack(Var Versh : U; X : BT); Procedure Iz_Stack(Var Versh : U; Var X : BT); Function Pust(Versh : U) : Boolean; Function V_Vershine(Versh : U) : BT; Procedure Ochistka(Var Versh : U); Implementation Procedure V_Stack; Begin V_Nachalo(Versh, X) End; Procedure Iz_Stack; Begin Iz_Nachala(Versh, X) End; Function Pust; Begin Pust := Versh = Nil End; Function V_Vershine; Begin V_Vershine := Versh^.Inf End; Procedure Ochistka; Begin Spisok.Ochistka(Versh) End; Begin End. |
|
/* C++, файл STACK.CPP */ #include "SPIS.CPP" Zveno *V_Stack(Zveno *Versh, BT X) { return V_Nachalo(Versh, X); } Zveno *Iz_Stack(Zveno *Versh) { return Iz_Nachala(Versh); } int SPust(Zveno *Versh) { return !Versh; } BT V_Vershine(Zveno *Versh) { return Versh->Inf; } Zveno *Chistka(Zveno *Versh) { while (!Pust(Versh)) Versh=Iz_Stack(Versh); return Versh; } |
Используя разработанные здесь библиотеки, решим задачу.
Пример. Написать программу, которая вычисляет как целое число значение выражений (без переменных), записанных (без ошибок) в постфиксной форме в текстовом файле. Каждая строка файла содержит ровно одно выражение.
Алгоритм решения. Выражение просматривается слева направо. Если встречается число, то его значение (как целое) заносится в стек, а если встречается знак операции, то из стека извлекаются два последних элемента (это операнды данной операции), над ними выполняется операция и ее результат записывается в стек. В конце в стеке остается только одно число — значение всего выражения.
|
/* C++, файл ST2.CPP */ #include "STACK.CPP" #include < string.h > #include < stdio.h > void main(void) { char S[255]; FILE *T; int I; BT X, Y; Zveno *NS; clrscr(); cout << "Введите имя файла: "; cin >> S; T=fopen(S, "r"); NS = NULL; while (!feof(T)) { fgets(S, 255, T); I = 0; while (I <= strlen(S)-1) { if (S[I]>='0'&&S[I]<='9') { X=0; while(S[I]>='0'&&S[I]<='9') {X=X*10+(S[I]-'0'); I++;} NS=V_Stack(NS, X); } else if (S[I]=='+'||S[I]=='-'||S[I]=='/'||S[I]=='*') { X=V_Vershine(NS); NS=Iz_Stack(NS); Y=V_Vershine(NS); NS=Iz_Stack(NS); switch (S[I]) { case '+' : X += Y; break; case '-' : X = Y - X; break; case '*' : X *= Y; break; case '/' : X = Y / X; break;} NS=V_Stack(NS, X); } I++; } X=V_Vershine(NS); NS=Iz_Stack(NS); |
|