Вы находитесь на странице: 1из 10

Технический Университет Молдовы

Отчёт
по лабораторной работе №4
По Анализу и построению алгоритмов

Тема: Хеш таблицы

Выполнил: студент гр. TI-155 Корнеску Р.


Проверила: Скороходова Т.А.

Кишинёв 2016
Цель: Изучить работу алгоритмов: прямой адресации, хеш-таблицы и открытой адресации.
Реализовать перечисленные выше алгоритмы и провести их сравнительный анализ.
Задание
1. Написать алгоритмы основных операций (добавление, поиск и удаление) в
псевдокодах для прямой адресации, хеш-таблицы и открытой адресации.
2. Продемонстрировать работу алгоритмов на примере (см. раздел «задание к
лабораторной работе»).
3. Реализовать основные операции на ЭВМ.
4. Провести анализ этих алгоритмов и сделать вывод по их применимости.

Массив 11, 35, 56, 41, 24, 88, 6, 2, 26 Ключи 44, 45, 46, 47 48

1. Привести все используемые алгоритмы в псевдокодах.

Прямая адресация:

DIRECT-ADDRESS-SEARCH (T,k)
return T[k]
DIRECT-ADDRESS-INSERT (T,k)
T[k] = k
DIRECT-ADDRESS-DELETE (T,k)
T[k] = NULL

Хеш-таблицы:

CHAINED-HASH-INSERT (T,k)
добавить k в голову списка T[h[k]]
CHAINED-HASH-SEARCH (T,k)
найти k в списке T[h[k]]
CHAINED-HASH-DELETE (T,k)
удалить k из списка T[h[k]]

h(k)
return k mod m

Открытая адресация:

HASH-INSERT (T,K)
i=0
repeat j=h(k,i)
if T[j]=NULL
then T[j]=k
return j
else i=i+1
until i=m
Error “Хеш-таблица переполнена”

HASH-SEARCH (T,k)
i=0
repeat j=h(k,i)
if T[j]=k
then return j;
i=i+1
until T[j]=NULL or i=m
return NULL

h(k,i)
return (k mod m + 1) mod m

HASH-DELETE (T,k)
i=0
repeat j=h(k,i)
if T[j]=k
then T[j]=NULL
i=i+1
until T[j]=NULL or i=m
Error “Элемент уже удален”

2. Продемонстрировать работу алгоритмов для массива ключей.

Ключи 44, 45, 46, 47 48

Прямая адресация:

DIRECT-ADDRESS-INSERT (T,44)
T[44]=44
DIRECT-ADDRESS-INSERT (T,45)
T[45]=45
DIRECT-ADDRESS-INSERT (T,46)
T[46]= 46
DIRECT-ADDRESS-INSERT (T,47)
T[47]= 47
DIRECT-ADDRESS-INSERT (T,48)
T[21]= 48

0 … 3 … 6 … 9 10 … 17 … 21 … 32 … 43 44 45 46 47 48

NIL … NIL NIL … NIL NIL … NIL … NIL … NIL … NIL 44 45 46 47 48


DIRECT-ADDRESS-DELETE (T,45)
return T[45]=NULL
DIRECT-ADDRESS-DELETE (T,47)
return T[47]=NULL
DIRECT-ADDRESS-DELETE (T,48)
return T[48]=NULL

0 … 3 … 6 … 9 10 … 17 … 21 … 32 … 43 44 45 46 47 48
… NIL … NIL NIL … NIL … NIL … NIL … NIL 44 NIL 46 NIL NIL
NIL … NIL

Хеш-таблицы:
m=11
h(k) = [m(kA mod 1)], где А = ( 5 - l)/2
CHAINED-HASH-INSERT (T,44)
добавить 44 в голову списка T[h[44]]
CHAINED-HASH-INSERT (T,45)
добавить 45 в голову списка T[h[45]]
CHAINED-HASH-INSERT (T,46)
добавить 46 в голову списка T[h[46]]
CHAINED-HASH-INSERT (T,47)
добавить 47 в голову списка T[h[47]]
CHAINED-HASH-INSERT (T,48)
добавить 48 в голову списка T[h[48]]

