
К9-12В. Вопросы и ответы к ГОСам 2013 / Программирование на языке высокого уровня / 06. Упорядоченная таблица - вектор. Определение, основные операции и особенности их реализации
.docx06. Упорядоченная таблица - вектор. Определение, основные операции и особенности их реализации.
Упорядоченные таблицы
В упорядоченных таблицах элементы располагаются в некотором определенном порядке, задаваемым относительным расположением ключей. Примем порядок расположения ключей по возрастанию, так как в наших таблицах ключи представлены целыми числами (такое предположение не снижает общности решения поставленной задачи).
Как правило, упорядоченные таблицы делают статическими, поскольку для динамических упорядоченных таблиц при включении и удалении элементов приходится выполнять реорганизацию таблиц сразу при выполнении операций, что увеличивает время выполнения этих операций. Тем не менее, возможны и динамические таблицы.
Обычно упорядоченные таблицы отображаются вектором, и это позволяет существенно ускорить поиск по сравнению с перемешанными таблицами.
Упорядоченная таблица-вектор
В упорядоченной таблице-векторе элементы располагаются по возрастанию значений ключей, что позволяет делать некоторые предположения о месте размещения искомого элемента таблицы. Если, например, нам требуется найти элемент с ключом k*, и нам известно, что в i-ом элементе таблицы ключ ki>k*, это означает, что искомый элемент может находиться среди первых (i-1)-го элементов таблицы. Если же ki<k*, то искомый элемент может находиться среди последних элементов таблиц, начиная с (i+1)-го элемента. На этом основан алгоритм двоичного поиска.
В соответствии с алгоритмом двоичного поиска определяется индекс записи, находящейся в середине таблицы. Сравнение искомого ключа и ключа найденного элемента позволяет определить (если они не равны), в какой половине таблицы – верхней или нижней – может находиться искомый элемент. В соответствии с принятым решением ненужная половина таблицы, включая и найденную запись, исключается из рассмотрения, в результате чего количество элементов, которые нужно проанализировать, сокращается вдвое. Таким образом, через некоторое количество попыток запись с требуемым ключом, если она имеется в таблице, будет найдена. Если же требуемая запись отсутствует в таблице, через некоторое количество попыток все элементы таблицы будут исключены из рассмотрения.
Схема алгоритма приведена на рис. II-40.
Текст функции приводится ниже и в файле Programs/tab2vec.cpp.
const int M = 20; /* максимальный размер таблицы */
struct Item{
int key;
Type info;
};
Item bintable[M];
/* Поиск элемента в таблице; результат – индекс найденного элемента или -1 */
int binsearch(intnkey)
{
int i = 0, k = M - 1;
while(i<= k){
int j = (i + k) / 2;
if(bintable[j].key == nkey)
return j; /* элементнайден */
if(bintable[j].key <nkey)
i = j + 1;
else
k = j - 1;
}
return -1; /* элемента в таблице нет */
}
Пусть упорядоченная таблица состоит из M = 8 элементов (рис. II-41).
Рассмотрим схему двоичного поиска для разных значений ключей.
(a)Искомый ключ k*1 = 60
|
этап |
1 |
2 |
3 |
начало таблицы: |
i = |
0 |
4 |
6 |
конец таблицы: |
k = |
7 |
7 |
7 |
середина таблицы: |
j = |
3 |
5 |
6 |
элемент таблицы: |
kj = |
23 |
49 |
60 |
возможное место расположения искомого элемента |
нижняя половина таблицы |
нижняя половина таблицы |
искомый элемент найден |
(b)Искомый ключ k*2 = 17
|
этап |
1 |
2 |
3 |
4 |
4 |
начало таблицы: |
i = |
0 |
0 |
1 |
2 |
3 |
конец таблицы: |
k = |
7 |
2 |
2 |
2 |
2 |
середина таблицы: |
j = |
3 |
1 |
1 |
2 |
? |
элемент таблицы: |
kj= |
23 |
8 |
8 |
15 |
15 |
возможное место расположения искомого элемента |
верхняя половина таблицы |
нижняя половина таблицы |
нижняя половина таблицы |
все просмотрено |
искомый элемент не найден |
В случае таблицы, включающей M элементов, максимальная длина поиска
T = log2M.
Средняя длина поиска не будет много меньше максимальной.
Динамическая упорядоченная таблица-вектор
Для динамических упорядоченных таблиц включение новых или удаление существующих элементов не должно вызывать нарушение структуры таблицы, поэтому при выполнении указанных операций требуется реорганизация таблицы.
Удаление элемента из упорядоченной таблицы реализуется достаточно просто: в результате поиска элемента получаем его индекс в таблице, после чего нижняя половина таблицы перемещается на одну позицию вверх:
const int M = 20; /* максимальный размер таблицы */
struct Item{
int key;
Type info;
};
Item bintable[M];
int n; /* текущий размер таблицы */
int binsearch(int k); /* Поиск элемента в таблице */
int del(int k)
{
Int i;
if((i = binsearch(k)) < 0)
return -1; /* элемента в таблице нет */
--n; /* новый текущий размер таблицы */
for(; i< n; i++)
bintable[i] = bintable[i + 1];
return 0;
}
При включении нового элемента в таблицу удобно использовать алгоритм сортировки вставками, схема которого приведена на рис. II-42. При этом если в таблице не могут находиться элементы с одинаковыми значениями ключей, сначала следует выполнить поиск элемента и, в случае неуспешного поиска, вставить в таблицу новый элемент.
При использовании сортировки вставками сравнение ключей элементов осуществляется от конца таблицы к ее началу. Пока очередной элемент таблицы имеет ключ, превышающий ключ включаемого элемента, этот элемент таблицы копируется в следующую за ним позицию таблицы. Как только ключ очередного элемента таблицы окажется меньше ключа нового элемента, новый элемент включается после найденного. Если вся таблица будет просмотрена, новый элемент будет включен в первую позицию таблицы.
Текст функции для включения нового элемента в упорядоченную таблицу (сортировки вставками) приводится ниже.
const int M = 20; /* максимальный размер таблицы */
struct Item{
int key;
Type info;
};
Item bintable[M];
int n; /* текущийразмертаблицы */
int inssort(int k, Type in)
{
int i;
for(i = n-1; i>= 0 &&bintable[i].key > k; i--)
bintable[i + 1] = bintable[i];
bintable[i + 1].key = k;
bintable[i + 1].info = in;
return ++n;
}
int insert(int k, Type in)
{
if(binsearch(k) >= 0)
return-1; /* в таблице есть элемент с указанным ключом */
if(n == M)
return-2; /* в таблице нет свободной позиции для нового элемента */
return inssort(k, in);
}
Все рассмотренные функции приведены также в файле Programs/tab2vec.cpp.