- •1. Типы структур данных
- •2. Стек
- •Void stack::Push(int NewElement){
- •Int stack::Pop(){
- •If(!Empty){
- •2.1. Применения стека
- •2.1.1. Программный стек
- •Void main(void){
- •2.1.2. Реализация рекурсии
- •2.1.2.1. Обход шахматной доски ходом коня
- •Int I,j; // координаты клетки
- •Int move; // номер хода, которым покидаем клетку
- •Int I,j; // текущие координаты клетки
- •Int V; // указатель стека
- •Int BegMove,k,i2,j2;
- •If(Move(n,I,j,k,&i2,&j2) && !Board[i2][j2]){
- •If(Good){
- •2.1.2.1. Вычисление определенного интеграла
- •Interval Stack[maxstack];
- •2.1.3. Польская инверсная запись (полиз)
- •If(isalpha(z)) return 'б'; // буква – операнд
- •Int Poliz(char *in,char *out){
- •2.1.4. Вычисление выражения, представленного в полиз
- •Контрольные вопросы
- •3. Очередь
- •Контрольные вопросы
- •4. Массивы
- •4.1. Размещение прямоугольных массивов в последовательной памяти
- •4.2. Метод Айлиффа
- •Контрольные вопросы
- •5. Списочные структуры
- •5.1. Односвязный линейный список
- •5.1.1. Представление односвязного списка
- •5.1.2. Операции над односвязным списком
- •!!!!!!5.1.3. Голова списка
- •5.1.4 Циклический список
- •5.1.5. Пример. Сложение многочленов
- •Int px,py,pz; // степени X,y,z
- •Int PowerCmp(node *p, node *q){
- •Void PoliAdd(node *p, node *q){
- •5.2. Двусвязный линейный список
- •Void DeleteUzel(uzel *p){
- •5.3. Ортогональные списки
- •Int Row,Col; // строка и столбец элемента
- •5.4. Списки общего вида
- •5.4.1. Пример. Топологическая сортировка.
- •Int count; // счетчик числа элементов, предшествующих
- •Void TopSort(pair *p, int n_pair, file *result){
- •Void AddToTail(mains *head, mains *V){
- •5.5. Стек свободного пространства
- •Void DeleteNode(node *p, node *s){
- •5.6. Обслуживание свободного пространства
- •5.6.1. Счетчик ссылок
- •5.6.2. Сбор мусора
- •Контрольные вопросы
- •6. Множества
- •Int nElem; // число элементов в множестве
- •Int Elem[maxsize]; // элементы множества
- •Int Element; // номер элемента множества
- •Void Delete(node *p); // удаление узла вслед за p
- •Void setinlist::Delete(node *p){
- •Контрольные вопросы
- •7. Деревья
- •7.1. Бинарные деревья
- •7.2. Обход бинарного дерева
- •Void DirectByPass(node *Root){
- •Void InverseByPass(node *Root){
- •Int Tag; // может принимать значения operation или number
- •7.3. Прошитые деревья
- •Void InverseBypass(node *Root){
- •7.4. Другие представления бинарных деревьев
- •7.5. Представление деревьев общего вида
- •Int nSon; // действительное число сыновей узла
- •7.5.1. Представление деревьев общего вида бинарными деревьями
- •Контрольные вопросы
- •8. Конечный автомат
- •Int State; // текущее состояние
- •Int Class;
- •If(!Found){
- •Контрольные вопросы
- •9. Таблицы
- •9.1. Последовательные таблицы
- •Контрольные вопросы
- •9.2. Сортированные таблицы
- •9.2.1. Алгоритмы поиска в сортированной таблице
- •9.2.1.1. Бинарный поиск (дихотомия)
- •Int BinSearch(int Key, int n, int t[]){
- •Void *bsearch(const void *key, const void *base, size_t nelem, size_t width, int (*fcmp)(const void *a, const void *b ));
- •9.2.2. Вставка и удаление в сортированной таблице
- •9.2.3. Оценка трудоемкости сортировки !!!!!
- •9.2.4. Внутренняя сортировка
- •9.2.4.1. Сортировка подсчетом
- •Void CountSort(int n, int t[]){
- •9.2.4.2. Сортировка простым выбором
- •Void SimpleChoice(int n, int t[]){
- •9.2.4.3. Квадратичный выбор
- •9.2.4.4. Выбор из дерева
- •9.2.4.5. Сортировка простыми вставками
- •Void InsertSort(int n, int t[]){
- •9.2.4.6. Сортировка методом "пузырька"
- •Void BubbleSort(int n, int t[]){
- •9.2.4.7. Сортировка слиянием
- •Void Merge(int n, int *t, int m, int *V, int *r){
- •9.2.4.8. Сортировка фон Неймана
- •Void Join(int a[], int b[], int *left, int *right,
- •Int *kl, int *kr, int Step){
- •9.2.4.9. Сортировка Хоара (1962 г.) !!!!!
- •Int Partition(int m, int n, int t[]){
- •Void Hoar(int m, int n, int t[]){
- •Void qsort(void *base, size_t nelem, size_t width,
- •Int (*fcmp)(const void *, const void *));
- •9.2.4.10. Двоичная поразрядная сортировка
- •Int BitPart(unsigned int Left, unsigned int Right,
- •Void BitSort(unsigned int Left, unsigned int Right,
- •Void BinarySort(int n,unsigned Tab[], unsigned int keylen){
- •9.2.4.11. Цифровая поразрядная сортировка
- •Void DigitalSort(byte *t, int n, int KeyLen){
- •Int *Count;
- •Int *Pos; // позиции расстановки
- •9.2.1. Внешняя сортировка
- •9.2.1.1. Многопутевое слияние и выбор с замещением
- •9.2.1.2. Многофазное слияние
- •9.2.1.3. Фибоначчиево слияние
- •9.2.1.4. Каскадное слияние
- •9.2.1.5. Сортировка в одном файле
- •Контрольные вопросы
- •9.3. Древовидные таблицы
- •Void *Record; // указатель на запись таблицы
- •Int WhatSon; // каким сыном устанавливать новую запись –
- •Int CmpKeys; // результат сравнения ключей
- •Int Info;
- •Int Rank; // для доступа по индексу
- •9.3.1. Оценка трудоемкости поиска в случайном дереве
- •9.3.2. Оптимальные деревья
- •Int Info;
- •9.3.3. Сбалансированные деревья
- •9.3.4.1. Поддержание балансировки
- •9.3.5. Представление линейных списков деревьями
- •Int Info;
- •Int Rank;
- •Контрольные вопросы
- •9.4. Таблицы с прямым доступом
- •9.5. Рассеянные таблицы (Hash)
- •9.5.1. Анализ трудоемкости операций над рассеянной таблицей
- •Контрольные вопросы
- •Литература
- •454091, Г.Челябинск, ул.Свободы, 155/1
5.4.1. Пример. Топологическая сортировка.
Топологической называют сортировку на множестве элементов в случае, когда на множестве элементов задано отношение частичного порядка. Порядок является частичным, если отношение предшествования задано не для всех пар элементов. Множество целых чисел является полностью упорядоченным, так как для любой пары целых чисел a,b определено отношение ‘>’ (больше) или ‘<’ (меньше).
В качестве примера ситуации, когда порядок является частичным, рассмотрим производство следующих работ:
сделать болт
сделать гайку
навернуть гайку на болт
Ясно, что работы 1 и 2 должны предшествовать работе 3. Запишем этот факт как 12 (читается: 1 предшествует 2) и 23. Работы 1 и 2 не связаны между собой отношением предшествования.
Другим примером, в котором имеется частичный порядок, является учебный план подготовки специалистов в ВУЗе. Курс "Основы алгоритмизации и языки программирования" должен предшествовать курсу "Структуры и алгоритмы обработки данных", но ни тот, ни другой никак не связаны с курсом "История государственного управления в России".
Третий пример: пусть требуется написать библиотеку подпрограмм, в которой некоторые из подпрограмм вызывают другие подпрограммы из той же библиотеки. Очевидно, что приступать к отладке вызывающих подпрограмм следует после завершения отладки вызываемых.
Топологическая сортировка на основе имеющегося отношения частичного порядка строит линейную последовательность элементов сортируемого множества, в которой для любой пары Xi, Xj не может быть выполнено условие Xi Xj при i>j. Иными словами, для пары a b, a не может появиться в выходной последовательности позже b.
Исходными данными для работы алгоритма является массив пар элементов first, second, таких, что first second. Одна такая пара представляется структурой:
struct PAIR{
char *first;
char *second;
};
Для реализации алгоритма используются списочная структура, содержащая узлы двух типов: узлы основного списка (MAINS) и узлы подсписков (POD). Основной список двусвязный, с головой, циклический. Подсписок – односвязный, без головы и нециклический.
struct MAINS{ // cтруктура узла основного списка
Int count; // счетчик числа элементов, предшествующих
//данному
char name[40]; // имя элемента
MAINS *llink; // связи двусвязного списка
MAINS *rlink;
struct POD *pod; // указатель на подсписок
};
struct POD { // структура узла подсписка
POD *next;// следующий узел подсписка
MAINS *m; // указатель на узел основного списка
};
Алгоритм имеет три фазы:
Первая
фаза –
первоначальное построение списочной
структуры. Проходим массив пар, и для
каждого элемента множества, который
ещё не включен в список, создаем узел и
помещаем его в хвост основного списка.
Для каждой пары first,
second
в подсписок узла first
помещаем
узел, в поле m
которого помещаем ссылку на узел
основного списка second.
Счетчик count
узла second
увеличиваем на единицу. После завершения
первой фазы узел каждого элемента
содержит число элементов, предшествующих
данному. На рис.19 изображено состояние
основного списка после завершения
первой фазы для массива пар п
редшествования
Рис 19. Топологическая сортировка. 1 фаза.
Вторая фаза – создание списка ведущих элементов. Список ведущих имеет такую же структуру, что и основной список. Проходя основной список слева направо, узлы, имеющие поле счетчика, равное нулю, переносим в список ведущих элементов. Этим элементам ничто не предшествует, и они первыми будут выведены в выходную последовательность.
Третья фаза – построение выходной последовательности. Проходим список ведущих и его элементы помещаем в выходную последовательность и удаляем из списка ведущих. Проходя подсписок выводимого в результат элемента, уменьшаем на единицу поле счетчика того элемента основного списка, на который ссылается поле m подсписка. Действительно, после вывода элемента списка ведущих в результирующую последовательность, он уже не предшествует оставшимся в основном списке элементам. Если поле счетчика окажется равным нулю, переносим его в хвост списка ведущих.
Если отношение предшествования было задано корректно, то все элементы будут выведены и основной список опустеет. Если же основной список по завершении третьей фазы не пуст, то это говорит о противоречивом задании частичного порядка. Например, частичный порядок
a b; b c; c a
противоречив.
Ниже приведен текст функции, реализующей топологическую сортировку:
