
сиаод / Reformating_Saod
.pdf1. Алгоритмы.
Алгоритм – это заданная определенным образом последовательность действий, приводящая за конечное число шагов к достижению поставленной цели (к решению поставленной задачи).
действие ≡ инструкция ≡ оператор.
Действия (инструкции, операторы) выполняются некоторым исполнителем. Для нас исполнитель ≡ процессор.
Исполнитель должен уметь выполнять некоторый набор действий и понимать, в какой последовательности эти действия нужно выполнять по заданному алгоритму. При этом должны быть соблюдены следующие два условия:
1)действия должны быть понятны исполнителю; 2)разные исполнители должны одинаково понимать одни и те же действия.
Один и тот же алгоритм может быть записан несколькими способами. В практике программирования распространены:
•словесная запись на естественном языке;
•схемы алгоритмов, блок-диаграммы;
•решающие таблицы;
•алгоритмические языки (формальные языки).
Первый, второй и третий способы предназначены для человека, последний – для исполнителя-машины. Такая запись называется программой.
Существует три основных типов алгоритмов:
1.Последовательный алгоритм – такой, в котором действия выполняются в том порядке, в каком они написаны (в естественном порядке).
2.Условный алгоритм–конструкция ЕСЛИ – ТО – ИНАЧЕ. Запись в общем виде: ЕСЛИ условие ТО последовательность действий 1 ИНАЧЕ последовательность действий 2.
3.Циклическая конструкция. Называется она конструкцией WHILE - DO. Соответствующий алгоритм называется циклическим алгоритмом. Он задает многократное выполнение одних и тех же действий. Запись в общем виде: ПОКА условие ВЫПОЛНИТЬ последовательность действий. Последовательность может выполняться 0,1,... ,∞ раз.Этих трех конструкций (трех типов алгоритмов) достаточно для написания алгоритмов любой сложности
3. Классификация структур.
1. По наличию явно заданных связей между элементами данных:
а) несвязные структуры: векторы, массивы, строки, стеки, очереди; б) связные структуры: связные списки
2.По признаку изменчивости структуры (т.е. изменения числа элементов и связей между ними:
а) статические; б) полустатические; в) динамические.
3.По характеру упорядоченности элементов структуры:
а) линейно-упорядоченные (линейные); б) нелинейные.
4. По характеру взаимного расположения элементов в памяти:
а) с последовательным распределением: векторы, массивы, строки, стеки, очереди; б) с произвольным связанным распределением: односвязные списки, двусвязные списки,
циклически связанные списки, ассоциативные списки.Для нелинейных структур – многосвязные списки, древовидные структуры и графовые структуры общего вида.
4. Перечислимые типы.
Перечисление позволяет описывать новые типы данных, значения которых определяет сам программист. Описание перечислимого типа состоит из списка его элементов, заключенных в (). Каждый из элементов представляет собой уникальный идентификатор.
Type season = (spring,summer,fall,winter);
Ид-ры всех элементов перечислимого типа идентифицируются как константы. Упорядочение const в типе осуществляется в последовательности, в которой упорядочены идентификаторы. 1-ая const имеет номер 0 и определяет позицию «0» в списке. Достоинства: обеспечивает контроль за значением переменных (переменным нельзя присваивать предварительные неперечислимые значения).
Недостоинства: нельзя выводить переменную на экран.
Функции: Ord(Summer)=1 - позиция эл-та,Pred(Winter)=2 – позиция э-та-1,Suec(Spring)=1
– позиция э-та+1
5. Интервальные типы.
При описании указывается min и max значения диапазона допустимый для этих значений. Min и max зн-я разделяются точкой: 0..500, 1..1, -127..128, ”A”..”Z”. Переменные интервального типа имеют все св-ва базового типа(и только), однако её зн-я принадлежат ук-му диапазону. Интервальный тип необязательно описывать в разделе type, его можно указывать непосредственно при объявлении переменной.
Type date = ‘1’..’31’; или var date: 1..31; Левая граница диапазона не должна превышать его правую границу. В Паскале есть 2-е функции для этого типа: high(x) – возвращает макс зн- е интерв-ого типа, которому принадлежит x; low(x) – возвращает мин зн-е интервального типа.{$R+}-вкл. команды которые отслеживают чтоб знач. не выход. за диапазон.
6. Множество как структура данных
Множество является еще одной фундаментальной оперативной статической структурой. Множества – произвольный набор однотипных объектов, понимаемый как единое целое. Соответствующий тип описывается:
TYPE T = SET OF T0, где T0 - базовый тип элементов множества. Базовым типом может быть только перечислимый или интервальный. Значениями переменной x типа T являются множества элементов типа T0. Они составляют множества всех подмножеств T0. Такое множество называется множеством-степенью, т.е. можно сказать, что тип T – это множество-степень своего базового типа T0. Порядок следования элементов для множества роли не играет. Для хранения данных типа set требуется столько бит, из
скольки значений состоит множество. Для Паскаля количество элементов множества не должно превышать 256.
TYPE CHIS = SET OF 0..30;
TYPE DSET = SET OF DAY;
TYPE ZNSET = SET OF '*'..'/';
Соответствующие переменные описываются как VAR CH : CHIS; D : DSET; ZN : ZNSET; Операции над множествами:
Присваивание: CH:=[12]; D:=[SU, FR];
Объединение: A = [1, 2, 3, 4, 5] B = [2, 5, 6, 7, 8] A + B = [1, 2, 3, 4, 5, 6, 7, 8]
Пересечение: A * B = [2, 5]
Разность: A - B = [1, 3, 4]
Отношение: |
|
|
Паскаль Матем. запись |
значение |
|
A=B |
(A = B) |
true false |
A<>B |
(A ≠ B) |
|
A<=B |
(A ≤ B) |
|
A=>B |
(A ≥ B) |
|
х IN A |
(x A) |
|
Ранг операций: 1)пересечение,2)+,- , 3)=,<>,<=,=>,in
7. Стек. Абстрактный тип данных стек. Реализация стека с помощью массива.
Стек - линейный последовательный список, в котором доступ, включение и исключение элементов выполняется только с одного конца: k = n , т.е. доступен только последний элемент (вершина стека). Аббревиатура – "последний пришел – первым вышел". Вершина стека – это позиция, в которой находится последний поступивший элемент. Операции над элементами стека (включение и исключение) производятся с его вершины, причем в каждый момент для исключения доступен только верхний (последний) элемент . Вершина стека адресуется с помощью специального указателя. Стек считается пустым, если указатель смещен вниз на длину одной ячейки относительно низа стека. Возможные операции: 1)создать стек 2)поместить эл-т в стек 3)забрать эл-т 4)получить знач. верхнего элемента 5)проверить на пустоту 6)удалить. При работе со стеком необходимо учитывать, что если в процессе заполнения указатель выйдет за верхнюю границу, то происходит переполнение стека и новый элемент ввести уже невозможно. Для этого перед реализацией стека необходимо указывать его границы.
Представление стека – массивом, содержащим не меньшее число элементов, чем может быть заслано в стек. Для очередного элемента достаточно иметь один указатель t на этот элемент. Когда стек пуст, t = 0. Описание:
const ms = 100;
var stack : array[1..ms] of tt; t : integer;
Поместить новый элемент(Push(y)):
1)указатель перемещается "вверх" на длину слота или ячейки; 2)затем по значению указателя в стек помещается информация о новом элементе.
Чтобы добавить элемент в стек, нужно увеличить значение указателя на единицу, а затем занести в элемент массива с индексом t информацию из y:
t := t + 1; stack[t] := y;
Забрать элемент(Pop(y)):
1)прочитывается информация об исключаемом элементе по значению указателя; 2)затем указатель смещается "вниз" на один слот.
y := stack[t]; t := t - 1;
Получить знач. верхнего э-та(Top(y)): y:=stack[t]
Проверка на пустоту IsEmpty: if t = 0 then IsEmpty:=true
else IsEmpty:=false
При этом следует помнить, что t не может быть меньше 1 и больше MS. Следовательно, нужны проверки на пустоту и переполнение стека.
Извлекаем:
if t = 0 then write(ошибка)
else begin y := stack[t]; t := t - 1 end;
Добавляем:
if t = ms then write(ошибка)
else begin t := t + 1; stack[t] := y end;
Затраты постоянные О(1)-делается все за одну итерацию Недостаткипроверка на переполнение.
8.Стек. Абстрактный тип данных стек. Реализация стека с помощью указателей.
Стек - линейный последовательный список, в котором доступ, включение и исключение элементов выполняется только с одного конца: k = n , т.е. доступен только последний элемент (вершина стека). Аббревиатура – "последний пришел – первым вышел". Вершина стека – это позиция, в которой находится последний поступивший элемент. Операции над элементами стека (включение и исключение) производятся с его вершины, причем в каждый момент для исключения доступен только верхний (последний) элемент . Вершина стека адресуется с помощью специального указателя. Стек считается пустым, если указатель смещен вниз на длину одной ячейки относительно низа стека. Возможные операции: 1)создать стек 2)поместить эл-т в стек 3)забрать эл-т 4)получить знач. верхнего элемента 5)проверить на пустоту 6)удалить. Используется динамическое распределение памяти, т.е. выделять память для элемента списковой структуры в тот момент, когда этот элемент появляется во время выполнения программы, а не во время её компиляции. В этом случае транслятор выделяет фиксированный объем памяти для хранения адресов динамически размещаемых элементов, а не самих элементов. Эти адреса называются указателями или ссылками.
Доступ к динамическим переменным осуществляется с помощью указателей (ссылок), которые становятся определенными после создания динамического элемента программы. Стек состоит из нескольких динамических областей памяти, причем указатель вышерасположенного элемента указывает на предыдущий элемент. Указатель стека должен указывать на верхний элемент стека. Для организации и ведения стека должны быть предусмотрены два указателя:
TYPE pStack = ^StackNode StackNode = record
info : integer
next : pStack- ук-ль на предыдущий end
var Stack : pStackуказатель на вершину Инициализация:
Stack:=nil
Поместить первый э-нт в стек:
1.выделить память под элемент; new(p);
2.занести в неё нужную информацию; p^.info := 5;
3.p^.next:=nil;
4.указателю stack присвоить значение указателя; stack := p;
Добавить эл-т в стек:
1.выделение памяти под новый э-нт; new(p); 2.заполнить информ. часть; p^.info:=7; 3.указатель на вешину стека; p^.next := stack; 4.stack := p
Удалить эл-т из стека:
1.считываем информацию эл-та; val := stack^.info 2.указываем рабочий указатель на вершину стека; p := stack 3.перемещаем стек к следующ. эл-ту; stack := p^.next 4.освождаем память; dispose(p)
Формирование стека с самого начала. Стек из N элементов: stack := nil;
while n > 0 do begin new(k); read(val); p^.info := CH; p^.next := TOP; TOP := p; n := n -1 end;
В динамических структурах снимается проблема переполнения стека. Выч. затраты постоянны O(1)-за одну итерацию:
1)обращение к диспетчеру динамической памяти(new(p)) 2)занесение инф-ии в выдел. объем памяти 3)занесение значения в указатели
9.Очередь. Абстрактный тип данных очередь. Реализация очереди с помощью массива.
Очередь – линейный последовательный список, в котором все включения производятся в конце списка (в хвосте очереди), а исключения – в начале (в голове очереди). Аббревиатура – "первым пришел – первым вышел". Для индикации хвоста и головы очереди организуются два указателя. f - указатель головного элемента, r - адресует первый свободный слот, следующий за хвостовым.
Для абстрактного типа данных имеются 6 операций:
1)создать пустую очередь, 2)поместить эл-т, 3)забрать эл-т, 4)получить знач. э-та стоящ. в начале очереди, 5)проверка на пустоту, 6)удалить очередь.
Основные операции над очередью – включение и исключение элемента.
Реализация очереди на массиве: нужны два указателя: f - для начала и r - для конца очер. Описание:
const mq = 100;
type TypeElem:=<тип эл-ов очереди> var queue : array[1..mq] of TypeElem;
f, r : integer;
Поместить эл-т в очередь EnQueue(Queue, y):
1)новый элемент заносится в слот, адресуемый указателем r;
2)после чего указатель необходимо передвинуть к следующему пустому слоту (вправо). queue[r] := y;
r := r + 1; при этом r может только расти.
Исключение из очереди DeQueue(Queue, y):
1)извлекается элемент, адресуемый указателем f;
2)после чего f перемещается к следующему заполненному слоту. y := queue[f];
f := f + 1; Текущая длина очереди равна r - f .
Получить значение первого эл-та FrontQueue(Queue, y):
1)y:=Queue[f];
Проверка на пустоту IsEmpty(Queue)
1)if f=r then IsEmpty := true else IsEmpty := folse
Недостаток: в процессе включения новых элементов в очередь, организованную таким образом рано или поздно наступит переполнение. Этого можно избежать, если после Amax переводить r на слот с адресом A1. Такая очередь называется кольцевой. В такой очереди возможно любое из соотношений f < r, f = r, f > r. Текущая длина очереди равна r - f . В кольцевой очереди после queue[mq] логически следует queue[1] .Но при этом если r=f , то очередь может быть либо заполнена до конца, либо пуста. Чтобы избежать неоднозначности, последний элемент не заполняют и это обстоятельство считается переполнением.
Добавление в кольцевую очередь EnQueue(Queue,y):
1)Queue[r]:=y;
2)if r = mq then r := 1 else r := r + 1;
Исключение элемента из кольцевой очереди DeQueue(Queue,y):
1)y:=Queue[r];
2)if f = mq then f := 1 else f := f + 1;
Определение числа элементов в очереди: if r < f then k := mq + r – f else k := r – f.
Выч. затраты: const- O(1)
10. Очередь. Абстрактный тип данных очередь. Реализация очереди с помощью указателей.
Очередь – линейный последовательный список, в котором все включения производятся в конце списка (в хвосте очереди), а исключения – в начале (в голове очереди). Аббревиатура – "первым пришел – первым вышел". Для индикации хвоста и головы очереди организуются два указателя. f - указатель головного элемента очереди, r - адресует первый свободный слот, следующий за хвостовым.
При добавлении в очередь:
1)новый элемент заносится в слот, адресуемый указателем r;
2)после чего указатель необходимо передвинуть к следующему пустому слоту (вправо). При исключении из очереди:
1)извлекается элемент, адресуемый указателем f;
2)после чего f перемещается к следующему заполненному слоту. Для абстрактного типа данных имеются 6 операций:
1)создать пустую очередь, 2)поместить эл-т, 3)забрать эл-т, 4)получить знач. э-та стоящ. в начале очереди, 5)проверка на пустоту, 6)удалить очередь.
Естественно, что в процессе включения новых элементов в очередь, организованную таким образом рано или поздно наступит переполнение. Этого можно избежать, если после Amax переводить r на слот с адресом A1. Организованная таким образом очередь называется кольцевой. В такой очереди возможно любое из соотношений f < r, f = r, f > r. Основные операции над очередью – включение и исключение элемента.
Характерная особенность списковых структур данных (связных списков, стеков, очередей и т.д.) – это способность изменять число элементов. Используется динамическое распределение памяти, т.е. выделять память для элемента списковой структуры в тот момент, когда этот элемент появляется во время выполнения программы, а не во время её компиляции. В этом случае транслятор выделяет фиксированный объем памяти для хранения адресов динамически размещаемых элементов, а не самих элементов. Эти адреса называются указателями или ссылками. Элементы, выделяемые динамически, не имеют

