- •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
9.2.4. Внутренняя сортировка
Различают внутреннюю и внешнюю сортировку. Под внутренней сортировкой понимают сортировку в условиях, когда вся таблица помещается в оперативную память. Внешняя сортировка – это сортировка данных на внешнем носителе, причем доступный объем оперативной памяти недостаточен для того, что считать сразу всю таблицу в оперативную память.
9.2.4.1. Сортировка подсчетом
Этот простой метод основан на том, что j-й ключ в сортированной последовательности превышает ровно j-1 ключ. В первой фазе алгоритм подсчитывает для каждого ключа число ключей, которые меньше его. Значение счетчика для ключа и есть тот номер позиции в сортированной таблице, который он должен занять.
Void CountSort(int n, int t[]){
// t – сортируемый массив целых чисел длиной n
int i,j;
int *c=new int[n]; // массив счетчиков
// обнулим счетчики
for(i=0; i<n; i++) c[i]=0;
// фаза подсчета
for(i=0; i<n; i+){
for(j=0; j<i; j++){
if(t[i]>t[j]){
c[i]++;
} else {
c[j]++;
}
}
}
// фаза расстановки
for(i=0; i<n; i++){
while(i!=c[i]){ // до тех пор, пока t[i] не займет
// окончательного положения
swap(t[i],t[c[i]]); // обмен местами эл-тов таблицы
swap(c[i],c[c[i]]); // обмен местами счетчиков
}
}
}
Ключ ti в исходной последовательности сравнивается с i предшествующими ключами и, следовательно, общее число сравнений равно
то есть пропорционально N2.
9.2.4.2. Сортировка простым выбором
Просматривая исходную последовательность ключей t, начиная с t0, находим среди них наименьший и меняем местами с t0, затем повторяем процесс начиная с t1, находим наименьший и меняем местами с t1, и так далее до конца таблицы. Ниже представлен текст функции, выполняющей сортировку простым выбором.
Void SimpleChoice(int n, int t[]){
int i,j,k;
for(i=0; i<n; i++){
k=i;
// к моменту завершения цикла по j, k будет индексом
// наименьшего ключа на отрезке i…N-1
for(j=i+1;j<n;j++){
if(t[j]<t[k]){
k=j;
}
}
swap(t[i], t[k]);
}
}
В этом случае время также пропорционально N2, так как при поиске наименьшего ключа на отрезке i…N-1, потребуется выполнить N-i-1 сравнений. Суммируя по i, получим величину, пропорциональную N2.
9.2.4.3. Квадратичный выбор
Б
ыстродействие
сортировки выбором можно улучшить, если
сделать процесс выбора многоступенчатым.
Пусть размер таблицы N=16.
Разобьем таблицу на 4 группы по 4 элемента
в каждой, как на рис 32
Рис 32. Квадратичный выбор
Определим
наибольший элемент в каждой группе и
поместим его в отдельную группу "лидеров".
Наибольший среди них и есть наибольший
в таблице. Поместим его в область вывода.
Последующие элементы отыскиваются так:
среди элементов группы, из которой
происходил выбранный на предыдущем
шаге элемент, выбираем наибольший и
помещаем вместо выбывшего в группу
лидеров. Затем очередной элемент
выводится из группы лидеров. Если N
– точный квадрат, то можно разделить
таблицу на
групп по
элементов. Любой выбор, кроме первого
потребует не более
сравнений внутри группы ранее выбранного
элемента плюс
сравнений внутри группы лидеров. Таким
образом, время такой сортировки
пропорционально
,
что гораздо лучше N2.
Эту идею можно обобщить, получив метод
кубического выбора, выбора четвертой
степени и т.д.
Кубический
выбор состоит в том, чтобы разделить
таблицу на
больших групп, каждая из которых состоит
из
малых групп по
элементов. Время такой сортировки
пропорционально
.
Если развить эту идею до ее полного
завершения, когда в группе на каждом
уровне содержится только два элемента,
то придем к методу, основанному на выборе
из бинарного дерева.
