Главная страница

Хеш-таблица для строк. лабочка 5. Лабораторная работа 5 Хеширование данных. Поиск данных в хештаблице


Скачать 159.66 Kb.
НазваниеЛабораторная работа 5 Хеширование данных. Поиск данных в хештаблице
АнкорХеш-таблица для строк
Дата12.05.2022
Размер159.66 Kb.
Формат файлаdocx
Имя файлалабочка 5.docx
ТипЛабораторная работа
#525645

Лабораторная работа №5

Хеширование данных. Поиск данных в хеш-таблице.
Разработать программу хеширования данных из файла методом открытого хеширования. Хеш-таблицу закодировать как класс, а операции с ней - как функции-члены класса. В программе предусмотреть следующий действия:

а) создание хеш-таблицы с небольшим количеством классов (B<=30) и небольшим набором исходных данных, вывод всей таблицы на экран, осуществление поиска по таблице, в качестве хеш-функции выбрать h(x)=x%B;

б) создание хеш-таблицы, для которой количество классов B задается пользователем (до 20000 - 50000), осуществление поиска по таблице, подсчет общего числа коллизий в таблице, нахождение самой длинной цепочки коллизий, процента заполняемости таблицы. В качестве хеш-функции выбрать h(x)=(ax+c)%B, проанализировать результаты заполняемости таблицы для различных a и c.
В качестве исходных данных выбрать:

9 вариант. Текстовый файл (варианты 3,6,9,12).

Алгоритм:

  1. Создается массив списков размером B.

  2. Считывается текст из файла и делится на лексемы. (пропускаются ненужные символы)

  3. Лексема добавляется в список с индексом h(x). В качестве x берется hashcode лексемы.

Алгоритм поиска:

  1. Список с индексом h(x) проверяется на наличие слова

  2. При наличии выводится само слово, при отсутствии – соответствующее сообщение.


Алгоритм вывод таблицы:

  1. Создается таблица с количеством строчек = B.

  2. Каждая строка заполняется всеми словами, которые находятся в списке с соответствующим индексом.

Алгоритм подсчета коллизий:

  1. Создается переменная для подсчета коллизий.

  2. Проверяется каждый список и к переменной добавляется количество элементов в данном списке.

Алгоритм поиска самой длинной коллизии:

  1. Создается переменная, которой изначально присваивается количество коллизий в списке с индексом 0.

  2. Проверяется количество коллизий в каждом списке, если коллизий больше, то происходит переприсваивание.

Алгоритм подсчета заполняемости:

  1. Считается количество непустых списков, делится на B и умножается на 100.


Код:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System.IO;
namespace WindowsFormsApp1

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

class HashTableA

{

public int B;

List[] Key;

public void Tablica()

{

Key = new List[B];

for (int i = 0; i < B; i++)

Key[i] = new List();

String[] data = File.ReadAllText("inputa.txt").Split(',', ' ', '\n').ToArray();

for (int i = 0; i < data.Length; i++)

{

/*string slovo = data[i];

int r = 0;

if (slovo.Length > 2) r = slovo[0] + slovo[1];

else r = slovo[0];

Key[System.Math.Abs(r % B)].Add(data[i]);*/
if (data[i].CompareTo(" ") > 0)

Key[System.Math.Abs(data[i].GetHashCode() % B)].Add(data[i]);

}

}

public void Vivod(DataGridView tablica)

{

tablica.Rows.Clear();

tablica.Columns.Clear();

int length = Key[0].Count;

for (int i = 1; i < B; i++)

if (Key[i].Count > length)

length = Key[i].Count;

for (int i = 0; i <= length; i++)

tablica.Columns.Add(" ", " ");

tablica.Rows.Add(B - 1);

for (int i = 0; i < B; i++)

tablica.Rows[i].Cells[0].Value = i;

for (int i = 0; i < B; i++)

for (int j = 0; j < Key[i].Count; j++)

tablica.Rows[i].Cells[j + 1].Value = Key[i][j];

}

public String Search(String word)

{

if (Key[System.Math.Abs(word.GetHashCode() % B)].Contains(word))

return word;

else

return "Такого слова нет";

}

}

class HashTableB

{

List[] Key;

public int B, a, c;

public void Build()

{

Key = new List[B];

for (int i = 0; i < B; i++)

Key[i] = new List();

String[] data = File.ReadAllText("inputb.txt").Split(',', ' ', '\n',';','\r','\t').ToArray();

for (int i = 0; i < data.Length; i++)

{

// int kk = data[i].GetHashCode();

// int gg = data[i].CompareTo(" ");

if (data[i].CompareTo(" ") > 0) //убираем пустые строки (все, что в Юникоде до пробела)

/*<0 текст в классе раньше по алфавиту чем пробел

=0 текст в классе одинаков с текстом пробел

>0 текст в классе позже по алфавиту чем текст пробел*/

Key[System.Math.Abs((a * data[i].GetHashCode() + c) % B)].Add(data[i]); //Аbs, тк хэши могут быть отрицательные

}

}

public String Search_Word(String word)

{

if (Key[System.Math.Abs((a * word.GetHashCode() + c) % B)].Contains(word)) //contains определяет, есть ли данное слово под индексом

return word;

else

return "Слово не найдено";

}

public void Collizii(Label l)

{

int x = 0;

for (int i = 0; i < Key.Length; i++)

if (Key[i].Count > 1) //число элементов под данным индексом

x += Key[i].Count;

l.Text = "Число коллизий: " + (x - 1);

}

public void MakcimumCollizii(Label l)

{

int x = Key[0].Count; //число элементов в первой ячейке

for (int i = 1; i < Key.Length; i++)

if (Key[i].Count > x)

x = Key[i].Count;

l.Text = "Самая длинная цепочка коллизий составляет: " + (x - 1) + " элементов";

}

public void Zapolnenie(Label l)

{

double x = 0;

for (int i = 0; i < Key.Length; i++)

if (Key[i].Count > 0)

x++;

x = Math.Round(x / Key.Length * 100);

l.Text = "Процент заполняемости таблицы составляет " + x + "%";

}

}

HashTableA hta = new HashTableA();

HashTableB htb = new HashTableB();

private void button1_Click(object sender, EventArgs e)

{

hta.B = Convert.ToInt32(numericUpDown1.Value);

hta.Tablica();

hta.Vivod(dataGridView1);

}
private void button2_Click(object sender, EventArgs e)

{

textBox2.Text = hta.Search(textBox1.Text);

}
private void button3_Click(object sender, EventArgs e)

{

htb.B = Convert.ToInt32(numericUpDown2.Value);

htb.c = Convert.ToInt32(numericUpDown3.Value);

htb.a = Convert.ToInt32(numericUpDown4.Value);

htb.Build();

htb.Collizii(label5);

htb.MakcimumCollizii(label6);

htb.Zapolnenie(label7);

}
private void button4_Click(object sender, EventArgs e)

{

textBox4.Text = htb.Search_Word(textBox3.Text);

}
private void label11_Click(object sender, EventArgs e)

{
}
private void numericUpDown3_ValueChanged(object sender, EventArgs e)

{
}

}

}



Тесты:


Выводы:



  1. При увеличении B, количество коллизий увеличивается, но максимальная коллизия уменьшается = > таблица нормализуется;

  2. При нечетном a процент заполняемости больше,количество коллизий меньше;









  1. Большое увеличение a негативно влияет на количество коллизий и заполняемость;





написать администратору сайта