имени, к ним нельзя обращаться стандартным путем. Доступ к динамическим переменным осуществляется с помощью указателей (ссылок), которые становятся определенными после создания динамического элемента программы. Нужны два указателя на начало и конец очереди, BeginQначало, EndQконец. Указатель последнего элемента очереди должен быть равен NIL. Таким образом, для работы с очередью нужны три переменных типа "указатель".
Тогда описание:
TYPE TP = ^SP;
SP = RECORD
INF : CHAR; LINK : TP END;
VAR F, K, R : TP; CH : CHAR;
Занесение 1-го э-та в очередь(создание очереди):
BeginQ:=nil
EndQ:=nil
1)выделяем память; new(p)
2)заполняем информ. поле; p^.info:=3
3)добавленному эл-ту делаем указатель на nil; p^.next:=nil 4)beginq:=p; endq:=p
Добавить элемент в очередь:
1)выделяем память; new(p)
2)заполняем информ. поле; p^.info:=7
3)добавленному эл-ту делаем указатель на nil; p^.next:=nil 4)endQ^.next:=p
5)endQ:=p
Удалить эл-т из очереди:
1)считываем информационное поле; val:=BeginQ^.info
2)устанавливаем рабочий указатель на начало очереди; p:=BeginQ
3)перемещаем указатель BeginQ на начало очереди; BeginQ:=p^.next
4)освобождаем память; dispos(p)
При работе с динамической очередью снимается проблема переполнения очереди. Проверка на пустую очередь осуществляется сравнением F с NIL.
11.Дек как структуры данных.
Дек – линейный последовательный список с двумя концами, в котором как включение, так и исключение элементов может осуществляться с любого из двух концов списка Дек - более общая структура среди трех. Является сочетанием очереди и стека. Структуру дека имитирует, например, схема железнодорожного разъезда:
Операции: создать, поместить в начало/конец, забрать первый/последний эл-т, получить значение первого/последнего эл-та, проверить на пустоту, удалить.
Частными случаями являются:
1)дек с ограниченным входом;
2)дек с ограниченным выходом
В первом случае закрыт верхний участок пути, во втором случае – нижний. Логическая и физическая структуры дека аналогичны логической и физической структурам очереди. Но вместо хвоста и головы для дека принято говорить о левом и
правом конце. Основные операции над деком – включение и исключение элементов. Они являются обобщением и развитием аналогичных операций над очередью.

12.Односвязный список. Основные операции. Реализация списка с помощью массива. (Включение и исключение элементов, просмотр списка и поиск нужного элемента).
Связный список – структура, элементами которой служат записи с одним и тем же форматом, связанные друг с другом логически с помощью указателей, хранящихся в самих элементах. В односвязном списке каждый элемент состоит из двух полей: содержательного и поля указателя. Содержательное поле хранит данные (в общем случае это запись). Поле указателя хранит адрес следующего элемента списка. По указателю получаем доступ к следующему элементу, от него к очередному и т.д. Поле указателя последнего элемента должно содержать специальный признак нулевого или пустого указателя, свидетельствующего о конце списка. Должен быть указатель начала списка. Он является частью его логической структуры. В данном случае указатель будет иметь значение индекса следующего элемента в массиве записей.
Операции со связанными списками:
1)создать пустой список, 2)уничтожить список, 3)проверка на пустоту, 4)включить эл-нт, 5)исключить элемент, 6)найти элемент в списке. Простейшая модель – массив записей (структур), в котором есть дополнительное поле – указатель на следующую запись(Записьсоставной тип данных). В данном случае указатель будет иметь значение индекса следующего элемента в массиве записей.
const ms = 100; type Sp = record
info : T0; { T0 - базовый тип; } link : integer
end;
var spisok : array[1..ms] of sp; BeginL : integer;
k, i, j : integer;
Установлена логическая связь между элементами списка в порядке 3–5–6–9–2. Признак последнего элемента – значение указателя равно 0. Индекс начала списка
находится в переменной nach или BeginL. Элементы массива 1, 4, 7, 8, 10, 11, 12 в список не включены.
Основные операции:
Переход к следующему элементу списка:
i - индекс текущего элемента, индекс следующего элемента:
J := SPISOK[I].LINK;
C := SPISOK[I].INF; - значение I-го элемента
Связь с предыдущим элементом потеряна совершенно.
Просмотр всего списка с начала: i := beginL;
while i <> 0 do begin c := spisok[i].info;
{ обработка c }
i := spisok[i].link;
end; Просматривать список можно с начала или с промежуточного элемента, но только в сторону конца списка.
Включение элемента в список:
Элемент массива с индексом j надо включить в список после элемента i. Например, j = 11, i = 6. Тогда:
spisok[j].info := c; занести информацию
spisok[j].link := spisok[i].link; занести указатель spisok[i].link := j; сменить указатель предыдущего элемента
Включение и исключение производится после элемента с заданным номером.
Поиск нужного элемента
I := NACH;
WHILE (C <> '...') AND (I <> 0) DO BEGIN C := SPISOK[I].INF;
I := SPISOK[I].LINK; END;
IF C <> '...' THEN { элемент не найден }
Исключение элемента из списка
Исключить из списка элемент, стоящий после элемента с индексом i. Например, i = 3 (следовательно, нужно исключить элемент с j = 5). Для этого нужно указатель элемента j перенести в указатель элемента i.
J := SPISOK[I].LINK; нашли индекс удаляемого элемента
SPISOK[I].LINK := SPISOK[J].LINK; перенесли указатель
C := SPISOK[J].INF; сохранили информацию
Обратим внимание на цикличность и зеркальность операций включения и исключения элементов из списка.
Освобожденный элемент является "мусором". Выход из положения – все свободные элементы массива связать в еще один список – список свободного пространства. Теперь перед операцией добавления в основной список нужно взять один элемент из списка свободного пространства (обычно первый – признак стека).
После операции удаления из основного списка надо добавить операцию включения освобожденного элемента в список свободного пространства (в начало этого списка – стек).
Список свободного пространства используется как стек. Теперь две последние операции выполняются следующим образом.
Включение в список после i-го элемента
J := FREE; индекс свободного элемента
FREE := SPISOK[J].LINK; индекс нового свободного элемента
SPISOK[J].INF := C; занести информацию
SPISOK[J].LINK := SPISOK[I].LINK; занести указатель
SPISOK[I].LINK := J; сменить указатель предыдущего элемента
Удаление из списка после i-го элемента
J := SPISOK[I].LINK; нашли индекс удаляемого элемента C := SPISOK[J].INF; переписали информацию
SPISOK[I].LINK := SPISOK[J].LINK; переписали указатель теперь добавим перед FREE:
SPISOK[J].LINK := FREE; занесли в указатель индекс свободного элемента
FREE := J; сменили номер свободного элемента
Операции тоже цикличны и выполняются в обратном порядке (зеркальны).
Однако существуют определенные ограничения, накладываемые на выполнение этих операций:
1)нужна проверка на переполнение при включении элемента;
2)нужна проверка на исключение элемента после последнего в списке;
13.Односвязный список. Основные операции. Реализация списка с помощью указателей.
Связный список – структура, элементами которой служат записи с одним и тем же форматом, связанные друг с другом логически с помощью указателей, хранящихся в самих элементах. В односвязном списке каждый элемент состоит из двух полей:
содержательного и поля указателя. Содержательное поле хранит данные (в общем случае это запись). Поле указателя хранит адрес следующего элемента списка. По указателю получаем доступ к следующему элементу, от него к очередному и т.д. Поле указателя последнего элемента должно содержать специальный признак нулевого или пустого указателя, свидетельствующего о конце списка. Кроме того, должен быть указатель начала списка. Он является частью его логической структуры. В данном случае указатель будет иметь значение индекса следующего элемента в массиве записей.
Основные операции со связанными списками:
1)переход к соседним элементам; 2)включение элемента; 3)исключение элемента, Простейшая модель – массив записей (структур), в котором есть дополнительное поле – указатель на следующую запись(Записьсоставной тип данных).
Характерная особенность списковых структур данных (связных списков, стеков, очередей и т.д.) – это способность изменять число элементов.
Используется так называемое динамическое распределение памяти, т.е. выделять память для элемента списковой структуры в тот момент, когда этот элемент появляется во время выполнения программы, а не во время её компиляции. В этом случае транслятор выделяет фиксированный объем памяти для хранения адресов динамически размещаемых элементов, а не самих элементов. Эти адреса называются указателями или ссылками.
В современных яп можно явно использовать указатели. Это дает возможность строить более разнообразные динамические структуры данных. В них память отводится только на время существования элемента и освобождается, когда элемент уничтожается. В дальнейшем эта область памяти может использоваться повторно.
Динамические списки легко ведутся, если в качестве ссылок использовать переменные типа "указатель". В этом случае снимается проблема переполнения, т.к. теоретически память ЭВМ можно считать неограниченной.
Опишем односвязный список. TYPE TP = ^SP;
SP = RECORD
INF : CHAR; { INF : T0 } LINK : TP
END;
VAR NACH, I, J, K : TP C : CHAR;
Обратите внимание: переменной типа SP нет! Основные операции со списками.
Переход к следующему элементу.
Пусть I – указатель на текущий элемент списка. Тогда
J := I^.LINK; указывает на следующий элемент списка.
Поиск нужного элемента с начала списка.
Пусть хотим найти элемент со значением 'A'. I := NACH;
WHILE (C <> 'A') AND (I <> NIL) DO BEGIN C := I^.INF;
I := I^.LINK END;
IF C <> 'A' THEN { нет элемента }