0->47->Nil
1->Nil
2->44->Nil
3->Nil
4->46->Nil
5->Nil
6->Nil
7->48->Nil
8->45->Nil
9->Nil
10->Nil

CHAINED-HASH-DELETE (T,45)
удалить 45 из списка T[h[45]]
CHAINED-HASH-DELETE (T,46)
удалить 46 из списка T[h[46]]
CHAINED-HASH-DELETE (T,47)
удалить 47 из списка T[h[47]]

0->Nil
1->Nil
2->44->Nil
3->Nil
4->Nil
5->Nil
6->Nil
7->48->Nil
8->Nil
9->Nil
10->Nil
Открытая адресация:

m=11
ℎ1 (𝑘) = 𝑘 𝑚𝑜𝑑 𝑚
ℎ(𝑘, 𝑖) = (ℎ1 (𝑘) + 𝑖ℎ2 (𝑘))𝑚𝑜𝑑 𝑚,
ℎ2 (𝑘) = (1 + 𝑘 𝑚𝑜𝑑 𝑚)

HASH-INSERT (T,44)
HASH-INSERT (T,45)
HASH-INSERT (T,46)
HASH-INSERT (T,47)
HASH-INSERT (T,48)
0->47
1->Nil
2->44
3->Nil
4->46
5->Nil
6->Nil
7->48
8->45
9->Nil
10->Nil

HASH-DELETE (T,45)
HASH-DELETE (T,46)
HASH-DELETE (T,47)

0-> Nil
1->Nil
2->44
3->Nil
4-> Nil
5->Nil
6->Nil
7->48
8-> Nil
9->Nil
10->Nil

Код программы:
// laba_apa_4.cpp: определяет точку входа для консольного приложения.
//

#include "stdafx.h"

