Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
математическая логика и теория алгоритмов.doc
Скачиваний:
118
Добавлен:
10.05.2014
Размер:
2.32 Mб
Скачать
        1. Статическая просматриваемая таблица-вектор

Такая таблица представляется одномерным массивом элементов, размер которого заранее известен:

const int M = 100; /* максимальный размер таблицы */

struct Item{

int key;

Type info;

}; /* структура элемента таблицы */

Item table[M];

Реализация алгоритма поиска элемента не вызывает затруднений и может быть такой:

int search(int k)

{

int i;

for(i = 0; i < M && table[i].key != k; i++)

;

return (i < M ? i : -1);

}

        1. Динамическая просматриваемая таблица-вектор

Динамические таблицы разрешают выполнение операций включения новых элементов и удаления существующих. Это накладывает дополнительные требования на отображение таблицы.

Прежде всего, поскольку разрешена операция включения, нужно иметь информацию о наличии в таблице свободных позиций; кроме того, при наличии в таблице нескольких свободных позиций необходимо решить, в какую именно будет включаться новый элемент.

Наличие в таблице свободных элементов может повлиять на реализацию алгоритма поиска.

Для фиксации в таблице свободных и занятых элементов полезно реорганизовать элемент таблицы, включив в него дополнительное (служебное) поле 1/0 – поле занятости (рис. II–36): значение 1 в этом поле означает, что элемент занят, значение 0 – что элемент свободен.

1/0

ключ

информация

Рис. II–36

В исходном состоянии таблица пуста, и все элементы таблицы помечены как свободные. При включении нового элемента в таблицу нужно найти подходящий свободный элемент. Критерием для выбора может служить длина доступа L(т.е. количество элементов таблицы, которое необходимо просмотреть, прежде чем будет найдена свободная позиция; в какой-то степени длина доступа аналогична длине поиска). Можно обеспечитьL= 1, если все операции включения выполнять в конец таблицы и использовать специальную переменную (например,int n;), которая определяет первый свободный элемент в конце таблицы. В исходном состоянии n=0; каждая операция включения нового элемента увеличивает значениеn.

При удалении элемента в найденном элементе таблицы достаточно установить в 0 поле занятости; можно не модифицировать значения других полей таблицы. Не следует при удалении элемента из середины таблицы перемещать информацию из конца таблицы в освободившуюся позицию, так как это может привести к увеличению времени выполнения операции. Отсюда, при удалении элемента из таблицы переменная nне меняет свое значение.

Таким образом, если для таблицы выполняются в произвольном порядке операции включения и удаления, в некоторый момент времени состояние таблицы может иметь вид, приведенный на рис. II–37. Следовательно, при выполнении поиска элемента в таблице следует учитывать, свободен очередной элемент или занят.

1/0

ключ

информация

1

25

...

0

13

...

1

47

...

0

18

...

0

33

...

Рис. II–37

Для динамических таблиц, использующих указанные выше операции включения и удаления, с течением времени может возникнуть ситуация, когда в конце таблицы свободных позиций нет (т.е. n = M), в то время как в середине таблицы есть много элементов, помеченных как свободные. В таких ситуациях, прежде чем можно будет выполнить очередную операцию включения нового элемента в таблицу, следует ее реорганизовать, собрав все свободные элементы в конце таблицы и изменив текущий размер таблицы (n). Такая операция получила название "сборки мусора". В зависимости от того, насколько часто прикладная программа выполняет операции включения/удаления, может оказаться удобнее выполнить операцию "сборки мусора", зато потом все операции включения не будут требовать дополнительные накладные расходы. С другой стороны, можно включать новый элемент в первую найденную свободную позицию, исключив тем самым операцию "сборки мусора", но увеличив время выполнения операции включения.

Тексты функций для выполнения операций включения, удаления, поиска элементов в таблице и "сборки мусора" приводятся ниже и в файле tab1vec.cpp.В приведенных примерах используются две вспомогательные функции:delInfo()– удаление информации иdupl()– создание копии данных. Конкретная реализация этих функций зависит от типа информации, включаемой в таблицу (типType), и определяется разработчиком соответствующего приложения.

const int M = 20; /* Максимальный размер таблицы */

struct Item{

int busy; /* поле занятости */

int key; /* ключ */

Type info; /* информация */

};

Item table[M]; /* Объявление таблицы как внешней (вне функций) приводит к тому, что все элементы инициализируются нулем; поэтому можно не устанавливать явно значения 0 в полеbusyвсех элементов при создании таблицы */

int n = 0;

/* поиск элемента в таблице */

int search(int k)

{

int i;

for(i = 0; i < n; i++)

if(table[i].busy && table[i].key == k)

return i; /* элемент найден – он занят и имеет искомый ключ */

return -1; /* элемент не найден */

}

/* удаление элемента*/

int del(int k)

{

int l;

if((l = search(k)) < 0)

return -1; /* указанного элемента в таблице нет */

table[l].busy = 0; /* "удаление" элемента */

delInfo(table[I].info);

return 0;

}

/* "сборка мусора" */

int garbage()

{

int i, cur = n;

n = 0;

for(i = 0; i < cur; i++)

if(table[i].busy){ /* элемент занят */

if(i != n) /* элемент должен быть перемещен */

table[n] = table[i]; /* перемещение элемента */

n++;

}

return n == M ? -1 : 0; /* в таблице нет свободного места */

}

/* включение нового элемента в таблицу */

int insert(int k, Type in)

{

if(search(k) >= 0)

return -1; /* в таблице есть элемент с заданным ключом */

if(n == M) /* в конце таблицы нет свободной позиции */

if(garbage() < 0) /* "сборка мусора" */

return -2; /* в таблице нет свободной позиции */

/* включение нового элемента в таблицу */

table[n].busy = 1;

table[n].key = k;

table[n++].info = dupl(in);

return 0;

}