#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <math.h>
using namespace std;
int N = 100;
class Direct
{
int *D;
public:
Direct()
{
D = new int[N];
for (int i = 0; i<N; i++) D[i] = -1;
}
void Insert(int k)
{
D[k] = k;
}
void Search(int k)
{
if (k<N)
if (k >= 0)
cout << "Элемент найден\n";
else cout << "Элемент не найден\n";
}
void Delete(int k)
{
if (D[k] != -1) { D[k] = -1; cout << "Элемент удален\n"; }
}
void print()
{
for (int i = 0; i<N; i++)
if (D[i] != -1) cout << i << "->" << D[i] << endl;
}
~Direct()
{
delete[] D;
}
};
class Hash
{
int **H;
int m;
public:
Hash()
{
m = 11;
H = new int*[m];
for (int i = 0; i<m; i++) H[i] = new int[N];
for (int i = 0; i<m; i++)
for (int j = 0; j<N; j++)
H[i][j] = -1;
}
int h(int k, int func) //func = 1 - m[kAmod1] , func != 1 - k mod 9
{
if (func == 1)
{
float A = 0.618;
return int(m*(fmod((float(k)*A), 1)));
}
return int(fmod(float(k), 11));
}
void print()
{
for (int i = 0; i<m; i++)
{
cout << i << "->";
for (int j = 0; j<N; j++)
if (H[i][j] == -1) { cout << " Nil"; break; }
else cout << H[i][j] << "->";
cout << endl;
}
}
void Insert(int k, int func)
{
int place = 0;
while (1)
{
if (H[h(k, func)][place] == -1) { H[h(k, func)][place] = k; break; }
else place++;
}
}
void Search(int k, int func)
{
int place = 0;
while (1)
{
if (H[h(k, func)][place] == k) { cout << "Элемент найден" << endl; return; }
else if (place<m) place++;
else { cout << "Элемент не найден" << endl; return; }
}
}
void Delete(int k, int func)
{
int place = 0;
while (1)
{
if (H[h(k, func)][place] == k) { cout << "Элемент удален" << endl; H[h(k,
func)][place] = -1; return; }
else if (place<m) place++;
else { cout << "Элемент не найден" << endl; return; }
}
}
~Hash()
{
delete H;
}
};
class Open
{
int *O;
int m;
public:
Open()
{
m = 11;
O = new int[m];
for (int i = 0; i<m; i++) O[i] = -1;
}
int h(int k, int func) //func: 1-kAmod1 , 2-kmod11 , other - 1+kmod m-1
{
if (func == 1)
{
float A = 0.618;
return int(m*(fmod((float(k)*A), 1)));
}
if (func == 2) return int(fmod(float(k), 11));
return int(1 + fmod(float(k), (m - 1)));

void print()
{
for (int i = 0; i<m; i++)
{
cout << i << "->";
if (O[i] == -1) cout << " Nil";
else cout << O[i];
cout << endl;
}
}
void Insert(int k, int func)
{
int place = h(k, func);
while (1)
{
if (O[place] == -1) { O[place] = k; return; }
else if (place<m)
place++;
if (place == m) break;
}
cout << "Элемент не добавлен" << endl;
}
void Delete(int k, int func)
{
if (O[h(k, func)] == k) { O[h(k, func)] = -1; cout << "Элемент удален" << endl; }
else cout << "Элемент не найден" << endl;
}
void Search(int k, int func)
{
if (O[h(k, func)] == k) { cout << "Элемент найден" << endl; }
else cout << "элемент не найден" << endl;
}
~Open()
{
delete[] O;
}
};
int main()
{
setlocale(LC_ALL, "Russian");
Hash h;
Open o;
Direct d;

int key;
int fun = 1;
int option = 1;
while (option != 14)
{
cout << "1. Выберите функцию \n";
cout << "2. Вставка для прямой адресаци\n";
cout << "3. Вставка для хэш таблицы\n";
cout << "4. Вставка для открытой адресации\n";
cout << "5. Удаление для прямой адресации\n";
cout << "6. Удалиние элементов для хэш таблицы\n";
cout << "7. Удаление элементов для открытой адресации\n";
cout << "8. Поиск элементов для прямой адресации\n";
cout << "9. Поиск элементов для хэш таблицы\n";
cout << "10. Поиск элементов для открытой адресации\n";
cout << "11. Печать для прямой адрессации\n";
cout << "12. Печать для хэш таблицы\n";
cout << "13. Печать для открытой адресации\n";
cout << "14. Выход\n";
cin >> option;
system("cls");
switch (option)
{
case 1:
{
cout << "ВВедите функцию: 1 - умножение 2- деление "; cin >> fun;
system("cls");
}
break;
case 2:
{
cout << "ВВедите ключ: "; cin >> key;
d.Insert(key);
system("cls");
}
break;
case 3:
{
cout << "Введите ключ: "; cin >> key;
h.Insert(key, fun);
system("cls");
}
break;
case 4:
{
cout << "ВВедите ключ: "; cin >> key;
o.Insert(key, fun); _getch();
system("cls");
}
break;
case 5:
{
cout << "Введите клюя для удаления: "; cin >> key;
d.Delete(key); _getch();
system("cls");
}
break;
case 6:
{
cout << "Введите клюя для удаления: "; cin >> key;
h.Delete(key, fun); _getch();
system("cls");
}
break;
case 7:
{
cout << "Введите клюя для удаления: "; cin >> key;
o.Delete(key, fun); _getch();
system("cls");
}
break;
case 8:
{
cout << "Введите клюя для поиска: "; cin >> key;
d.Search(key); _getch();
system("cls");
}
break;
case 9:
{
cout << "Введите клюя для поиска: "; cin >> key;
h.Search(key, fun); _getch();
system("cls");
}
break;
case 10:
{
cout << "Введите клюя для поиска: "; cin >> key;
o.Search(key, fun); _getch();
system("cls");
}
break;
case 11:
{
d.print(); _getch();
system("cls");
}
break;
case 12:
{
h.print(); _getch();
system("cls");
}
break;
case 13:
{
o.print(); _getch();
system("cls");
}
break;
case 14:
{
break;
}
}
}
_getch();
return 0;
}
Прямая адресация

Хеш-таблица

Открытая адресация

Вывод: В ходе выполнения данной лабораторной работы были реализованы 3


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

Вам также может понравиться