Initial commit
@@ -0,0 +1,85 @@
|
||||
TEMPLATE = app
|
||||
|
||||
QMAKE_CXXFLAGS += -O2 -finline-small-functions -momit-leaf-frame-pointer #-mpreferred-stack-boundary=2
|
||||
|
||||
#QMAKE_CXXFLAGS_DEBUG += -pg
|
||||
#QMAKE_LFLAGS_DEBUG += -pg
|
||||
|
||||
CONFIG += \
|
||||
c++14 \
|
||||
#release
|
||||
|
||||
QT += \
|
||||
widgets \
|
||||
core \
|
||||
gui \
|
||||
charts \
|
||||
xml
|
||||
|
||||
RESOURCES += \
|
||||
SourceCode/resources.qrc
|
||||
|
||||
FORMS += \
|
||||
SourceCode/UserInterface/FilesUI/demonstrationWidget.ui \
|
||||
SourceCode/UserInterface/FilesUI/mainWindow.ui \
|
||||
SourceCode/UserInterface/FilesUI/testingWidget.ui \
|
||||
SourceCode/UserInterface/FilesUI/textBrowserWidget.ui
|
||||
|
||||
HEADERS += \
|
||||
SourceCode/BusinessLogic/Convert/convert.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorDoubleHashing.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorFamily.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorPseudorandomProbing.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/Family/doubleHashing.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/Family/family.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/Family/pseudorandomProbing.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/One/creatorLinearProbing.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/One/creatorOne.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/One/creatorQuadraticProbing.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/One/linearProbing.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/One/one.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/One/quadraticProbing.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/abstract.h \
|
||||
SourceCode/BusinessLogic/Hash/Algorithm/creatorAbstract.h \
|
||||
SourceCode/BusinessLogic/Hash/Factory/abstract.h \
|
||||
SourceCode/BusinessLogic/Hash/Factory/family.h \
|
||||
SourceCode/BusinessLogic/Hash/Factory/one.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/Family/creatorFamily.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/Family/creatorFnv1a.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/Family/family.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/Family/fnv1a.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/One/creatorEquivalent.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/One/creatorOne.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/One/equivalent.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/One/one.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/One/creatorStandart.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/One/standart.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/Pattern/creatorFamilyToOne.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/Pattern/familyToOne.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/abstract.h \
|
||||
SourceCode/BusinessLogic/Hash/Function/creatorAbstract.h \
|
||||
SourceCode/BusinessLogic/Hash/Table/Pattern/subscriber.h \
|
||||
SourceCode/BusinessLogic/Hash/Table/abstract.h \
|
||||
SourceCode/BusinessLogic/Hash/Table/chains.h \
|
||||
SourceCode/BusinessLogic/Hash/Table/openAddress.h \
|
||||
SourceCode/BusinessLogic/Pattern/singleton.h \
|
||||
SourceCode/BusinessLogic/Statistics/dispersion.h \
|
||||
SourceCode/BusinessLogic/businessLogic.h \
|
||||
SourceCode/BusinessLogic/hashHeaderFiles.h \
|
||||
SourceCode/UserInterface/ClassesUI/Validator/validator.h \
|
||||
SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.h \
|
||||
SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.h \
|
||||
SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.h \
|
||||
SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.h
|
||||
|
||||
SOURCES += \
|
||||
SourceCode/BusinessLogic/Convert/convert.cpp \
|
||||
SourceCode/BusinessLogic/Statistics/dispersion.cpp \
|
||||
SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.cpp \
|
||||
SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.cpp \
|
||||
SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.cpp \
|
||||
SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.cpp \
|
||||
SourceCode/main.cpp
|
||||
#SourceCode/BusinessLogic/debug.cpp
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "Inserting into a hash table"
|
||||
#define MyAppVersion "1.0.0"
|
||||
#define MyAppExeName "HashTable.exe"
|
||||
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
AppId={{E9AC9BF2-18C1-4A8D-9576-5A1B632AC7F7}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
;AppVerName={#MyAppName} {#MyAppVersion}
|
||||
DefaultDirName={autopf}\HashTable
|
||||
AllowNoIcons=yes
|
||||
OutputBaseFilename=setup
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "C:\Users\*\Desktop\HashTable\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "C:\Users\*\Desktop\HashTable\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
||||
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0"?>
|
||||
<questions>
|
||||
|
||||
<question category = "hashTable|algorithm" complexity = "easy" type = "choice">
|
||||
<caption>Соотнесите подходящие варианты ответа с высказыванием.</caption>
|
||||
<text>Метод решения коллизий в хеш-таблице.</text>
|
||||
<answer type = "wrong">Прямая адрессация.</answer>
|
||||
<answer type = "correct">Открытая адрессация.</answer>
|
||||
<answer type = "wrong">Регистровая адресация.</answer>
|
||||
<answer type = "correct">Метод цепочек.</answer>
|
||||
<answer type = "wrong">Ничего из вышеперечисленного.</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashFunction" complexity = "easy" type = "choice">
|
||||
<caption>Выберите несколько правильных ответов.</caption>
|
||||
<text>С какими данными оперирует хеш-функция в процессе хеширования?</text>
|
||||
<answer>Хеш-память.</answer>
|
||||
<answer type = "correct">Хеш-значение.</answer>
|
||||
<answer>Кеш-память.</answer>
|
||||
<answer type = "correct">Множество ключей.</answer>
|
||||
<answer type = "correct">Множество значений.</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashFunction" complexity = "easy" type = "choice">
|
||||
<caption>Выберите несколько правильных ответов.</caption>
|
||||
<text>На что влияет коэффициент заполнения?</text>
|
||||
<answer type = "correct">Поиск неиспользующегося бункера, при гарантии его существования.</answer>
|
||||
<answer>Поиск использующегося бункера по его ключу.</answer>
|
||||
<answer>Скорость хеширования.</answer>
|
||||
<answer type = "correct">Количество используемых бункеров.</answer>
|
||||
<answer>Количество возможных ключей.</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashTable|algorithm" complexity = "easy" type = "choice">
|
||||
<caption>Выберите несколько правильных ответов.</caption>
|
||||
<text>Какие алгоритмы поиска бункера при решении коллизий открытой адресацией используют ровно одну хеш-функцию?</text>
|
||||
<answer type = "correct">Линейное пробирование.</answer>
|
||||
<answer type = "correct">Квадратичное пробирование.</answer>
|
||||
<answer type = "correct">Псевдослучайное пробирование.</answer>
|
||||
<answer>Двойное хеширование.</answer>
|
||||
<answer>Ничего из перечисленного.</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashTable|algorithm" complexity = "easy" type = "integer">
|
||||
<caption>Введите правильное целочисленое число.</caption>
|
||||
<text>Чему равна дисперсия, как мера разброса элементов хеш-таблицы от средней условной величины при идеальном хешировании?</text>
|
||||
<answer type = "correct">0</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashTable" complexity = "easy" type = "choice">
|
||||
<caption>Выберите варианты ответов, которые подходят по смыслу с заданным текстом.</caption>
|
||||
<text>Сопоставьте - идеальное хеширование.</text>
|
||||
<answer type = "correct">Словарь.</answer>
|
||||
<answer type = "correct">Прямая адрессация.</answer>
|
||||
<answer type = "wrong">Открытая адрессация.</answer>
|
||||
<answer type = "wrong">Регистровая адресация.</answer>
|
||||
<answer type = "wrong">Метод цепочек.</answer>
|
||||
<answer type = "wrong">Ничего из вышеперечисленного.</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashTable|algorithm" complexity = "easy" type = "choice">
|
||||
<caption>Определите про какие алгоритмы поиска бункера при решении коллизий открытой адресацией идёт речь?</caption>
|
||||
<text>Политика разрешения коллизий использует шаг по индексу, который зависит от информации (позиция или данные) бункера.</text>
|
||||
<answer type = "wrong">Линейное пробирование.</answer>
|
||||
<answer type = "wrong">Квадратичное пробирование.</answer>
|
||||
<answer type = "correct">Псевдослучайное пробирование.</answer>
|
||||
<answer type = "correct">Двойное хеширование.</answer>
|
||||
<answer type = "wrong">Ничего из вышеперечисленного.</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashTable|algorithm" complexity = "easy" type = "choice">
|
||||
<caption>Определите про какие алгоритмы поиска бункера при решении коллизий открытой адресацией идёт речь?</caption>
|
||||
<text>Политика разрешения коллизий использует шаг по индексу, который зависит от количества итераций и/или размера хеш-таблицы.</text>
|
||||
<answer type = "correct">Линейное пробирование.</answer>
|
||||
<answer type = "correct">Квадратичное пробирование.</answer>
|
||||
<answer type = "wrong">Псевдослучайное пробирование.</answer>
|
||||
<answer type = "wrong">Двойное хеширование.</answer>
|
||||
<answer type = "wrong">Ничего из вышеперечисленного.</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashTable|algorithm|discreteMathematics" complexity = "hard" type = "integer">
|
||||
<caption>Напишите правильный ответ.</caption>
|
||||
<text>Рассмотрим хеш-функцию, которая равномерно распределяет значения по хеш-таблице.
|
||||
Размер хеш-таблицы равен 20.
|
||||
После какого количества вставок вероятность того, что при попытке вставить в хеш-таблицу новое значение произойдёт коллизия, превысит 0.5?</text>
|
||||
<answer type = "correct">11</answer>
|
||||
</question>
|
||||
|
||||
<question category = "hashTable" complexity = "medium" type = "integer">
|
||||
<caption>Напишите правильный ответ.</caption>
|
||||
<text>Чему будет равен коэффициент заполненности, если в хеш-таблица с 25 цепочками поместить 2000 элементов?</text>
|
||||
<answer type = "correct">80</answer>
|
||||
</question>
|
||||
|
||||
<question category = "discreteMathematics" complexity = "medium" type = "floatingPoint">
|
||||
<caption>Напишите правильный ответ.</caption>
|
||||
<text>Определите коэффициет заполнения хеш-таблицы с решением коллизий методом открытой адресациии, если её размер равняется 50, но свободных бункеров - 20.</text>
|
||||
<answer type = "correct">0,60</answer>
|
||||
</question>
|
||||
|
||||
</questions>
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "convert.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Convert)
|
||||
|
||||
size_t FromStdString::operator()(const std::array<char, 5> &value, size_t alphabetPower) const {
|
||||
if (value.empty()) {
|
||||
throw std::invalid_argument("undefined key");
|
||||
}
|
||||
|
||||
size_t result = 0;
|
||||
size_t counter = 0;
|
||||
for (auto crbegin = value.crbegin(), crend = value.crend()
|
||||
; crbegin != crend && *crbegin >= '!' && *crbegin <= '~'; ++crbegin, ++counter
|
||||
) {
|
||||
result += (*crbegin) * std::pow(alphabetPower, counter);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
END_NAMESPACE // Convert
|
||||
END_NAMESPACE // BusinessLogic
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef CONVERT_H
|
||||
#define CONVERT_H
|
||||
|
||||
#include "../businessLogic.h"
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <limits>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Convert)
|
||||
|
||||
class FromStdString
|
||||
{
|
||||
public:
|
||||
size_t operator()(const std::array<char, 5> &, size_t) const;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Convert
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // CONVERT_H
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef CREATOR_ALGHORITHM_DOUBLE_HASHING_H
|
||||
#define CREATOR_ALGHORITHM_DOUBLE_HASHING_H
|
||||
|
||||
#include "doubleHashing.h"
|
||||
#include "creatorFamily.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(DoubleHashing)
|
||||
|
||||
class Creator : public Family::Creator
|
||||
{
|
||||
private:
|
||||
size_t m_firstHashFunction;
|
||||
size_t m_secondHashFunction;
|
||||
|
||||
public:
|
||||
Creator(size_t first, size_t second) : m_firstHashFunction(first), m_secondHashFunction(second)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual std::unique_ptr<Abstract::Product> create() const override {
|
||||
return std::unique_ptr<Abstract::Product>(new Product(m_firstHashFunction, m_secondHashFunction));
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // DoubleHashing
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_ALGHORITHM_DOUBLE_HASHING_H
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef CREATOR_ALGHORITHM_FAMILY_H
|
||||
#define CREATOR_ALGHORITHM_FAMILY_H
|
||||
|
||||
#include "../creatorAbstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(Family)
|
||||
|
||||
class Creator : public Abstract::Creator
|
||||
{
|
||||
protected:
|
||||
Creator()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Family
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_ALGHORITHM_FAMILY_H
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef CREATOR_ALGHORITHM_PSEUDORANDOM_PROBING_H
|
||||
#define CREATOR_ALGHORITHM_PSEUDORANDOM_PROBING_H
|
||||
|
||||
#include "pseudorandomProbing.h"
|
||||
#include "creatorFamily.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(PseudorandomProbing)
|
||||
|
||||
class Creator : public Family::Creator
|
||||
{
|
||||
private:
|
||||
size_t m_hashFunctionNumber;
|
||||
|
||||
public:
|
||||
Creator(size_t number) : m_hashFunctionNumber(number)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual std::unique_ptr<Abstract::Product> create() const override {
|
||||
return std::unique_ptr<Abstract::Product>(new Product(m_hashFunctionNumber));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
END_NAMESPACE // PseudorandomProbing
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_ALGHORITHM_PSEUDORANDOM_PROBING_H
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef ALGHORITHM_DOUBLE_HASHING_H
|
||||
#define ALGHORITHM_DOUBLE_HASHING_H
|
||||
|
||||
#include "family.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(DoubleHashing)
|
||||
|
||||
class Product final : public Family::Product
|
||||
{
|
||||
private:
|
||||
size_t m_firstHashFunction;
|
||||
size_t m_secondHashFunction;
|
||||
size_t m_multiplier;
|
||||
private:
|
||||
friend Creator;
|
||||
Product(size_t first, size_t second) : m_firstHashFunction(first), m_secondHashFunction(second)
|
||||
{
|
||||
if (first == second) {
|
||||
throw std::invalid_argument("hash functions must be different");
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual size_t getFirstCoefficient() override {
|
||||
m_multiplier = m_hashFunction->getHash(m_convertValue, m_firstHashFunction);
|
||||
return m_hashFunction->getHash(m_convertValue, m_firstHashFunction);
|
||||
}
|
||||
virtual size_t getSecondCoefficient(size_t counter) override {
|
||||
return counter * m_multiplier;
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // DoubleHashing
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !ALGHORITHM_DOUBLE_HASHING_H
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef ALGHORITHM_FAMILY_H
|
||||
#define ALGHORITHM_FAMILY_H
|
||||
|
||||
#include "../../Function/Family/family.h"
|
||||
#include "../abstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(Family)
|
||||
|
||||
class Product : public Abstract::Product
|
||||
{
|
||||
public:
|
||||
using function_type = Function::Family::Product;
|
||||
|
||||
protected:
|
||||
const function_type *m_hashFunction;
|
||||
|
||||
protected:
|
||||
Product() : m_hashFunction(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
void setHashFunction(const function_type &hashFunction) {
|
||||
m_hashFunction = &hashFunction;
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Family
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !ALGHORITHM_FAMILY_H
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef ALGHORITHM_PSEUDORANDOM_PROBING_H
|
||||
#define ALGHORITHM_PSEUDORANDOM_PROBING_H
|
||||
|
||||
#include "family.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(PseudorandomProbing)
|
||||
|
||||
class Product final : public Family::Product
|
||||
{
|
||||
private:
|
||||
size_t m_hashFunctionNumber;
|
||||
size_t m_multiplier;
|
||||
|
||||
private:
|
||||
friend Creator;
|
||||
Product(size_t number) : m_hashFunctionNumber(number)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
// virtual bool isValidInput() const override {
|
||||
// return isPrimeNumber(size());
|
||||
// }
|
||||
virtual size_t getFirstCoefficient() override {
|
||||
m_multiplier = m_hashFunction->getHash(m_convertValue, m_hashFunctionNumber);
|
||||
srand(m_multiplier);
|
||||
return m_hashFunction->getHash(m_convertValue, m_hashFunctionNumber);
|
||||
}
|
||||
virtual size_t getSecondCoefficient(size_t counter) override {
|
||||
return counter * rand();
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // PseudorandomProbing
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !ALGHORITHM_PSEUDORANDOM_PROBING_H
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef CREATOR_ALGHORITHM_LINEAR_PROBING_H
|
||||
#define CREATOR_ALGHORITHM_LINEAR_PROBING_H
|
||||
|
||||
#include "linearProbing.h"
|
||||
#include "creatorOne.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(LinearProbing)
|
||||
|
||||
class Creator : public One::Creator
|
||||
{
|
||||
private:
|
||||
/* A number that is not mutually prime to the size will not apply */
|
||||
const size_t m_coefficient;
|
||||
|
||||
public:
|
||||
Creator(size_t coefficient = 1) : m_coefficient(coefficient)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual std::unique_ptr<Abstract::Product> create() const override {
|
||||
return std::unique_ptr<Abstract::Product>(new Product(m_coefficient));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
END_NAMESPACE // LinearProbing
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_ALGHORITHM_LINEAR_PROBING_H
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef CREATOR_ALGHORITHM_ONE_H
|
||||
#define CREATOR_ALGHORITHM_ONE_H
|
||||
|
||||
#include "../creatorAbstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(One)
|
||||
|
||||
class Creator : public Abstract::Creator
|
||||
{
|
||||
protected:
|
||||
Creator()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // One
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_ALGHORITHM_ONE_H
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef CREATOR_ALGHORITHM_QUADRATIC_PROBING_H
|
||||
#define CREATOR_ALGHORITHM_QUADRATIC_PROBING_H
|
||||
|
||||
#include "quadraticProbing.h"
|
||||
#include "creatorOne.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(QuadraticProbing)
|
||||
|
||||
class Creator : public One::Creator
|
||||
{
|
||||
public:
|
||||
Creator()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual std::unique_ptr<Abstract::Product> create() const override {
|
||||
return std::unique_ptr<Abstract::Product>(new Product());
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // LinearProbing
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_ALGHORITHM_QUADRATIC_PROBING_H
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef ALGHORITHM_LINEAR_PROBING_H
|
||||
#define ALGHORITHM_LINEAR_PROBING_H
|
||||
|
||||
#include "one.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(LinearProbing)
|
||||
|
||||
class Product final : public One::Product
|
||||
{
|
||||
private:
|
||||
/* A number that is not mutually prime to the size will not apply */
|
||||
const size_t m_coefficient;
|
||||
|
||||
private:
|
||||
friend Creator;
|
||||
Product(size_t coefficient)
|
||||
: m_coefficient(coefficient == 0 ? 1 : coefficient)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
// virtual bool isValidInput() const override {
|
||||
// return gcd(m_coefficient, size()) == 1;
|
||||
// }
|
||||
virtual size_t getFirstCoefficient() override {
|
||||
return m_hashFunction->getHash(m_convertValue);
|
||||
}
|
||||
virtual size_t getSecondCoefficient(size_t counter) override {
|
||||
return counter * m_coefficient;
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // LinearProbing
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !ALGHORITHM_LINEAR_PROBING_H
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef ALGHORITHM_ONE_H
|
||||
#define ALGHORITHM_ONE_H
|
||||
|
||||
#include "../../Function/One/one.h"
|
||||
#include "../abstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(One)
|
||||
|
||||
class Product : public Abstract::Product
|
||||
{
|
||||
public:
|
||||
using function_type = Function::One::Product;
|
||||
|
||||
protected:
|
||||
const function_type *m_hashFunction;
|
||||
|
||||
protected:
|
||||
Product() : m_hashFunction(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
void setHashFunction(const function_type &hashFunction) {
|
||||
m_hashFunction = &hashFunction;
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // One
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !ALGHORITHM_ONE_H
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef ALGHORITHM_QUADRATIC_PROBING_H
|
||||
#define ALGHORITHM_QUADRATIC_PROBING_H
|
||||
|
||||
#include "one.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(QuadraticProbing)
|
||||
|
||||
class Product final : public One::Product
|
||||
{
|
||||
private:
|
||||
friend Creator;
|
||||
Product()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
// virtual bool isValidInput() const override {
|
||||
// return isPrimeNumber(size());
|
||||
// }
|
||||
virtual size_t getFirstCoefficient() override {
|
||||
return m_hashFunction->getHash(m_convertValue);
|
||||
}
|
||||
virtual size_t getSecondCoefficient(size_t counter) override {
|
||||
return std::pow(size(), counter);
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // LinearProbing
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !ALGHORITHM_QUADRATIC_PROBING_H
|
||||
@@ -0,0 +1,101 @@
|
||||
#ifndef ALGHORITHM_ABSTRACT_H
|
||||
#define ALGHORITHM_ABSTRACT_H
|
||||
|
||||
#include "../../Convert/convert.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(Abstract)
|
||||
|
||||
class Product
|
||||
{
|
||||
public:
|
||||
using value_type = std::array<char, 5>;
|
||||
|
||||
private:
|
||||
const std::vector<value_type> *m_table;
|
||||
BusinessLogic::Convert::FromStdString m_toInteger;
|
||||
|
||||
protected:
|
||||
size_t m_convertValue;
|
||||
|
||||
protected:
|
||||
Product() : m_table(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t gcd(size_t first, size_t second) const {
|
||||
while (first > 0 && second > 0) {
|
||||
first > second
|
||||
? first %= second
|
||||
: second %= first;
|
||||
}
|
||||
return first + second;
|
||||
}
|
||||
bool isPrimeNumber(size_t value) const {
|
||||
size_t size = static_cast<size_t>(sqrt(value));
|
||||
for (size_t i = 2; i <= size; i++) {
|
||||
if (value % i == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
size_t size() const {
|
||||
return m_table->size();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool isValidInput() const {
|
||||
return true;
|
||||
}
|
||||
virtual size_t getFirstCoefficient() = 0;
|
||||
virtual size_t getSecondCoefficient(size_t counter) = 0;
|
||||
|
||||
public:
|
||||
void setTable(decltype(m_table) table) {
|
||||
m_table = table;
|
||||
}
|
||||
|
||||
size_t getIndex(const value_type &value, size_t& numberOfCollisions, size_t alphabetPower) {
|
||||
if (not isValidInput()) {
|
||||
throw std::invalid_argument("the condition for using the algorithm is not met");
|
||||
}
|
||||
|
||||
size_t size = m_table->size();
|
||||
m_convertValue = m_toInteger(value, alphabetPower);
|
||||
// It is necessary to use some coefficient
|
||||
|
||||
numberOfCollisions = 0;
|
||||
decltype (m_table->cbegin()) currentIterator;
|
||||
|
||||
constexpr std::array<char, 5> nullValue = {'\0', '\0', '\0', '\0', '\0'};
|
||||
while (numberOfCollisions <= size) {
|
||||
currentIterator = {
|
||||
m_table->cbegin()
|
||||
+ ( getFirstCoefficient() + getSecondCoefficient(numberOfCollisions) ) % size
|
||||
};
|
||||
|
||||
if ( *currentIterator == nullValue || *currentIterator == value ) { // Free cell or value match
|
||||
return ( currentIterator - m_table->cbegin() );
|
||||
}
|
||||
++numberOfCollisions;
|
||||
}
|
||||
return std::numeric_limits<size_t>::max();
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Abstract
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !ALGHORITHM_ABSTRACT_H
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef CREATOR_ALGHORITHM_ABSTRACT_H
|
||||
#define CREATOR_ALGHORITHM_ABSTRACT_H
|
||||
|
||||
#include "../../../BusinessLogic/businessLogic.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Algorithm)
|
||||
BEGIN_NAMESPACE(Abstract)
|
||||
|
||||
class Creator
|
||||
{
|
||||
protected:
|
||||
Creator()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual std::unique_ptr<Product> create() const = 0;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Abstract
|
||||
END_NAMESPACE // Algorithm
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_ALGHORITHM_ABSTRACT_H
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef FACTORY_ABSTRACT_H
|
||||
#define FACTORY_ABSTRACT_H
|
||||
|
||||
#include "../Function/abstract.h"
|
||||
#include "../Algorithm/abstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Factory)
|
||||
|
||||
class Abstract
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* I used to use a constant link. This led to UB.
|
||||
*
|
||||
* https://eel.is/c++draft/class.temporary#6 (27.10.2021)
|
||||
*
|
||||
* The exceptions to this lifetime rule are:
|
||||
* (6.9) A temporary object bound to a reference parameter in a function call ([expr.call]) persists until the completion of the full-expression containing the call.
|
||||
*/
|
||||
using AFC_type = std::shared_ptr<Function::Abstract::Creator>;
|
||||
using AAC_type = std::shared_ptr<Algorithm::Abstract::Creator>;
|
||||
|
||||
protected:
|
||||
AFC_type m_functionCreator;
|
||||
AAC_type m_algorithmCreator;
|
||||
|
||||
protected:
|
||||
Abstract(AFC_type functionCreator, AAC_type algorithmCreator)
|
||||
: m_functionCreator(functionCreator), m_algorithmCreator(algorithmCreator)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using AFP_type = Function::Abstract::Product;
|
||||
using AAP_type = Algorithm::Abstract::Product;
|
||||
|
||||
public:
|
||||
virtual const AFP_type &getFunction() const = 0;
|
||||
virtual std::unique_ptr<AAP_type> getAlgorithm() const = 0;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Factory
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !FACTORY_ABSTRACT_H
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef FACTORY_FAMILY_H
|
||||
#define FACTORY_FAMILY_H
|
||||
|
||||
#include "../Factory/abstract.h"
|
||||
|
||||
#include "../Function/Family/family.h"
|
||||
#include "../Function/Family/creatorFamily.h"
|
||||
|
||||
#include "../Algorithm/Family/family.h"
|
||||
#include "../Algorithm/Family/creatorFamily.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Factory)
|
||||
|
||||
class Family final : public Abstract
|
||||
{
|
||||
public:
|
||||
using FFC_type = std::shared_ptr<Function::Family::Creator>;
|
||||
using FAC_type = std::shared_ptr<Algorithm::Family::Creator>;
|
||||
|
||||
using FFP_type = Function::Family::Product;
|
||||
using FAP_type = Algorithm::Family::Product;
|
||||
|
||||
public:
|
||||
Family(const FFC_type functionCreator, const FAC_type algorithmCreator)
|
||||
: Abstract(functionCreator, algorithmCreator)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual const FFP_type &getFunction() const override {
|
||||
return dynamic_cast<const FFP_type &>(m_functionCreator->create());
|
||||
}
|
||||
virtual std::unique_ptr<AAP_type> getAlgorithm() const override {
|
||||
std::unique_ptr<AAP_type> algorithm = m_algorithmCreator->create();
|
||||
dynamic_cast<FAP_type *>(algorithm.get())->setHashFunction(getFunction());
|
||||
return algorithm;
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Factory
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !FACTORY_FAMILY_H
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef FACTORY_ONE_H
|
||||
#define FACTORY_ONE_H
|
||||
|
||||
#include "../Factory/abstract.h"
|
||||
|
||||
#include "../Function/One/one.h"
|
||||
#include "../Function/One/creatorOne.h"
|
||||
|
||||
#include "../Algorithm/One/one.h"
|
||||
#include "../Algorithm/One/creatorOne.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Factory)
|
||||
|
||||
class One final : public Abstract
|
||||
{
|
||||
public:
|
||||
using OFC_type = std::shared_ptr<Function::One::Creator>;
|
||||
using OAC_type = std::shared_ptr<Algorithm::One::Creator>;
|
||||
|
||||
using OFP_type = Function::One::Product;
|
||||
using OAP_type = Algorithm::One::Product;
|
||||
|
||||
public:
|
||||
One(OFC_type functionCreator, OAC_type algorithmCreator)
|
||||
: Abstract(functionCreator, algorithmCreator)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual const OFP_type &getFunction() const override {
|
||||
return dynamic_cast<const OFP_type &>(m_functionCreator->create());
|
||||
}
|
||||
virtual std::unique_ptr<AAP_type> getAlgorithm() const override {
|
||||
std::unique_ptr<AAP_type> algorithm = m_algorithmCreator->create();
|
||||
dynamic_cast<OAP_type *>(algorithm.get())->setHashFunction(getFunction());
|
||||
return algorithm;
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Factory
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !FACTORY_ONE_H
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef CREATOR_FUNCTION_FAMILY_H
|
||||
#define CREATOR_FUNCTION_FAMILY_H
|
||||
|
||||
#include "../creatorAbstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Family)
|
||||
|
||||
class Creator : public Abstract::Creator
|
||||
{
|
||||
protected:
|
||||
Creator()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual const Product &create() const = 0;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Family
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // CREATOR_FUNCTION_FAMILY_H
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef CREATOR_FUNCTION_FNV1a_H
|
||||
#define CREATOR_FUNCTION_FNV1a_H
|
||||
|
||||
#include "fnv1a.h"
|
||||
#include "creatorFamily.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(FNV1a)
|
||||
|
||||
class Creator : public Family::Creator
|
||||
{
|
||||
public:
|
||||
virtual const Product &create() const override {
|
||||
return Product::getInstance();
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // FNV1a
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_FUNCTION_FNV1a_H
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef FUNCTION_FAMILY_H
|
||||
#define FUNCTION_FAMILY_H
|
||||
|
||||
#include "../abstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Family)
|
||||
|
||||
using function_type = std::function<size_t(size_t, size_t)>;
|
||||
|
||||
class Product : public Abstract::Product
|
||||
{
|
||||
protected:
|
||||
const function_type m_function;
|
||||
|
||||
protected:
|
||||
Product(const function_type& function) : m_function(function)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
const function_type &to_std() const {
|
||||
return m_function;
|
||||
}
|
||||
size_t getHash(size_t first, size_t second) const {
|
||||
// First - the value that is hashed
|
||||
// Second - coefficient
|
||||
return m_function(first, second);
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Family
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // FUNCTION_FAMILY_H
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef FUNCTION_FNV1a_H
|
||||
#define FUNCTION_FNV1a_H
|
||||
|
||||
#include "family.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(FNV1a)
|
||||
|
||||
using Singleton = BusinessLogic::Pattern::Singleton<Product>;
|
||||
|
||||
class Product final : public Family::Product, public Singleton
|
||||
{
|
||||
private:
|
||||
const int32_t m_p;
|
||||
|
||||
private:
|
||||
friend const Product &Singleton::getInstance();
|
||||
Product()
|
||||
: Family::Product(
|
||||
[this](size_t value, size_t i) -> size_t {
|
||||
size_t result = (0x811C9DC5 xor i) xor static_cast<int32_t>(value);
|
||||
return static_cast<int32_t>(result * m_p);
|
||||
}
|
||||
)
|
||||
, m_p(0x01000193)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using Singleton::getInstance;
|
||||
};
|
||||
|
||||
END_NAMESPACE // FNV1a
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !FUNCTION_FNV1a_H
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef CREATOR_FUNCTION_EQUIVALENT_H
|
||||
#define CREATOR_FUNCTION_EQUIVALENT_H
|
||||
|
||||
|
||||
#include "creatorOne.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Equivalent)
|
||||
|
||||
class Creator : public One::Creator
|
||||
{
|
||||
public:
|
||||
virtual const Product &create() const override {
|
||||
return Product::getInstance();
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Equivalent
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_FUNCTION_EQUIVALENT_H
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef CREATOR_FUNCTION_ONE_H
|
||||
#define CREATOR_FUNCTION_ONE_H
|
||||
|
||||
#include "../creatorAbstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(One)
|
||||
|
||||
class Creator : public Abstract::Creator
|
||||
{
|
||||
protected:
|
||||
Creator()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual const Product &create() const = 0;
|
||||
};
|
||||
|
||||
END_NAMESPACE // One
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_FUNCTION_ONE_H
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef CREATOR_FUNCTION_STANDART_H
|
||||
#define CREATOR_FUNCTION_STANDART_H
|
||||
|
||||
#include "creatorOne.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Standart)
|
||||
|
||||
class Creator : public One::Creator
|
||||
{
|
||||
public:
|
||||
virtual const Product &create() const override {
|
||||
return Product::getInstance();
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Standart
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_FUNCTION_FNV1a_H
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef FUNCTION_EQUIVALENT_H
|
||||
#define FUNCTION_EQUIVALENT_H
|
||||
|
||||
#include "one.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Equivalent)
|
||||
|
||||
using Singleton = BusinessLogic::Pattern::Singleton<Product>;
|
||||
|
||||
class Product final : public One::Product, public Singleton
|
||||
{
|
||||
private:
|
||||
friend const Product &Singleton::getInstance();
|
||||
Product() :
|
||||
One::Product(
|
||||
[](size_t value) -> size_t {
|
||||
return value;
|
||||
}
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using Singleton::getInstance;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Equivalent
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !FUNCTION_EQUIVALENT_H
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef FUNCTION_ONE_H
|
||||
#define FUNCTION_ONE_H
|
||||
|
||||
#include "../abstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(One)
|
||||
|
||||
using function_type = std::function<size_t(size_t)>;
|
||||
|
||||
class Product : public Abstract::Product
|
||||
{
|
||||
protected:
|
||||
const function_type m_function;
|
||||
|
||||
protected:
|
||||
Product(const function_type& function) : m_function(function)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
const function_type& to_std() const {
|
||||
return m_function;
|
||||
}
|
||||
size_t getHash(size_t value) const {
|
||||
return m_function(value);
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // One
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !FUNCTION_ONE_H
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef FUNCTION_STANDART_H
|
||||
#define FUNCTION_STANDART_H
|
||||
|
||||
#include "one.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Standart)
|
||||
|
||||
using Singleton = BusinessLogic::Pattern::Singleton<Product>;
|
||||
|
||||
class Product final : public One::Product, public Singleton
|
||||
{
|
||||
private:
|
||||
std::hash<size_t> m_standartHashFunction;
|
||||
|
||||
private:
|
||||
friend const Product &Singleton::getInstance();
|
||||
Product()
|
||||
: One::Product(
|
||||
std::bind(&std::hash<size_t>::operator(), &m_standartHashFunction, std::placeholders::_1)
|
||||
)
|
||||
, m_standartHashFunction()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using Singleton::getInstance;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Standart
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !FUNCTION_FNV1a_H
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef CREATOR_ADAPTER_FAMILY_TO_ONE_H
|
||||
#define CREATOR_ADAPTER_FAMILY_TO_ONE_H
|
||||
|
||||
#include "familyToOne.h"
|
||||
#include "../One/creatorOne.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Pattern)
|
||||
BEGIN_NAMESPACE(FamilyToOne)
|
||||
|
||||
class Creator final : public One::Creator
|
||||
{
|
||||
private:
|
||||
Product m_product; // To support the interface
|
||||
|
||||
public:
|
||||
Creator(std::shared_ptr<Family::Creator> adaptee, size_t coefficient)
|
||||
: m_product(adaptee->create(), coefficient)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual const Product &create() const override {
|
||||
return m_product;
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // FamilyToOne
|
||||
END_NAMESPACE // Pattern
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_ADAPTER_FAMILY_TO_ONE_H
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef ADAPTER_FAMILY_TO_ONE_H
|
||||
#define ADAPTER_FAMILY_TO_ONE_H
|
||||
|
||||
#include "../Family/family.h"
|
||||
#include "../One/one.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Pattern)
|
||||
BEGIN_NAMESPACE(FamilyToOne)
|
||||
|
||||
class Product final : public One::Product
|
||||
{
|
||||
public:
|
||||
Product(const Family::Product &adaptee, size_t coefficient)
|
||||
: One::Product(
|
||||
std::bind(adaptee.to_std(), std::placeholders::_1, coefficient)
|
||||
)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // FamilyToOne
|
||||
END_NAMESPACE // Pattern
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !ADAPTER_FAMILY_TO_ONE_H
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef FUNCTION_ABSTRACT_H
|
||||
#define FUNCTION_ABSTRACT_H
|
||||
|
||||
#include "../../businessLogic.h"
|
||||
#include "../../Pattern/singleton.h"
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Abstract)
|
||||
|
||||
class Product
|
||||
{
|
||||
protected:
|
||||
Product()
|
||||
{
|
||||
}
|
||||
/* With the virtual destructor, the compiler considers this class to be polymorphic */
|
||||
virtual ~Product() = default;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Abstract
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !FUNCTION_ABSTRACT_H
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef CREATOR_FUNCTION_ABSTRACT_H
|
||||
#define CREATOR_FUNCTION_ABSTRACT_H
|
||||
|
||||
#include "../../businessLogic.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Function)
|
||||
BEGIN_NAMESPACE(Abstract)
|
||||
|
||||
class Creator
|
||||
{
|
||||
protected:
|
||||
Creator()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual const Product &create() const = 0;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Abstract
|
||||
END_NAMESPACE // Function
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // !CREATOR_FUNCTION_ABSTRACT_H
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef SUBSCRIBER_H
|
||||
#define SUBSCRIBER_H
|
||||
|
||||
#include "../../../businessLogic.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Table)
|
||||
BEGIN_NAMESPACE(Pattern)
|
||||
|
||||
class InterfaceSubscriber
|
||||
{
|
||||
public:
|
||||
virtual void successfulInsertion(const Table::Abstract *, const std::array<char, 5> &, std::pair<size_t, size_t>, size_t) = 0;
|
||||
virtual void unsuccessfulInsertion(const Table::Abstract *, const std::array<char, 5> &) = 0;
|
||||
};
|
||||
|
||||
class Publisher
|
||||
{
|
||||
private:
|
||||
std::vector<InterfaceSubscriber *> m_subscribers;
|
||||
|
||||
public:
|
||||
virtual void signTheObject(InterfaceSubscriber *subscriber) {
|
||||
if (subscriber not_eq nullptr) {
|
||||
m_subscribers.push_back(subscriber);
|
||||
}
|
||||
}
|
||||
virtual void unsubscribe(InterfaceSubscriber *subscriber) {
|
||||
if (subscriber not_eq nullptr) {
|
||||
m_subscribers.erase(std::find(m_subscribers.begin(), m_subscribers.end(), subscriber));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void sendSuccessfulInsertion(const Table::Abstract *sender, const std::array<char, 5> &value, std::pair<size_t, size_t> index, size_t numberOfCollisions) const {
|
||||
for (decltype(auto) currentSubscriber : m_subscribers) {
|
||||
currentSubscriber->successfulInsertion(sender, value, index, numberOfCollisions);
|
||||
}
|
||||
}
|
||||
virtual void sendUnseccessInsertion(const Table::Abstract *sender, const std::array<char, 5> &value) const {
|
||||
for (decltype(auto) currentSubscriber : m_subscribers) {
|
||||
currentSubscriber->unsuccessfulInsertion(sender, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Pattern
|
||||
END_NAMESPACE // Table
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // SUBSCRIBER_H
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef ABSTRACT_HASH_TABLE_H
|
||||
#define ABSTRACT_HASH_TABLE_H
|
||||
|
||||
#include "../../businessLogic.h"
|
||||
#include "../../Statistics/dispersion.h"
|
||||
#include "Pattern/subscriber.h"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Table)
|
||||
|
||||
class Abstract : public Pattern::Publisher
|
||||
{
|
||||
public:
|
||||
using value_type = std::array<char, 5>;
|
||||
using collision_container = BusinessLogic::Statistics::Dispersion::container_type;
|
||||
|
||||
protected: // Members
|
||||
size_t m_numberOfBuckets;
|
||||
size_t m_alphabetPower;
|
||||
BusinessLogic::Statistics::Dispersion m_dispersion;
|
||||
|
||||
protected:
|
||||
Abstract(size_t alphabetPower)
|
||||
: m_numberOfBuckets(0)
|
||||
, m_alphabetPower(alphabetPower)
|
||||
{
|
||||
}
|
||||
|
||||
Abstract(Abstract &&) = default;
|
||||
Abstract &operator=(Abstract &&) = default;
|
||||
Abstract(const Abstract &) = delete;
|
||||
Abstract &operator=(const Abstract &) = delete;
|
||||
|
||||
public:
|
||||
virtual bool isExist(const value_type &) const = 0;
|
||||
virtual size_t size() const = 0;
|
||||
virtual bool insert(const value_type &value) = 0;
|
||||
virtual double simpleUniformHashingCoefficient() const = 0;
|
||||
size_t alphabetPower() const {
|
||||
return m_alphabetPower;
|
||||
}
|
||||
size_t numberOfBuckets() const {
|
||||
return m_numberOfBuckets;
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Table
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // ABSTRACT_HASH_TABLE_H
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef CHAINS_HASH_TABLE_H
|
||||
#define CHAINS_HASH_TABLE_H
|
||||
|
||||
#include "abstract.h"
|
||||
#include "../../Convert/convert.h"
|
||||
#include "../Function/One/one.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Table)
|
||||
|
||||
class Chains final : public Abstract
|
||||
{
|
||||
public: // Types
|
||||
using container_type = std::vector<std::list<value_type>>;
|
||||
using OFP_type = Function::One::Product;
|
||||
using OFC_type = Function::One::Creator;
|
||||
|
||||
private:
|
||||
BusinessLogic::Convert::FromStdString m_toInteger;
|
||||
|
||||
public:
|
||||
container_type m_container;
|
||||
const OFP_type &m_function;
|
||||
|
||||
Chains(size_t size, const OFC_type &function, size_t alphabetPower = std::numeric_limits<char>::max())
|
||||
: Abstract(alphabetPower)
|
||||
, m_function(function.create())
|
||||
{
|
||||
if (size == 0) {
|
||||
size = 1;
|
||||
}
|
||||
/* The use of 'this' is mandatory */
|
||||
this->m_container.resize(size);
|
||||
}
|
||||
|
||||
private:
|
||||
bool isExist(const value_type &value, size_t index) const {
|
||||
const std::list<value_type> ¤tList = m_container[index];
|
||||
return std::find(currentList.cbegin(), currentList.cend(), value) not_eq currentList.cend();
|
||||
}
|
||||
|
||||
public:
|
||||
virtual bool isExist(const value_type &value) const override {
|
||||
size_t size = this->size();
|
||||
size_t index = m_function.getHash(m_toInteger(value, m_alphabetPower)) % size;
|
||||
return isExist(value, index);
|
||||
}
|
||||
auto row(size_t index) const {
|
||||
return m_container[index];
|
||||
}
|
||||
virtual size_t size() const override {
|
||||
return m_container.size();
|
||||
}
|
||||
virtual bool insert(const value_type &value) override {
|
||||
using namespace BusinessLogic::Statistics;
|
||||
|
||||
size_t index = m_function.getHash(m_toInteger(value, m_alphabetPower)) % this->size();
|
||||
if( isExist(value, index) ) {
|
||||
sendUnseccessInsertion(this, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// List does not need a reserve
|
||||
m_container[index].push_back(value);
|
||||
}
|
||||
catch (const std::bad_alloc &) {
|
||||
sendUnseccessInsertion(this, value);
|
||||
return false;
|
||||
}
|
||||
++m_numberOfBuckets;
|
||||
|
||||
size_t listLength = m_container[index].size();
|
||||
sendSuccessfulInsertion(this, value, std::make_pair(index, listLength - 1), listLength - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
virtual double simpleUniformHashingCoefficient() const override {
|
||||
size_t size = this->size();
|
||||
collision_container container(size);
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
container[i] = m_container[i].size();
|
||||
}
|
||||
return m_dispersion(container, size);
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Table
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // CHAINS_HASH_TABLE_H
|
||||
@@ -0,0 +1,82 @@
|
||||
#ifndef DIRECT_ADRESS_HASH_TABLE_H
|
||||
#define DIRECT_ADRESS_HASH_TABLE_H
|
||||
|
||||
#include "../Factory/abstract.h"
|
||||
#include "abstract.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Hash)
|
||||
BEGIN_NAMESPACE(Table)
|
||||
|
||||
class OpenAddressing final : public Abstract
|
||||
{
|
||||
public: // Types
|
||||
using container_type = std::vector<value_type>;
|
||||
using factory_type = Factory::Abstract;
|
||||
|
||||
private:
|
||||
using sample_type = BusinessLogic::Statistics::Dispersion::container_type;
|
||||
|
||||
private:
|
||||
friend factory_type::AAP_type;
|
||||
container_type m_container;
|
||||
collision_container m_numberOfCollision;
|
||||
std::unique_ptr<Algorithm::Abstract::Product> m_algorithm;
|
||||
|
||||
public:
|
||||
OpenAddressing(size_t size, const factory_type &factory, size_t alphabetPower = std::numeric_limits<char>::max())
|
||||
: Abstract(alphabetPower)
|
||||
, m_numberOfCollision(size, std::numeric_limits<size_t>::max())
|
||||
, m_algorithm(factory.getAlgorithm())
|
||||
{
|
||||
constexpr std::array<char, 5> nullValue = {'\0', '\0', '\0', '\0', '\0'};
|
||||
m_container.resize(size, nullValue);
|
||||
m_algorithm->setTable(&m_container);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual bool isExist(const value_type &value) const override {
|
||||
size_t numberOfCollisions = 0;
|
||||
size_t index = (*m_algorithm).getIndex(value, numberOfCollisions, m_alphabetPower);
|
||||
return ( index != std::numeric_limits<size_t>::max() )
|
||||
|| ( (m_container.begin() + index).operator*() == value );
|
||||
}
|
||||
virtual size_t size() const override {
|
||||
return m_container.size();
|
||||
}
|
||||
virtual bool insert(const value_type &value) override {
|
||||
using namespace BusinessLogic::Statistics;
|
||||
|
||||
size_t size = m_container.size();
|
||||
if ( m_numberOfBuckets == size) {
|
||||
sendUnseccessInsertion(this, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t numberOfCollisions = 0;
|
||||
size_t index = (*m_algorithm).getIndex(value, numberOfCollisions, m_alphabetPower);
|
||||
if (index == std::numeric_limits<size_t>::max()
|
||||
|| (m_container.begin() + index).operator*() == value
|
||||
) {
|
||||
sendUnseccessInsertion(this, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_container[index] = value;
|
||||
m_numberOfCollision[m_numberOfBuckets] = numberOfCollisions;
|
||||
++m_numberOfBuckets;
|
||||
|
||||
sendSuccessfulInsertion(this, value, std::make_pair(index, 0), numberOfCollisions);
|
||||
|
||||
return true;
|
||||
}
|
||||
virtual double simpleUniformHashingCoefficient() const override {
|
||||
return m_dispersion(m_numberOfCollision, m_numberOfBuckets);
|
||||
}
|
||||
};
|
||||
|
||||
END_NAMESPACE // Table
|
||||
END_NAMESPACE // Hash
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // DIRECT_ADRESS_HASH_TABLE_H
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef SINGLETON_H
|
||||
#define SINGLETON_H
|
||||
|
||||
#include "../businessLogic.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Pattern)
|
||||
|
||||
template <typename T>
|
||||
class Singleton {
|
||||
private:
|
||||
static std::unique_ptr<T> m_singleton;
|
||||
|
||||
public:
|
||||
static const T &getInstance() {
|
||||
if (m_singleton == nullptr) {
|
||||
m_singleton = std::unique_ptr<T>(new T);
|
||||
}
|
||||
return m_singleton.operator*();
|
||||
}
|
||||
|
||||
Singleton() = default;
|
||||
Singleton(const Singleton &) = delete;
|
||||
Singleton(Singleton &&) = delete;
|
||||
Singleton &operator=(const Singleton &) = delete;
|
||||
Singleton &operator=(Singleton &&) = delete;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::unique_ptr<T> Singleton<T>::m_singleton = nullptr;
|
||||
|
||||
END_NAMESPACE // Pattern
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // SINGLETON_H
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "dispersion.h"
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Statistics)
|
||||
|
||||
long double Dispersion::operator()(const container_type &container, size_t size) const {
|
||||
long double average = 0;
|
||||
long double averageOfSquares = 0;
|
||||
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
average += ( container[i] ) / static_cast<long double>(size);
|
||||
averageOfSquares += ( container[i] ) * ( container[i] ) / static_cast<long double>(size);
|
||||
}
|
||||
return averageOfSquares - average * average;
|
||||
}
|
||||
|
||||
END_NAMESPACE // Statistics
|
||||
END_NAMESPACE // BusinessLogic
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef DISPERSION_H
|
||||
#define DISPERSION_H
|
||||
|
||||
#include "../businessLogic.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
BEGIN_NAMESPACE(BusinessLogic)
|
||||
BEGIN_NAMESPACE(Statistics)
|
||||
|
||||
class Dispersion {
|
||||
public: // Types
|
||||
using value_type = size_t;
|
||||
using container_type = std::vector<value_type>;
|
||||
|
||||
public:
|
||||
long double operator()(const container_type &container, size_t size) const;
|
||||
};
|
||||
|
||||
END_NAMESPACE // Statistics
|
||||
END_NAMESPACE // BusinessLogic
|
||||
|
||||
#endif // DISPERSION_H
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifndef BUSINESS_LOGIC_H
|
||||
#define BUSINESS_LOGIC_H
|
||||
|
||||
/* Opening bracket */
|
||||
#define OPEN {
|
||||
|
||||
/* Closing bracket */
|
||||
#define CLOSE }
|
||||
|
||||
/* Begin of namespace */
|
||||
#define BEGIN_NAMESPACE(name) \
|
||||
namespace name OPEN
|
||||
|
||||
/* Begin of namespace */
|
||||
#define END_NAMESPACE \
|
||||
CLOSE
|
||||
|
||||
/* Declaring classes of factory method */
|
||||
#define DFM_TYPES \
|
||||
class Product; \
|
||||
class Creator;
|
||||
|
||||
/* Factory method namespace declaration */
|
||||
#define DFM_NAMESPACE(name) \
|
||||
BEGIN_NAMESPACE(name) \
|
||||
DFM_TYPES \
|
||||
END_NAMESPACE
|
||||
|
||||
/* Factory method base cod declaration */
|
||||
#define DFM_BASE \
|
||||
DFM_NAMESPACE(Abstract) \
|
||||
DFM_NAMESPACE(One) \
|
||||
DFM_NAMESPACE(Family)
|
||||
|
||||
namespace BusinessLogic
|
||||
{
|
||||
namespace Hash
|
||||
{
|
||||
namespace Function
|
||||
{
|
||||
DFM_BASE
|
||||
DFM_NAMESPACE(FNV1a)
|
||||
DFM_NAMESPACE(Standart)
|
||||
DFM_NAMESPACE(Equivalent)
|
||||
|
||||
namespace Pattern
|
||||
{
|
||||
DFM_NAMESPACE(FamilyToOne)
|
||||
}
|
||||
}
|
||||
|
||||
namespace Algorithm
|
||||
{
|
||||
DFM_BASE
|
||||
DFM_NAMESPACE(LinearProbing)
|
||||
DFM_NAMESPACE(QuadraticProbing)
|
||||
DFM_NAMESPACE(PseudorandomProbing)
|
||||
DFM_NAMESPACE(DoubleHashing)
|
||||
}
|
||||
|
||||
namespace Factory
|
||||
{
|
||||
class Abstract;
|
||||
class One;
|
||||
class Family;
|
||||
}
|
||||
|
||||
namespace Table /* Only string data */
|
||||
{
|
||||
class Abstract;
|
||||
|
||||
class OpenAddressing; // Direct address hash function
|
||||
|
||||
class Chains; // Hash function implemented by the chain method
|
||||
|
||||
namespace Pattern
|
||||
{
|
||||
class InterfaceSubscriber;
|
||||
|
||||
class Publisher;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Pattern // Can be used for different classes
|
||||
{
|
||||
template<typename T>
|
||||
class Singleton;
|
||||
}
|
||||
|
||||
namespace Convert
|
||||
{
|
||||
class FromStdString;
|
||||
}
|
||||
|
||||
namespace Statistics
|
||||
{
|
||||
class Dispersion;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BUSINESS_LOGIC_H
|
||||
@@ -0,0 +1,197 @@
|
||||
#include "hashHeaderFiles.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include <initializer_list>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
|
||||
#include "Convert/convert.h"
|
||||
|
||||
using namespace BusinessLogic::Hash;
|
||||
using namespace Function::Pattern;
|
||||
using namespace Table::Pattern;
|
||||
|
||||
using factory_ptr = std::shared_ptr<const Factory::Abstract>;
|
||||
|
||||
class Subscriber : public InterfaceSubscriber {
|
||||
private:
|
||||
clock_t m_time;
|
||||
size_t m_maxCollision;
|
||||
size_t m_numberOfSuccesses;
|
||||
size_t m_numberOfFailures;
|
||||
size_t m_target;
|
||||
long double m_lastCoefficients;
|
||||
|
||||
public:
|
||||
Subscriber(size_t target)
|
||||
: m_maxCollision(0)
|
||||
, m_numberOfSuccesses(0)
|
||||
, m_numberOfFailures(0)
|
||||
, m_target(target)
|
||||
, m_lastCoefficients(0)
|
||||
{
|
||||
}
|
||||
|
||||
void startTime() {
|
||||
m_time = clock();
|
||||
}
|
||||
void endTime() {
|
||||
m_time = clock() - m_time;
|
||||
}
|
||||
double lastCoefficient() const {
|
||||
return m_lastCoefficients;
|
||||
}
|
||||
double workingTime() const {
|
||||
return m_time / static_cast<double>(CLOCKS_PER_SEC);
|
||||
}
|
||||
size_t maxCollision() const {
|
||||
return m_maxCollision;
|
||||
}
|
||||
auto numberOfSuccesses() const {
|
||||
return m_numberOfSuccesses;
|
||||
}
|
||||
auto numberOfFailures() const {
|
||||
return m_numberOfFailures;
|
||||
}
|
||||
|
||||
virtual void successfulInsertion(const Table::Abstract *table, const std::array<char, 5> &, std::pair<size_t, size_t>, size_t numberOfCollisions) override {
|
||||
m_maxCollision = {
|
||||
numberOfCollisions > m_maxCollision
|
||||
? numberOfCollisions
|
||||
: m_maxCollision
|
||||
};
|
||||
++m_numberOfSuccesses;
|
||||
|
||||
if(m_numberOfSuccesses + m_numberOfFailures >= m_target) {
|
||||
m_lastCoefficients = table->simpleUniformHashingCoefficient();
|
||||
}
|
||||
}
|
||||
virtual void unsuccessfulInsertion(const Table::Abstract *, const std::array<char, 5> &) override {
|
||||
++m_numberOfFailures;
|
||||
}
|
||||
virtual void filledInPart(const Table::Abstract *) override {
|
||||
m_lastCoefficients = 0;
|
||||
}
|
||||
};
|
||||
|
||||
void runTable(std::unique_ptr<Table::Abstract> table, size_t target) {
|
||||
/* 26 letters */
|
||||
constexpr char firstChar = ' ';
|
||||
constexpr char endChar = '~';
|
||||
size_t progress = 0;
|
||||
std::array<char, 5> currentString = { ' ', ' ', ' ', ' ', ' ' };
|
||||
|
||||
bool continueFlag = true;
|
||||
while (continueFlag) {
|
||||
if (++progress > target || not table->insert(currentString)) {
|
||||
continueFlag = false;
|
||||
}
|
||||
|
||||
currentString[4] < endChar ? ++currentString[4]
|
||||
: (currentString[4] = firstChar, currentString[3] < endChar) ? ++currentString[3]
|
||||
: (currentString[3] = firstChar, currentString[2] < endChar) ? ++currentString[2]
|
||||
: (currentString[2] = firstChar, currentString[1] < endChar) ? ++currentString[1]
|
||||
: (currentString[1] = firstChar, currentString[0] < endChar) ? ++currentString[0]
|
||||
: (continueFlag = false);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char **/*argv*/)
|
||||
{
|
||||
auto fnv1a = std::make_shared<Function::FNV1a::Creator>();
|
||||
auto equivalent = std::make_shared<Function::Equivalent::Creator>();
|
||||
auto standart = std::make_shared<Function::Standart::Creator>();
|
||||
|
||||
auto doubleHashing = std::make_shared<Algorithm::DoubleHashing::Creator>(0, 1);
|
||||
auto pseudorandomProbing = std::make_shared<Algorithm::PseudorandomProbing::Creator>(0);
|
||||
auto linearProbing = std::make_shared<Algorithm::LinearProbing::Creator>();
|
||||
auto quadraticProbing = std::make_shared<Algorithm::QuadraticProbing::Creator>();
|
||||
|
||||
/* First Hash Function has a number 0, second - 1 */
|
||||
const Factory::Abstract &fac1 { Factory::Family(fnv1a, doubleHashing) };
|
||||
const Factory::Abstract &fac2 { Factory::Family(fnv1a, pseudorandomProbing) };
|
||||
const Factory::Abstract &fac3 { Factory::One(equivalent, linearProbing) };
|
||||
const Factory::Abstract &fac4 { Factory::One(equivalent, quadraticProbing) };
|
||||
const Factory::Abstract &fac5 { Factory::One(standart, linearProbing) };
|
||||
const Factory::Abstract &fac6 { Factory::One(standart, quadraticProbing) };
|
||||
|
||||
auto simpleFNV1a = std::make_shared<FamilyToOne::Creator>(fnv1a, 0);
|
||||
const Factory::Abstract &fac7 { Factory::One(simpleFNV1a, linearProbing) };
|
||||
const Factory::Abstract &fac8 { Factory::One(simpleFNV1a, quadraticProbing) };
|
||||
|
||||
/* 0x5 == 0b0101 */
|
||||
auto complicatedFNV1a = std::make_shared<FamilyToOne::Creator>(fnv1a, 0x55555555);
|
||||
const Factory::Abstract &fac9 { Factory::One(complicatedFNV1a, linearProbing) };
|
||||
const Factory::Abstract &fac10 { Factory::One(complicatedFNV1a, quadraticProbing) };
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
constexpr size_t numberOfInserts = (
|
||||
//11
|
||||
//101
|
||||
//5'003
|
||||
//50'021
|
||||
//230'003
|
||||
//456'959
|
||||
//1'000'003
|
||||
//5'000'011
|
||||
//10'000'019
|
||||
10'000'019
|
||||
); // Must be simple - max is 10'371'957'246
|
||||
|
||||
constexpr size_t quantityOfTables = 14;
|
||||
constexpr size_t numberOfBins = numberOfInserts / 10;
|
||||
constexpr size_t alphabetPower = '~' - ' ' + 1;
|
||||
constexpr double alpha = 0.9;
|
||||
|
||||
std::array<std::shared_ptr<Subscriber>, quantityOfTables> results;
|
||||
for(std::shared_ptr<Subscriber> ¤t : results) {
|
||||
current = std::make_shared<Subscriber>(static_cast<size_t>(numberOfInserts * alpha));
|
||||
}
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
|
||||
|
||||
std::array<std::unique_ptr<Table::Abstract>, quantityOfTables> tables {
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac1, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac2, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac3, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac4, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac5, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac6, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac7, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac8, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac9, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::OpenAddressing(numberOfInserts, fac10, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::Chains (numberOfBins, *equivalent, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::Chains (numberOfBins, *standart, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::Chains (numberOfBins, *simpleFNV1a, alphabetPower) ),
|
||||
std::unique_ptr<Table::Abstract>( new Table::Chains (numberOfBins, *complicatedFNV1a, alphabetPower) )
|
||||
};
|
||||
|
||||
std::cout << std::fixed;
|
||||
std::cout.precision(10);
|
||||
std::cout << "START!" << std::endl;
|
||||
for(size_t i = 0; i < quantityOfTables; ++i) {
|
||||
tables[i]->signTheObject( &results[i].operator*() );
|
||||
results[i]->startTime();
|
||||
runTable(std::move(tables[i]), numberOfInserts * alpha);
|
||||
results[i]->endTime();
|
||||
|
||||
std::cout
|
||||
<< results[i]->maxCollision() << ' '
|
||||
<< std::sqrt(results[i]->lastCoefficient()) << ' '
|
||||
<< results[i]->numberOfSuccesses() << '/'
|
||||
<< alpha << '/'
|
||||
<< numberOfInserts << ' '
|
||||
<< results[i]->workingTime() << std::endl;
|
||||
}
|
||||
std::cout << "END!" << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef HASH_HEADER_FILES_H
|
||||
#define HASH_HEADER_FILES_H
|
||||
|
||||
#include "Statistics/dispersion.h"
|
||||
|
||||
#include "Hash/Algorithm/One/linearProbing.h"
|
||||
#include "Hash/Algorithm/One/quadraticProbing.h"
|
||||
#include "Hash/Algorithm/Family/pseudorandomProbing.h"
|
||||
#include "Hash/Algorithm/Family/doubleHashing.h"
|
||||
|
||||
#include "Hash/Function/Family/fnv1a.h"
|
||||
#include "Hash/Function/One/standart.h"
|
||||
#include "Hash/Function/One/equivalent.h"
|
||||
#include "Hash/Function/Pattern/familyToOne.h"
|
||||
|
||||
#include "Hash/Algorithm/One/creatorLinearProbing.h"
|
||||
#include "Hash/Algorithm/One/creatorQuadraticProbing.h"
|
||||
#include "Hash/Algorithm/Family/creatorPseudorandomProbing.h"
|
||||
#include "Hash/Algorithm/Family/creatorDoubleHashing.h"
|
||||
|
||||
#include "Hash/Function/Family/creatorFnv1a.h"
|
||||
#include "Hash/Function/One/creatorStandart.h"
|
||||
#include "Hash/Function/One/creatorEquivalent.h"
|
||||
#include "Hash/Function/Pattern/creatorFamilyToOne.h"
|
||||
|
||||
#include "Hash/Factory/one.h"
|
||||
#include "Hash/Factory/family.h"
|
||||
|
||||
#include "Hash/Table/chains.h"
|
||||
#include "Hash/Table/openAddress.h"
|
||||
|
||||
#endif // HASH_HEADER_FILES_H
|
||||
|
After Width: | Height: | Size: 143 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,84 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Demonstration</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 style="text-align: center">Руководство пользователя</h2>
|
||||
<h3 style="text-align: center">Система демонстрации</h3>
|
||||
<p style="text-align: justify">
|
||||
Данный раздел - описание существующих возможностей взаимодействия с
|
||||
системой демонстрации изученного материала.<br />
|
||||
На рисунке 3.1 виден весь основной интерфейс пользователя, необходимый для
|
||||
полноценного комфортного взаимодействия с данной системой.
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="demonstration.png" />
|
||||
<p style="text-align: center">
|
||||
Рисунок 2.1 - система демонстрации вставки элемента в хеш-таблицу
|
||||
</p>
|
||||
</div>
|
||||
<p style="text-align: justify">
|
||||
Каждая цифра указывает на определённый интерфейс пользователя, где даётся
|
||||
его описание:
|
||||
</p>
|
||||
<ol>
|
||||
<li style="text-align: justify">
|
||||
Табличное представление модели, которое заполняется ранее
|
||||
вставленными в хеш-таблицу элементами в порядке их хранения в самой
|
||||
хей-таблице.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
График, показывающий тенденцию изменения коэффициента простого
|
||||
равномерного хеширования на протяжении процесса вставки элементов в
|
||||
хеш-таблицу.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
График, показывающий тенденцию изменения количества коллизий на
|
||||
протяжении процесса вставки элементов в хеш-таблицу.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Группирующий блок, позволяющий изменять способ решения проблем
|
||||
коллизий хеш-таблицы.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Группирующий блок, позволяющий изменять применяемую в процессе вставки
|
||||
элемента хеш-функцию.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Группирующий блок, позволяющий изменять применяемую в процессе вставки
|
||||
элемента алгоритм, применяемый в попытке решения колизии на основе
|
||||
таблицы с открытой адрессацией.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Сгруппированный интерфейс, позволяющий создать новую хеш-таблицу с
|
||||
указанием размера первоначального контейнера, сбросить действительную
|
||||
хеш-таблицу, запросить последнюю статистику по операциям вставки
|
||||
элементов
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Сгруппированный интерфейс, позволяющий создавать инструкции по вставке
|
||||
новых элементов в хеш таблицу несколькими способами: n-ое количество
|
||||
элементов разных элементов и один единственный, где задаётся первый
|
||||
элемент. Так же существует возможность поиска первого несуществующего
|
||||
элемента хеш-таблице, остановки процесса вставки элементов в
|
||||
хеш-таблцицу, фокусирования графиков для полного отображения информации.
|
||||
Каждая функция соответствует своей кнопке данного сгруппированного
|
||||
интерфейса.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Вывод информации о действиях пользователя и результатах хеширования
|
||||
элементов.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Масштабирование всех видов, вплоть до освобождения места для
|
||||
определённого вида с целью его более детального рассмотрения.
|
||||
Существвует возможность полного масштабирования одного вида, взамен
|
||||
скрытия всех остальных.
|
||||
</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Main</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 style="text-align: center">Руководство пользователя</h2>
|
||||
<h3 style="text-align: center">
|
||||
Предоставление помощи пользователю<br />
|
||||
в использовании демонстрационной программы:<br />
|
||||
"Алгоритм вставки в хеш-таблицу"
|
||||
</h3>
|
||||
<p style="text-align: justify;">
|
||||
Данное руководство предназначено пользователю для лучшего понимания работы
|
||||
программы и взаимодействия с ней.
|
||||
</p>
|
||||
<p>Оглавление:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<a href="theoryPage.html">Раздел теории</a>
|
||||
<ul>
|
||||
<li><a href="theory.html">Теория</a></li>
|
||||
<li><a href="demonstration.html">Демонстрация</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="testingPage.html">Раздел тестирования</a></li>
|
||||
<li><a href="menubar.html">Полоса или строка меню</a></li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Menubar</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 style="text-align: center">Руководство пользователя</h2>
|
||||
<h3 style="text-align: center">Полоска или строка меню</h3>
|
||||
<p style="text-align: justify">
|
||||
Данный раздел - описание существующих возможностей взаимодействия с
|
||||
посолкой или строкой меню данной программы.<br />
|
||||
На рисунке 5.1 и 5.2 отображены подменю, каждое из которых группирует
|
||||
определённые действия.
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="menubarFirst.png" />
|
||||
<p style="text-align: center">
|
||||
Рисунок 5.1 - подменю выбора текущего раздела
|
||||
</p>
|
||||
<p style="text-align: center">
|
||||
<img src="menubarSecond.png" />
|
||||
</p>
|
||||
<p>Рисунок 5.2 - подменю предоставления помощи</p>
|
||||
</div>
|
||||
<p style="text-align: justify">
|
||||
<span style="text-align: center"
|
||||
>Первое подменю (см. рис. 5.1) необходимо для переключения разделов -
|
||||
раздел теории, который включает две системы (система теории и система
|
||||
демонстрации) и раздел тестирования.</span
|
||||
>
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Каждая цифра указывает на определённый интерфейс пользователя, где даётся
|
||||
его описание:
|
||||
</p>
|
||||
<ol>
|
||||
<li style="text-align: justify">
|
||||
Действие подменю, необходимое для переключения вида на раздел теории.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Действие подменю, необходимое для переключения вида на раздел практики.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Действие подменю, необходимое для открытия модального диалогового окна -
|
||||
руководства пользователя.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Действие подменю, необходимое для открытия модального диалогового окна,
|
||||
которое содержит информацию об использующимся программой фреймворке
|
||||
Qt.
|
||||
</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PracticPage</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 style="text-align: center">Руководство пользователя</h2>
|
||||
<h3 style="text-align: center">Система тестирования</h3>
|
||||
<p style="text-align: justify">
|
||||
Данный раздел - описание существующих возможностей взаимодействия с
|
||||
системой тестирования.<br />
|
||||
На рисунке 4.1 виден весь основной интерфейс пользователя, необходимый для
|
||||
полноценного комфортного взаимодействия с данной системой.
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="testingPage.html" />
|
||||
<p style="text-align: center">Рисунок 4.1 - система тестирования</p>
|
||||
</div>
|
||||
<p style="text-align: justify">
|
||||
Каждая цифра указывает на определённый интерфейс пользователя, где даётся
|
||||
его описание:
|
||||
</p>
|
||||
<ol>
|
||||
<li style="text-align: justify">
|
||||
Отображаемый текст, как текущий вопрос с описанием ввода правильного
|
||||
ответа и самого тестового задания.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Панель ввода правильного ответа. Может представлять
|
||||
определённое количество флагов для указания множественного
|
||||
ответа из множества альтернатив (от 5-и до 9-и), поле ввода целого
|
||||
числа или числа с плавающей точкой.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Нажимная кнопка для подтверждения ответа и проверки его на корректность.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Выходная информация, как способ идентификации успешного / безуспешного
|
||||
начала тестирования с указанием конкретной ошибки, завершения
|
||||
тестирования и успешного / безуспешного ответа на предыдущий вопрос.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Нажимная кнопка, реализующая начало тестирования.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Нажимная кнопка, реализующая предварительное завершение тестирования.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Группирующий интерфейс необходимый для выбора типа предоставляемых
|
||||
вопросов в процессе тестирования.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Группирующий интерфейс необходимый для выбора сложности
|
||||
предоставляемых вопросов в процессе тестирования.
|
||||
</li>
|
||||
</ol>
|
||||
<p style="text-align: justify">
|
||||
Стоит отметить, что результат тестирования сохраняется в бинарном файле
|
||||
(формат записи смотри в технической документации), когда тестирование
|
||||
завершается после окончания подходящих под критерии вопросов или решения
|
||||
пользователя, при нажатии соответствующей кнопки.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Theory</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 style="text-align: center">Руководство пользователя</h2>
|
||||
<h3 style="text-align: center">Система теории</h3>
|
||||
<p style="text-align: justify">
|
||||
Данный раздел - описание существующих возможностей взаимодействия с
|
||||
системой изучения теоретического материала.<br />
|
||||
На рисунке 2.1 виден весь основной интерфейс пользователя, необходимый для
|
||||
полноценного комфортного взаимодействия с данной системой.
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="theory.png" />
|
||||
<p style="text-align: center">
|
||||
Рисунок 2.1 - система изучения теоретического материала
|
||||
</p>
|
||||
</div>
|
||||
<p style="text-align: justify">
|
||||
Каждая цифра указывает на определённый интерфейс пользователя, где даётся
|
||||
его описание:
|
||||
</p>
|
||||
<ol>
|
||||
<li style="text-align: justify">
|
||||
Нажимная кнопка, при нажатии которой пользователь переходит на следующую
|
||||
страницу теоретического материала. Доступна, если отображается не
|
||||
главная и не последняя страницы.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Нажимная кнопка, при нажатии которой пользователь переходит на главную
|
||||
страницу теоретического материала. Доступна, если не отображается
|
||||
главная страница.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Нажимная кнопка, при нажатии которой пользователь переходит на
|
||||
предыдущую страницу теоретического материала. Доступна, если
|
||||
отображается не главная и не первая страницы.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Нажимная кнопка, позволяющая отобразить предыдущую небольшую
|
||||
доступную часть отображаемой страницы.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Ползунок, при перемещении которого можно перейти к любой части
|
||||
отображаемой страницы.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Нажимная кнопка, позволяющая отобразить следующую небольшую
|
||||
доступную часть отображаемой страницы.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Гиперссылка оглавления, при нажатии на которую пользователь может
|
||||
перейти к любой интересующей его теме, которая описывается в отдельной
|
||||
страцице.
|
||||
</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>TheoryPage</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 style="text-align: center">Руководство пользователя</h2>
|
||||
<h3 style="text-align: center">Раздел теории</h3>
|
||||
<p style="text-align: justify">
|
||||
Данный раздел - первое, что видит пользователь, при первом запуске
|
||||
программы.<br />
|
||||
На рисунке 1.1 виден весь основной интерфейс пользователя, необходимый для
|
||||
перехода в ту или иную систему.
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="theoryPage.png"/>
|
||||
<p style="text-align: center">Рисунок 1.1 - раздел теории и практики</p>
|
||||
</div>
|
||||
<p>Всего существует три системы:</p>
|
||||
<ul>
|
||||
<li style="text-align: justify">Теории.</li>
|
||||
<li style="text-align: justify">Демонстрации.</li>
|
||||
<li style="text-align: justify">Тестирования.</li>
|
||||
</ul>
|
||||
<p style="text-align: justify">
|
||||
Основой графического интерфейса пользователя являются нажимаемые кнопки,
|
||||
переключающие между собой вкладки, флажки множественного или одиночного
|
||||
выборов, и другие элементы, которые будут обсуждаться по мере описания
|
||||
данного руководства. Каждая цифра указывает на определённый интерфейс
|
||||
пользователя, где даётся его описание:
|
||||
</p>
|
||||
<ol>
|
||||
<li style="text-align: justify">
|
||||
Раздел изучения теоретического материала, необходимый для понимания темы
|
||||
"Алгоритм вставки элемента в хеш-таблицу".
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Раздел демонстрации вставки элемента в хеш-таблицу.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Полоса или строка меню, как единственный способ переключения фокуса
|
||||
между системами теории, которая подразумевает включение системы
|
||||
демонстрации, и тестирования.
|
||||
</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<info>
|
||||
<directory>:/ManualHTML/Pages</directory>
|
||||
<directory>:/ManualHTML/Images</directory>
|
||||
<order>
|
||||
<page>main.html</page>
|
||||
<page>theoryPage.html</page>
|
||||
<page>theory.html</page>
|
||||
<page>demonstration.html</page>
|
||||
<page>testingPage.html</page>
|
||||
<page>menubar.html</page>
|
||||
</order>
|
||||
</info>
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef LATIN_VALIDATOR_H
|
||||
#define LATIN_VALIDATOR_H
|
||||
|
||||
#include <QValidator>
|
||||
|
||||
class LatinValidator : public QValidator {
|
||||
public:
|
||||
LatinValidator(QObject *parent) : QValidator(parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual State validate(QString& str, int&) const override {
|
||||
QRegExp rxp = QRegExp("[!-~]*");
|
||||
if (str.contains(rxp)) {
|
||||
return Acceptable;
|
||||
}
|
||||
return Invalid;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LATIN_VALIDATOR_H
|
||||
@@ -0,0 +1,564 @@
|
||||
#include "demonstrationWidget.h"
|
||||
|
||||
inline void DemonstrationWidget::TableInformation::clear() {
|
||||
for (size_t *value :
|
||||
{&m_maxCollision, &m_numberOfSuccesses, &m_numberOfFailures}) {
|
||||
*value = 0;
|
||||
}
|
||||
for (double *value : {&m_lastCoefficient, &m_maxCoefficient}) {
|
||||
*value = 0;
|
||||
}
|
||||
for (auto *series : {m_pSeriesNumberOfCollisions}) {
|
||||
series->removePoints(0, series->count());
|
||||
}
|
||||
m_pSeriesNumberOfCollisions->append(0, 0);
|
||||
|
||||
m_lastCoord = {0, 0};
|
||||
m_lastValue = {'\0', '\0', '\0', '\0', '\0'};
|
||||
m_lastInsertion = false;
|
||||
}
|
||||
|
||||
DemonstrationWidget::DemonstrationWidget(QWidget *pWidget)
|
||||
: QWidget(pWidget),
|
||||
m_pChartCollisionsView(new QChartView(new QChart, this)),
|
||||
m_pStandardModel(nullptr), m_stop(false), m_pFunction(nullptr),
|
||||
m_complicatedFunction(nullptr), m_pAlgorithm(nullptr),
|
||||
m_alphabetPower(endChar - firstChar + 1), m_pTable(nullptr),
|
||||
m_tableInformation(new QLineSeries(m_pChartCollisionsView->chart())) {
|
||||
setupUi(dynamic_cast<QWidget *>(this));
|
||||
|
||||
m_tableView->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::ResizeToContents);
|
||||
QGridLayout *gridLayout = new QGridLayout;
|
||||
|
||||
/*
|
||||
* Сhart
|
||||
*/
|
||||
|
||||
auto *axisX = new QValueAxis();
|
||||
auto *axisY = new QValueAxis();
|
||||
axisX->setTickCount(20);
|
||||
axisY->setTickCount(10);
|
||||
axisX->setRange(1, 2);
|
||||
axisY->setRange(0, 1);
|
||||
|
||||
QChart *chartCollision = m_pChartCollisionsView->chart();
|
||||
chartCollision->setTitle("Graph of collision changes");
|
||||
chartCollision->legend()->hide();
|
||||
chartCollision->addAxis(axisX, Qt::AlignBottom);
|
||||
chartCollision->addAxis(axisY, Qt::AlignLeft);
|
||||
chartCollision->addSeries(m_tableInformation.m_pSeriesNumberOfCollisions);
|
||||
m_tableInformation.m_pSeriesNumberOfCollisions->attachAxis(axisX);
|
||||
m_tableInformation.m_pSeriesNumberOfCollisions->attachAxis(axisY);
|
||||
|
||||
/*
|
||||
* View(-s)
|
||||
*/
|
||||
|
||||
m_pChartCollisionsView->installEventFilter(this);
|
||||
m_pChartCollisionsView->setRubberBand(QChartView::RectangleRubberBand);
|
||||
m_pChartCollisionsView->setRenderHint(QPainter::Antialiasing);
|
||||
m_pChartCollisionsView->setMinimumHeight(m_tableView->minimumHeight());
|
||||
m_pChartCollisionsView->setMinimumWidth(m_tableView->minimumWidth());
|
||||
|
||||
/*
|
||||
* Splitter
|
||||
*/
|
||||
|
||||
QSplitter *splitter = new QSplitter(Qt::Vertical);
|
||||
splitter->addWidget(m_tableView);
|
||||
splitter->addWidget(m_pChartCollisionsView);
|
||||
|
||||
gridLayout->addWidget(splitter, 0, 0, 1, 1);
|
||||
gridLayout->addWidget(m_rightScrollArea, 0, 1, 1, 1);
|
||||
gridLayout->addWidget(m_frmProgressBar, 1, 0, 1, 2);
|
||||
setLayout(gridLayout);
|
||||
|
||||
/*
|
||||
* Validator and HTML theory
|
||||
*/
|
||||
|
||||
m_leFrom->setValidator(new LatinValidator(m_leFrom));
|
||||
m_leInsert->setValidator(new LatinValidator(m_leInsert));
|
||||
|
||||
/*
|
||||
* Signal & slots
|
||||
*/
|
||||
|
||||
connect(m_pbReset, &QPushButton::clicked, this,
|
||||
&DemonstrationWidget::slotClickedReset);
|
||||
connect(m_pbApply, &QPushButton::clicked, this,
|
||||
&DemonstrationWidget::slotClickedApply);
|
||||
connect(m_pbStatistics, &QPushButton::clicked, this,
|
||||
&DemonstrationWidget::slotClickedStatistics);
|
||||
connect(m_pbMakeItems, &QPushButton::clicked, this,
|
||||
&DemonstrationWidget::slotClickedMakeItems);
|
||||
connect(m_pbInsert, &QPushButton::clicked, this,
|
||||
&DemonstrationWidget::slotClickedInsert);
|
||||
connect(m_pbFindFree, &QPushButton::clicked, this,
|
||||
&DemonstrationWidget::slotClickedFindFree);
|
||||
connect(m_pbStop, &QPushButton::clicked, this,
|
||||
&DemonstrationWidget::slotClickedStop);
|
||||
connect(m_pbFocus, &QPushButton::clicked, this,
|
||||
&DemonstrationWidget::slotClickedFocus);
|
||||
|
||||
connect(m_rbFNV1a32bit, &QRadioButton::toggled, this,
|
||||
&DemonstrationWidget::slotUpdateAdditionalInputData);
|
||||
connect(m_rbPseudorandomProbing, &QRadioButton::toggled, this,
|
||||
&DemonstrationWidget::slotUpdateAdditionalInputData);
|
||||
connect(m_rbDoubleHashing, &QRadioButton::toggled, this,
|
||||
&DemonstrationWidget::slotUpdateAdditionalInputData);
|
||||
connect(m_rbChains, &QRadioButton::toggled, this,
|
||||
&DemonstrationWidget::slotUpdateAdditionalInputData);
|
||||
|
||||
/*
|
||||
* GUI
|
||||
*/
|
||||
m_frmProgressBar->hide();
|
||||
m_frmFirstInputData->hide();
|
||||
m_frmSecondInputData->hide();
|
||||
m_gbInputData->hide();
|
||||
}
|
||||
|
||||
/*
|
||||
* Inserting elements
|
||||
*/
|
||||
|
||||
void DemonstrationWidget::successfulInsertion(const table_type *,
|
||||
const value_type &value,
|
||||
std::pair<size_t, size_t> index,
|
||||
size_t numberOfCollisions) {
|
||||
m_tableInformation.m_lastCoord = index;
|
||||
m_tableInformation.m_lastValue = value;
|
||||
m_tableInformation.m_lastInsertion = true;
|
||||
++m_tableInformation.m_numberOfSuccesses;
|
||||
|
||||
m_tableInformation.m_lastCollision = numberOfCollisions;
|
||||
m_tableInformation.m_maxCollision = {numberOfCollisions >
|
||||
m_tableInformation.m_maxCollision
|
||||
? numberOfCollisions
|
||||
: m_tableInformation.m_maxCollision};
|
||||
|
||||
m_tableInformation.m_lastCollision = numberOfCollisions;
|
||||
if (numberOfCollisions > m_tableInformation.m_maxCollision) {
|
||||
m_tableInformation.m_maxCollision = numberOfCollisions;
|
||||
}
|
||||
|
||||
m_tableInformation.m_pSeriesNumberOfCollisions->append(
|
||||
m_tableInformation.m_numberOfSuccesses, numberOfCollisions);
|
||||
|
||||
QModelIndex modelIndex = m_pStandardModel->index(index.first, index.second);
|
||||
if (getCurrentTableType() == TableType::Chain) {
|
||||
updateColumns(index.first);
|
||||
} else {
|
||||
m_pStandardModel->setData(modelIndex, QVariant(toQString(value)));
|
||||
}
|
||||
}
|
||||
|
||||
void DemonstrationWidget::unsuccessfulInsertion(const table_type *,
|
||||
const value_type &value) {
|
||||
m_tableInformation.m_lastValue = value;
|
||||
m_tableInformation.m_lastInsertion = false;
|
||||
++m_tableInformation.m_numberOfFailures;
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::updateColumns(size_t rowIndex) {
|
||||
using namespace BusinessLogic::Hash::Table;
|
||||
|
||||
auto tableRow =
|
||||
dynamic_cast<BusinessLogic::Hash::Table::Chains *>(m_pTable.get())
|
||||
->row(rowIndex);
|
||||
size_t modelColumnCount = m_pStandardModel->columnCount();
|
||||
size_t tableColumnCount = tableRow.size();
|
||||
|
||||
if (modelColumnCount < tableColumnCount) {
|
||||
m_pStandardModel->insertColumns(
|
||||
modelColumnCount,
|
||||
std::max(tableColumnCount - modelColumnCount,
|
||||
static_cast<size_t>(std::ceil(
|
||||
std::sqrt(m_tableInformation.m_lastCoefficient)))));
|
||||
}
|
||||
|
||||
QModelIndex modelIndex;
|
||||
auto iterator = tableRow.begin();
|
||||
for (size_t i = 0, size = tableRow.size(); i < size; ++i, ++iterator) {
|
||||
modelIndex = m_pStandardModel->index(rowIndex, i);
|
||||
m_pStandardModel->setData(modelIndex, QVariant(toQString(*iterator)));
|
||||
}
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::updateCharts() {
|
||||
m_pChartCollisionsView->chart()
|
||||
->axes(Qt::Horizontal)
|
||||
.front()
|
||||
->setRange(1, m_tableInformation.m_numberOfSuccesses);
|
||||
m_pChartCollisionsView->chart()
|
||||
->axes(Qt::Vertical)
|
||||
.front()
|
||||
->setRange(0, m_tableInformation.m_maxCollision);
|
||||
m_pChartCollisionsView->chart()->resetMatrix();
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::updateTableView() {
|
||||
m_tableView->scrollTo(
|
||||
m_pStandardModel->index(m_tableInformation.m_lastCoord.first,
|
||||
m_tableInformation.m_lastCoord.second),
|
||||
QAbstractItemView::PositionAtCenter);
|
||||
m_tableView->repaint();
|
||||
}
|
||||
|
||||
inline DemonstrationWidget::value_type &
|
||||
DemonstrationWidget::next(value_type &value) const {
|
||||
auto rbegin = value.rbegin();
|
||||
auto rend = value.rend();
|
||||
|
||||
for (; rbegin != rend; ++rbegin) {
|
||||
if (*rbegin >= firstChar && *rbegin < endChar) {
|
||||
++(*rbegin);
|
||||
return value;
|
||||
} else if (*rbegin == '\0') {
|
||||
*rbegin = firstChar;
|
||||
return value;
|
||||
} else {
|
||||
*rbegin = firstChar;
|
||||
}
|
||||
}
|
||||
value = toStdArray(std::string(4, '\0') + firstChar);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline bool DemonstrationWidget::checkBeforeInsertion(bool tableTypeIsChain) {
|
||||
size_t quantityOfInserts = m_sbQuantity->value();
|
||||
if (tableTypeIsChain &&
|
||||
(m_pTable->numberOfBuckets() + quantityOfInserts) / m_pTable->size() >
|
||||
10) {
|
||||
outputMessage(
|
||||
"Prohibit insertion when allocating more than 10 elements per chain",
|
||||
"red");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::slotClickedMakeItems() {
|
||||
using namespace BusinessLogic::Convert;
|
||||
|
||||
bool tableTypeIsChain = getCurrentTableType() == TableType::Chain;
|
||||
if (not checkBeforeInsertion(tableTypeIsChain)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preparing
|
||||
*/
|
||||
|
||||
if (tableTypeIsChain && m_pStandardModel->columnCount() == 0) {
|
||||
m_pStandardModel->insertColumns(0, m_sbQuantity->value() /
|
||||
m_sbBucketQuantity->value());
|
||||
}
|
||||
|
||||
m_frmProgressBar->setVisible(true);
|
||||
m_progressBar->setValue(0);
|
||||
|
||||
/*
|
||||
* For other thread
|
||||
*/
|
||||
|
||||
setEnabledInsertingProcess(false);
|
||||
m_frmProgressBar->setVisible(true);
|
||||
|
||||
auto differenceNumberOfSuccesses = m_tableInformation.m_numberOfSuccesses;
|
||||
auto differenceNumberOfFailures = m_tableInformation.m_numberOfFailures;
|
||||
|
||||
int value;
|
||||
value_type currentString = toStdArray(m_leFrom->text().toStdString());
|
||||
for (size_t progress = 0, target = m_sbQuantity->value(); progress < target;
|
||||
++progress) {
|
||||
m_pTable->insert(currentString);
|
||||
next(currentString);
|
||||
if (m_stop) {
|
||||
m_stop = false;
|
||||
break;
|
||||
}
|
||||
|
||||
value = static_cast<int>(
|
||||
progress * static_cast<double>(m_progressBar->maximum()) / target);
|
||||
if (value > m_progressBar->value()) {
|
||||
m_progressBar->setValue(value);
|
||||
}
|
||||
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
updateCharts();
|
||||
updateTableView();
|
||||
|
||||
m_frmProgressBar->setVisible(false);
|
||||
setEnabledInsertingProcess(true);
|
||||
|
||||
/*
|
||||
* Output message
|
||||
*/
|
||||
|
||||
differenceNumberOfSuccesses =
|
||||
m_tableInformation.m_numberOfSuccesses - differenceNumberOfSuccesses;
|
||||
differenceNumberOfFailures =
|
||||
m_tableInformation.m_numberOfFailures - differenceNumberOfFailures;
|
||||
|
||||
m_lblOutputMessages->setText(
|
||||
getColorTextHTML(
|
||||
QString("Successful inserts: %1").arg(differenceNumberOfSuccesses),
|
||||
"green") +
|
||||
"<br>" +
|
||||
getColorTextHTML(QString("Failed inserts : %1")
|
||||
.arg(differenceNumberOfFailures),
|
||||
"red"));
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::slotClickedInsert() {
|
||||
bool tableTypeIsChain = getCurrentTableType() == TableType::Chain;
|
||||
if (not checkBeforeInsertion(tableTypeIsChain)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_pTable->insert(toStdArray(m_leInsert->text().toStdString()));
|
||||
outputMessage(m_tableInformation.m_lastInsertion ? "Inserting is successful"
|
||||
: "The insertion has failed",
|
||||
m_tableInformation.m_lastInsertion ? "green" : "red");
|
||||
}
|
||||
|
||||
/*
|
||||
* Other logic
|
||||
*/
|
||||
|
||||
inline auto DemonstrationWidget::getCurrentFactory() const {
|
||||
using namespace BusinessLogic::Hash;
|
||||
|
||||
std::unique_ptr<const Factory::Abstract> factory;
|
||||
bool functionTypeIsFamily =
|
||||
getCurrentFunctionType() == RelationshipType::Family;
|
||||
if (getCurrentAlgorythmType() == RelationshipType::One) {
|
||||
factory = std::make_unique<Factory::One>(
|
||||
functionTypeIsFamily
|
||||
? m_complicatedFunction // The complicated function must be prepared
|
||||
: std::dynamic_pointer_cast<Function::One::Creator>(m_pFunction),
|
||||
std::dynamic_pointer_cast<Algorithm::One::Creator>(m_pAlgorithm));
|
||||
} else if (functionTypeIsFamily) {
|
||||
factory = std::make_unique<Factory::Family>(
|
||||
std::dynamic_pointer_cast<Function::Family::Creator>(m_pFunction),
|
||||
std::dynamic_pointer_cast<Algorithm::Family::Creator>(m_pAlgorithm));
|
||||
} else {
|
||||
std::invalid_argument("function type not defined");
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::updateFunctionCreator() {
|
||||
using namespace BusinessLogic::Hash::Function;
|
||||
if (m_rbEquivalent->isChecked()) {
|
||||
m_pFunction = std::make_shared<Equivalent::Creator>();
|
||||
} else if (m_rbStandart->isChecked()) {
|
||||
m_pFunction = std::make_shared<Standart::Creator>();
|
||||
} else { // m_rbFNV1a32bit->isChecked()
|
||||
m_pFunction = std::make_shared<FNV1a::Creator>();
|
||||
}
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::updateAlgorithmCreator() {
|
||||
using namespace BusinessLogic::Hash::Algorithm;
|
||||
if (m_rbLinearProbing->isChecked()) {
|
||||
m_pAlgorithm = std::make_shared<LinearProbing::Creator>();
|
||||
} else if (m_rbQuadraticProbing->isChecked()) {
|
||||
m_pAlgorithm = std::make_shared<QuadraticProbing::Creator>();
|
||||
} else if (m_rbPseudorandomProbing->isChecked()) {
|
||||
m_pAlgorithm = std::make_shared<PseudorandomProbing::Creator>(
|
||||
m_sbFirstInputData->value());
|
||||
} else { // m_rbDoubleHashing->isChecked()
|
||||
m_pAlgorithm = std::make_shared<DoubleHashing::Creator>(
|
||||
m_sbFirstInputData->value(), m_sbSecondInputData->value());
|
||||
}
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::deleteModel() {
|
||||
auto stringListModel = m_tableView->selectionModel();
|
||||
m_tableView->setModel(nullptr);
|
||||
if (stringListModel not_eq nullptr) {
|
||||
delete stringListModel;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Table GUI
|
||||
*/
|
||||
|
||||
inline void DemonstrationWidget::slotUpdateAdditionalInputData() {
|
||||
bool predicate = {getCurrentFunctionType() == RelationshipType::Family};
|
||||
m_gbInputData->setVisible(predicate);
|
||||
m_frmFirstInputData->setVisible(predicate);
|
||||
|
||||
if (getCurrentTableType() == TableType::Chain) {
|
||||
m_rbStandart->setEnabled(true);
|
||||
m_rbEquivalent->setEnabled(true);
|
||||
m_frmSecondInputData->setVisible(false);
|
||||
} else {
|
||||
bool algorythmIsFamily =
|
||||
getCurrentAlgorythmType() == RelationshipType::Family;
|
||||
m_rbEquivalent->setDisabled(algorythmIsFamily);
|
||||
m_rbStandart->setDisabled(algorythmIsFamily);
|
||||
m_frmSecondInputData->setVisible(algorythmIsFamily);
|
||||
|
||||
if (algorythmIsFamily) {
|
||||
m_rbFNV1a32bit->setChecked(true);
|
||||
repaint();
|
||||
m_frmSecondInputData->setVisible(m_rbDoubleHashing->isChecked());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::slotClickedApply() {
|
||||
using namespace BusinessLogic::Hash;
|
||||
using namespace BusinessLogic::Hash::Function::Pattern;
|
||||
|
||||
if (m_rbDoubleHashing->isChecked() &&
|
||||
m_sbFirstInputData->value() == m_sbSecondInputData->value()) {
|
||||
outputMessage("Hash function coefficients should not match", "red");
|
||||
return;
|
||||
}
|
||||
|
||||
updateFunctionCreator();
|
||||
updateAlgorithmCreator();
|
||||
|
||||
bool tableTypeIsChain = getCurrentTableType() == TableType::Chain;
|
||||
bool functionTypeIsFamily =
|
||||
getCurrentFunctionType() == RelationshipType::Family;
|
||||
|
||||
if (functionTypeIsFamily && (tableTypeIsChain || getCurrentAlgorythmType() ==
|
||||
RelationshipType::One)) {
|
||||
m_complicatedFunction = std::make_shared<FamilyToOne::Creator>(
|
||||
std::dynamic_pointer_cast<Function::Family::Creator>(m_pFunction),
|
||||
m_sbFirstInputData->value());
|
||||
}
|
||||
|
||||
size_t bucketQuantity = m_sbBucketQuantity->value();
|
||||
try {
|
||||
if (tableTypeIsChain) {
|
||||
m_pTable = std::make_unique<Table::Chains>(
|
||||
bucketQuantity,
|
||||
functionTypeIsFamily
|
||||
? *m_complicatedFunction
|
||||
: *std::dynamic_pointer_cast<Function::One::Creator>(m_pFunction),
|
||||
m_alphabetPower);
|
||||
} else {
|
||||
auto factory = getCurrentFactory();
|
||||
m_pTable = std::make_unique<Table::OpenAddressing>(
|
||||
bucketQuantity, *factory, m_alphabetPower);
|
||||
}
|
||||
} catch (const std::bad_alloc &err) {
|
||||
outputMessage("Not enough RAM", "red");
|
||||
return;
|
||||
}
|
||||
|
||||
setEnabledCreateHashTable(false);
|
||||
m_pbFocus->setEnabled(true);
|
||||
m_pTable->signTheObject(this);
|
||||
|
||||
/*
|
||||
* A descendant will notify an ancestor of his own destruction when using
|
||||
* delete
|
||||
*/
|
||||
deleteModel();
|
||||
m_pStandardModel =
|
||||
new QStandardItemModel(bucketQuantity, (tableTypeIsChain ? 0 : 1), this);
|
||||
m_tableView->setModel(m_pStandardModel);
|
||||
|
||||
m_lblOutputMessages->setText(
|
||||
getColorTextHTML("The model was created", "green"));
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::slotClickedStatistics() {
|
||||
m_tableInformation.m_lastCoefficient =
|
||||
m_pTable->simpleUniformHashingCoefficient();
|
||||
QMessageBox::information(
|
||||
nullptr, "Statistics",
|
||||
QString("Maximum number of collisions:\t%1\n")
|
||||
.arg(m_tableInformation.m_maxCollision) +
|
||||
QString("Number of successful inserts:\t\t%1\n")
|
||||
.arg(m_tableInformation.m_numberOfSuccesses) +
|
||||
QString("Number of failed inserts:\t\t%1\n")
|
||||
.arg(m_tableInformation.m_numberOfFailures) +
|
||||
QString("Simple uniform hashing coefficient:\t%1\n")
|
||||
.arg(m_tableInformation.m_lastCoefficient));
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::slotClickedFindFree() {
|
||||
QString result;
|
||||
if (m_pTable->numberOfBuckets() == 0) {
|
||||
result = firstChar;
|
||||
} else {
|
||||
value_type currentString = m_tableInformation.m_lastValue;
|
||||
while (m_pTable->isExist(next(currentString)))
|
||||
continue;
|
||||
result = toQString(currentString);
|
||||
}
|
||||
|
||||
m_leFrom->setText(result);
|
||||
m_leInsert->setText(result);
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::slotClickedStop() {
|
||||
m_stop = true;
|
||||
setEnabledInsertingProcess(true);
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::slotClickedFocus() { updateCharts(); }
|
||||
|
||||
/*
|
||||
* Base GUI
|
||||
*/
|
||||
|
||||
inline void DemonstrationWidget::slotClickedReset() {
|
||||
setEnabledCreateHashTable(true);
|
||||
m_pbFocus->setDisabled(true);
|
||||
|
||||
m_complicatedFunction.reset();
|
||||
m_pTable.release();
|
||||
m_tableInformation.clear();
|
||||
resetAxes();
|
||||
deleteModel();
|
||||
|
||||
outputMessage("The model has been deleted", "green");
|
||||
}
|
||||
|
||||
inline QString
|
||||
DemonstrationWidget::getColorTextHTML(const QString &text,
|
||||
const char *const color) const {
|
||||
return QString(m_fontBeginColorHTML).arg(color) + text + m_fontEndHTML;
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::outputMessage(const QString &text,
|
||||
const char *const color) {
|
||||
m_lblOutputMessages->setText(getColorTextHTML(text, color));
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::setEnabledCreateHashTable(bool flag) {
|
||||
for (QWidget *widget : std::initializer_list<QWidget *>{
|
||||
m_pbApply, m_sbBucketQuantity, m_gbResolutionOfCollisions,
|
||||
m_gbFunction, m_gbInputData}) {
|
||||
widget->setEnabled(flag);
|
||||
}
|
||||
|
||||
if (getCurrentTableType() not_eq TableType::Chain) {
|
||||
m_gbAlgorithm->setEnabled(flag);
|
||||
}
|
||||
m_gbLoadTable->setDisabled(flag);
|
||||
m_pbStatistics->setDisabled(flag);
|
||||
}
|
||||
|
||||
inline void DemonstrationWidget::setEnabledInsertingProcess(bool flag) {
|
||||
for (QWidget *widget : std::initializer_list<QWidget *>{
|
||||
m_leFrom, m_sbQuantity, m_pbMakeItems, m_leInsert, m_pbInsert,
|
||||
m_pbReset, m_pbStatistics, m_pbFindFree}) {
|
||||
widget->setEnabled(flag);
|
||||
}
|
||||
m_pbStop->setDisabled(flag);
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
#ifndef DEMONSTRATION_WIDGET_H
|
||||
#define DEMONSTRATION_WIDGET_H
|
||||
|
||||
#include "../../Validator/validator.h"
|
||||
#include "SourceCode/BusinessLogic/businessLogic.h"
|
||||
#include "SourceCode/BusinessLogic/hashHeaderFiles.h"
|
||||
#include "hashTable.h"
|
||||
#include "ui_demonstrationWidget.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
#include <QChartView>
|
||||
#include <QLineSeries>
|
||||
#include <QStringListModel>
|
||||
#include <QtCharts>
|
||||
|
||||
class DemonstrationWidget
|
||||
: public QWidget,
|
||||
protected Ui::DemonstrationWidget,
|
||||
public BusinessLogic::Hash::Table::Pattern::InterfaceSubscriber {
|
||||
public:
|
||||
using value_type = BusinessLogic::Hash::Table::Abstract::value_type;
|
||||
using table_type = BusinessLogic::Hash::Table::Abstract;
|
||||
|
||||
private:
|
||||
struct TableInformation {
|
||||
public:
|
||||
/* Qt containers */
|
||||
QLineSeries *m_pSeriesNumberOfCollisions;
|
||||
|
||||
/* If successful */
|
||||
std::pair<size_t, size_t> m_lastCoord;
|
||||
size_t m_numberOfSuccesses;
|
||||
size_t m_lastCollision;
|
||||
size_t m_maxCollision;
|
||||
double m_lastCoefficient;
|
||||
double m_maxCoefficient;
|
||||
|
||||
/* If unsuccessful */
|
||||
size_t m_numberOfFailures;
|
||||
|
||||
/* In any case */
|
||||
value_type m_lastValue;
|
||||
bool m_lastInsertion;
|
||||
|
||||
public:
|
||||
TableInformation(const TableInformation &) = delete;
|
||||
TableInformation(TableInformation &&) = delete;
|
||||
|
||||
TableInformation(QLineSeries *maxCollision)
|
||||
: m_pSeriesNumberOfCollisions(maxCollision) {
|
||||
clear();
|
||||
};
|
||||
|
||||
public:
|
||||
void clear();
|
||||
};
|
||||
|
||||
private: // Event filter
|
||||
virtual bool eventFilter(QObject *target, QEvent *event) override {
|
||||
if (target == m_pChartCollisionsView) {
|
||||
QChartView *view = dynamic_cast<QChartView *>(target);
|
||||
QChart *chart = view->chart();
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::Wheel: {
|
||||
QWheelEvent *currentEvent = dynamic_cast<QWheelEvent *>(event);
|
||||
|
||||
qreal factor = currentEvent->angleDelta().y() > 0 ? 0.9 : 1.1;
|
||||
QRectF rect = QRectF(chart->plotArea().left(), chart->plotArea().top(),
|
||||
chart->plotArea().width() * factor,
|
||||
chart->plotArea().height() * factor);
|
||||
|
||||
QPointF mousePos = view->mapFromGlobal(QCursor::pos());
|
||||
rect.moveCenter(mousePos);
|
||||
chart->zoomIn(rect);
|
||||
|
||||
QPointF delta = chart->plotArea().center() - mousePos;
|
||||
chart->scroll(delta.x(), -delta.y());
|
||||
|
||||
return true;
|
||||
} break;
|
||||
default: {
|
||||
return false;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
enum class TableType : short { Chain, OpenAdressing, Indefined };
|
||||
enum class RelationshipType : short { One, Family, Indefined };
|
||||
|
||||
private:
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
static constexpr char firstChar = '!';
|
||||
static constexpr char endChar = '~';
|
||||
|
||||
QChartView *m_pChartCollisionsView;
|
||||
QStandardItemModel *m_pStandardModel;
|
||||
bool m_stop;
|
||||
|
||||
/*
|
||||
* Business logic
|
||||
*/
|
||||
std::shared_ptr<BusinessLogic::Hash::Function::Abstract::Creator> m_pFunction;
|
||||
std::shared_ptr<BusinessLogic::Hash::Function::One::Creator>
|
||||
m_complicatedFunction;
|
||||
std::shared_ptr<BusinessLogic::Hash::Algorithm::Abstract::Creator>
|
||||
m_pAlgorithm;
|
||||
size_t m_alphabetPower;
|
||||
std::unique_ptr<BusinessLogic::Hash::Table::Abstract> m_pTable;
|
||||
TableInformation m_tableInformation;
|
||||
|
||||
/*
|
||||
* HTML tags
|
||||
*/
|
||||
static constexpr auto m_fontBeginColorHTML = R"(<font color="%1">)";
|
||||
static constexpr auto m_fontEndHTML = R"(</font>)";
|
||||
|
||||
public:
|
||||
DemonstrationWidget(QWidget *pWidget = nullptr);
|
||||
|
||||
public: // Custom slots
|
||||
virtual void successfulInsertion(const table_type *, const value_type &,
|
||||
std::pair<size_t, size_t>, size_t) override;
|
||||
virtual void unsuccessfulInsertion(const table_type *,
|
||||
const value_type &) override;
|
||||
|
||||
private:
|
||||
/*
|
||||
* Business logic
|
||||
*/
|
||||
TableType getCurrentTableType() const {
|
||||
TableType result;
|
||||
result = {m_rbChains->isChecked() ? TableType::Chain
|
||||
: m_rbOpenAdressing->isChecked() ? TableType::OpenAdressing
|
||||
: TableType::Indefined};
|
||||
if (result == TableType::Indefined) {
|
||||
throw std::invalid_argument("table not defined");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
RelationshipType getCurrentFunctionType() const {
|
||||
RelationshipType result;
|
||||
result = {m_rbEquivalent->isChecked() ? RelationshipType::One
|
||||
: m_rbStandart->isChecked() ? RelationshipType::One
|
||||
: m_rbFNV1a32bit->isChecked() ? RelationshipType::Family
|
||||
: RelationshipType::Indefined};
|
||||
if (result == RelationshipType::Indefined) {
|
||||
throw std::invalid_argument("function not defined");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
RelationshipType getCurrentAlgorythmType() const {
|
||||
RelationshipType result;
|
||||
result = {m_rbLinearProbing->isChecked() ? RelationshipType::One
|
||||
: m_rbQuadraticProbing->isChecked() ? RelationshipType::One
|
||||
: m_rbPseudorandomProbing->isChecked() ? RelationshipType::Family
|
||||
: m_rbDoubleHashing->isChecked() ? RelationshipType::Family
|
||||
: RelationshipType::Indefined};
|
||||
if (result == RelationshipType::Indefined) {
|
||||
throw std::invalid_argument("algorythm not defined");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
auto getCurrentFactory() const;
|
||||
void updateFunctionCreator();
|
||||
void updateAlgorithmCreator();
|
||||
void deleteModel();
|
||||
void resetAxes() {
|
||||
m_pChartCollisionsView->chart()
|
||||
->axes(Qt::Horizontal)
|
||||
.front()
|
||||
->setRange(1, 2);
|
||||
m_pChartCollisionsView->chart()->axes(Qt::Vertical).front()->setRange(0, 1);
|
||||
}
|
||||
QString toQString(const value_type &value) {
|
||||
auto convert = value;
|
||||
unsigned size =
|
||||
std::remove(convert.begin(), convert.end(), '\0') - convert.begin();
|
||||
return QString::fromLatin1(convert.data(), size);
|
||||
}
|
||||
value_type toStdArray(std::string &&value) const {
|
||||
value_type result = {'\0', '\0', '\0', '\0', firstChar};
|
||||
std::copy(value.rbegin(), value.rend(), result.rbegin());
|
||||
return result;
|
||||
}
|
||||
value_type &next(value_type &value) const;
|
||||
bool checkBeforeInsertion(bool);
|
||||
|
||||
/*
|
||||
* GUI and displaying
|
||||
*/
|
||||
QString getColorTextHTML(const QString &text, const char *const color) const;
|
||||
void outputMessage(const QString &text, const char *const color);
|
||||
void updateColumns(size_t rowIndex);
|
||||
void updateCharts();
|
||||
void updateTableView();
|
||||
void setEnabledCreateHashTable(bool flag);
|
||||
void setEnabledInsertingProcess(bool flag);
|
||||
|
||||
public slots:
|
||||
void slotTabSwitched(int index) {
|
||||
if (index == 1) {
|
||||
QSplitter *splitter = findChild<QSplitter *>("");
|
||||
auto children = splitter->children();
|
||||
QList<int> sizes{dynamic_cast<QWidget *>(children[0])->minimumHeight(),
|
||||
dynamic_cast<QWidget *>(children[1])->minimumHeight()};
|
||||
splitter->setSizes(sizes);
|
||||
}
|
||||
}
|
||||
|
||||
private slots:
|
||||
void slotUpdateAdditionalInputData();
|
||||
void slotClickedReset();
|
||||
void slotClickedApply();
|
||||
void slotClickedMakeItems();
|
||||
void slotClickedInsert();
|
||||
void slotClickedStatistics();
|
||||
void slotClickedFindFree();
|
||||
void slotClickedStop();
|
||||
void slotClickedFocus();
|
||||
};
|
||||
|
||||
#endif // DEMONSTRATION_WIDGET_H
|
||||
@@ -0,0 +1,284 @@
|
||||
#include "testingWidget.h"
|
||||
|
||||
TestingWidget::TestingWidget(QWidget *pWidget)
|
||||
: QWidget(pWidget), m_currentComplexityName("everything"),
|
||||
m_currentTopicName("everything"), m_file("./QuestionsXML/questions.xml") {
|
||||
setupUi(dynamic_cast<QWidget *>(this));
|
||||
|
||||
connect(m_pbConfirm, &QPushButton::clicked, this,
|
||||
&TestingWidget::slotClickedConfirm);
|
||||
|
||||
connect(m_pbStart, &QPushButton::clicked, this,
|
||||
&TestingWidget::slotClickedStart);
|
||||
connect(m_pbStop, &QPushButton::clicked, this,
|
||||
&TestingWidget::slotResetTesting);
|
||||
|
||||
connect(m_rbAllDifficulties, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedComplexity);
|
||||
connect(m_rbEasy, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedComplexity);
|
||||
connect(m_rbMedium, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedComplexity);
|
||||
connect(m_rbHard, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedComplexity);
|
||||
|
||||
connect(m_rbAllTopics, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
connect(m_rbDiscreteMathematics, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
connect(m_rbHashFunction, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
connect(m_rbHashTable, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
connect(m_rbAlgorithm, &QRadioButton::clicked, this,
|
||||
&TestingWidget::slotSwitchedTopics);
|
||||
|
||||
m_frmConfirm->hide();
|
||||
}
|
||||
|
||||
inline void TestingWidget::hideCheckBoxes() {
|
||||
QCheckBox *currentCheckBox;
|
||||
for (unsigned i = 0; i < 9; ++i) {
|
||||
currentCheckBox = findChild<QCheckBox *>(QString("m_cbIndex%1").arg(i));
|
||||
currentCheckBox->hide();
|
||||
}
|
||||
}
|
||||
|
||||
inline void TestingWidget::showCheckBoxes() {
|
||||
QCheckBox *currentCheckBox;
|
||||
for (unsigned i = 0, size = m_answers.size(); i < size; ++i) {
|
||||
currentCheckBox = findChild<QCheckBox *>(QString("m_cbIndex%1").arg(i));
|
||||
currentCheckBox->show();
|
||||
currentCheckBox->setText(m_answers[i].first);
|
||||
}
|
||||
}
|
||||
|
||||
inline QString TestingWidget::getHTMLQuestion(QDomElement element) {
|
||||
QString currentQuestion;
|
||||
|
||||
element = element.firstChildElement();
|
||||
do {
|
||||
switch (getTagsEnumFromQString(element.tagName())) {
|
||||
case TagXML::Caption: {
|
||||
currentQuestion.append(QString("<h3>%1</h3>").arg(element.text()));
|
||||
} break;
|
||||
case TagXML::Text: {
|
||||
currentQuestion.append(QString(R"(
|
||||
<p align="justify">
|
||||
<var>
|
||||
<font face="Times New Roman, Times, serif">
|
||||
%2
|
||||
</font>
|
||||
</var>
|
||||
</p>
|
||||
)")
|
||||
.arg(element.text()));
|
||||
} break;
|
||||
case TagXML::Answer: {
|
||||
m_answers.append(std::make_pair(
|
||||
element.text(), element.hasAttribute("type")
|
||||
? (element.attribute("type") == "correct")
|
||||
: false));
|
||||
} break;
|
||||
case TagXML::Question: {
|
||||
throw std::invalid_argument(
|
||||
"the question cannot be nested within the question");
|
||||
} break;
|
||||
case TagXML::Undefined: {
|
||||
throw std::invalid_argument("tag undefined");
|
||||
} break;
|
||||
}
|
||||
element = element.nextSiblingElement();
|
||||
} while (not element.isNull());
|
||||
|
||||
return currentQuestion;
|
||||
}
|
||||
|
||||
inline void TestingWidget::configureInput(const QString &value) {
|
||||
hideCheckBoxes();
|
||||
resetInput();
|
||||
|
||||
if (value == "choice") {
|
||||
m_swInputData->setCurrentIndex(0);
|
||||
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
std::shuffle(m_answers.begin(), m_answers.end(),
|
||||
std::default_random_engine(seed));
|
||||
showCheckBoxes();
|
||||
} else if (value == "integer") {
|
||||
m_swInputData->setCurrentIndex(1);
|
||||
|
||||
} else if (value == "floatingPoint") {
|
||||
m_swInputData->setCurrentIndex(2);
|
||||
} else {
|
||||
throw std::invalid_argument("the type of the input option is undefined");
|
||||
}
|
||||
}
|
||||
|
||||
inline bool TestingWidget::showNextQuestion() {
|
||||
bool continueFlag = true;
|
||||
|
||||
auto checkType = [](const QString &value) -> bool {
|
||||
return bool{value == "choice" || value == "integer" ||
|
||||
value == "floatingPoint"};
|
||||
};
|
||||
|
||||
while (not m_currentQuestion.isNull() && continueFlag) {
|
||||
|
||||
m_currentTypeName = m_currentQuestion.attribute("type");
|
||||
if ((m_currentTopicName == "everything" ||
|
||||
m_currentQuestion.attribute("category")
|
||||
.split('|')
|
||||
.contains(m_currentTopicName)) &&
|
||||
(m_currentComplexityName == "everything" ||
|
||||
m_currentComplexityName ==
|
||||
m_currentQuestion.attribute("complexity")) &&
|
||||
checkType(m_currentTypeName)) {
|
||||
m_answers.clear();
|
||||
m_testingTextBrowser->setHtml(getHTMLQuestion(m_currentQuestion));
|
||||
|
||||
configureInput(m_currentTypeName);
|
||||
|
||||
continueFlag = false;
|
||||
}
|
||||
m_currentQuestion = m_currentQuestion.nextSiblingElement("question");
|
||||
}
|
||||
|
||||
return (not continueFlag);
|
||||
}
|
||||
|
||||
inline void TestingWidget::setEnabledGUIStartTesting(bool flag) {
|
||||
m_gbTopics->setEnabled(flag);
|
||||
m_gbDifficulty->setEnabled(flag);
|
||||
m_pbStart->setEnabled(flag);
|
||||
m_pbStop->setDisabled(flag);
|
||||
m_frmConfirm->setVisible(not flag);
|
||||
}
|
||||
|
||||
inline TestingWidget::TagXML
|
||||
TestingWidget::getTagsEnumFromQString(const QString &value) {
|
||||
TagXML result = {value == "question" ? TagXML::Question
|
||||
: value == "caption" ? TagXML::Caption
|
||||
: value == "text" ? TagXML::Text
|
||||
: value == "answer" ? TagXML::Answer
|
||||
: TagXML::Undefined};
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slots
|
||||
*/
|
||||
|
||||
inline void TestingWidget::slotSwitchedTopics() {
|
||||
QString result = {m_rbAllTopics->isChecked() ? QString("everything")
|
||||
: m_rbDiscreteMathematics->isChecked()
|
||||
? QString("discreteMathematics")
|
||||
: m_rbHashFunction->isChecked() ? QString("hashFunction")
|
||||
: m_rbHashTable->isChecked() ? QString("hashTable")
|
||||
: m_rbAlgorithm->isChecked() ? QString("algorithm")
|
||||
: QString()};
|
||||
if (result.isNull()) {
|
||||
throw std::invalid_argument("topic undefined");
|
||||
}
|
||||
m_currentTopicName = result;
|
||||
}
|
||||
|
||||
inline void TestingWidget::slotSwitchedComplexity() {
|
||||
QString result = {m_rbAllDifficulties->isChecked() ? QString("everything")
|
||||
: m_rbEasy->isChecked() ? QString("easy")
|
||||
: m_rbMedium->isChecked() ? QString("medium")
|
||||
: m_rbHard->isChecked() ? QString("hard")
|
||||
: QString()};
|
||||
if (result.isNull()) {
|
||||
throw std::invalid_argument("complexity undefined");
|
||||
}
|
||||
m_currentComplexityName = result;
|
||||
}
|
||||
|
||||
inline bool TestingWidget::checkAnswer(const QString &value) {
|
||||
if (m_answers.size() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
if (value == "choice") {
|
||||
QCheckBox *currentCheckBox;
|
||||
for (unsigned i = 0, size = m_answers.size(); i < size; ++i) {
|
||||
currentCheckBox = findChild<QCheckBox *>(QString("m_cbIndex%1").arg(i));
|
||||
if (m_answers[i].second) {
|
||||
result &= currentCheckBox->isChecked();
|
||||
} else {
|
||||
result &= not currentCheckBox->isChecked();
|
||||
}
|
||||
}
|
||||
} else if (value == "integer" || value == "floatingPoint") {
|
||||
QString answer = {value == "integer" ? m_sbInteger->text()
|
||||
: m_sbDouble->text()};
|
||||
auto iter =
|
||||
std::find_if(m_answers.begin(), m_answers.end(),
|
||||
[answer](const std::pair<QString, bool> &value) -> bool {
|
||||
return (value.second == true && value.first == answer);
|
||||
});
|
||||
return (iter not_eq m_answers.end());
|
||||
} else {
|
||||
throw std::invalid_argument("input not defined");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void TestingWidget::slotClickedConfirm() {
|
||||
bool result = checkAnswer(m_currentTypeName);
|
||||
emit signalReplyGiven(result);
|
||||
|
||||
if (not showNextQuestion()) {
|
||||
setEnabledGUIStartTesting(true);
|
||||
slotResetTesting();
|
||||
}
|
||||
}
|
||||
|
||||
inline void TestingWidget::slotClickedStart() {
|
||||
bool isOpened = m_file.open(QIODevice::ReadOnly);
|
||||
emit signalFileOpened(isOpened);
|
||||
|
||||
if (isOpened) {
|
||||
bool isSet = m_document.setContent(&m_file);
|
||||
m_file.close();
|
||||
emit signalContentIsSet(isSet);
|
||||
|
||||
if (isSet) {
|
||||
QDomNode questions =
|
||||
m_document.firstChild().nextSiblingElement("questions");
|
||||
if (questions.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDomNode firstQuestion =
|
||||
questions.firstChild().nextSiblingElement("question");
|
||||
if (firstQuestion.isNull()) {
|
||||
return;
|
||||
}
|
||||
m_currentQuestion = firstQuestion.toElement();
|
||||
if (showNextQuestion()) {
|
||||
setEnabledGUIStartTesting(false);
|
||||
emit signalStartOfTesting();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
inline void TestingWidget::resetInput() {
|
||||
QCheckBox *currentCheckBox;
|
||||
for (unsigned i = 0; i < 9; ++i) {
|
||||
currentCheckBox = findChild<QCheckBox *>(QString("m_cbIndex%1").arg(i));
|
||||
currentCheckBox->setChecked(false);
|
||||
}
|
||||
m_sbInteger->clear();
|
||||
m_sbDouble->clear();
|
||||
}
|
||||
|
||||
inline void TestingWidget::slotResetTesting() {
|
||||
m_testingTextBrowser->clear();
|
||||
setEnabledGUIStartTesting(true);
|
||||
resetInput();
|
||||
emit signalEndOfTesting();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef TESTING_WIDGET_H
|
||||
#define TESTING_WIDGET_H
|
||||
|
||||
#include "ui_testingWidget.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QtXml>
|
||||
#include <QMessageBox>
|
||||
|
||||
class TestingWidget : public QWidget
|
||||
, protected Ui::TestingWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QDomDocument m_document;
|
||||
QDomElement m_currentQuestion;
|
||||
QString m_currentComplexityName;
|
||||
QString m_currentTopicName;
|
||||
QString m_currentTypeName;
|
||||
|
||||
QFile m_file;
|
||||
QVector<std::pair<QString, bool>> m_answers;
|
||||
|
||||
private:
|
||||
enum class Topic : short {
|
||||
Everything, DiscreteMathematics, HashFunction, HashTable, Algorithm, Undefined
|
||||
};
|
||||
enum class Complexity : short {
|
||||
Everything, Easy, Medium, Hard, Undefined
|
||||
};
|
||||
enum class TagXML : short {
|
||||
Question, Caption, Text, Answer, Undefined
|
||||
};
|
||||
|
||||
public:
|
||||
TestingWidget(QWidget *pWidget = nullptr);
|
||||
~TestingWidget() {
|
||||
if(m_file.isOpen()) {
|
||||
m_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void hideCheckBoxes();
|
||||
void showCheckBoxes();
|
||||
QString getHTMLQuestion(QDomElement domNode);
|
||||
void configureInput(const QString &);
|
||||
bool showNextQuestion();
|
||||
void setEnabledGUIStartTesting(bool flag);
|
||||
TagXML getTagsEnumFromQString(const QString&);
|
||||
bool checkAnswer(const QString&);
|
||||
void resetInput();
|
||||
|
||||
private slots:
|
||||
void slotSwitchedTopics();
|
||||
void slotSwitchedComplexity();
|
||||
void slotClickedConfirm();
|
||||
void slotClickedStart();
|
||||
void slotResetTesting();
|
||||
|
||||
signals:
|
||||
void signalFileOpened(bool /*isOpen*/);
|
||||
void signalContentIsSet(bool /*isSet*/);
|
||||
void signalReplyGiven(bool /*isCorrect*/);
|
||||
void signalStartOfTesting();
|
||||
void signalEndOfTesting();
|
||||
};
|
||||
#endif // TESTING_WIDGET_H
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "textBrowserWidget.h"
|
||||
|
||||
TextBrowserWidget::TextBrowserWidget(const QString &xmlFile, QWidget *pWidget)
|
||||
: QWidget(pWidget)
|
||||
{
|
||||
setupUi(dynamic_cast<QWidget *>(this));
|
||||
|
||||
connect( m_main, &QPushButton::clicked, this, &TextBrowserWidget::slotClickedMain );
|
||||
connect( m_next, &QPushButton::clicked, this, &TextBrowserWidget::slotClickedNext );
|
||||
connect( m_previous, &QPushButton::clicked, this, &TextBrowserWidget::slotClickedPrev );
|
||||
connect( m_textBrowser, &QTextBrowser::sourceChanged, this, &TextBrowserWidget::slotPageChanged );
|
||||
|
||||
m_textBrowser->setOpenExternalLinks(true);
|
||||
|
||||
unpack(xmlFile);
|
||||
}
|
||||
|
||||
/*
|
||||
* HTML theory
|
||||
*/
|
||||
|
||||
inline void TextBrowserWidget::slotPageChanged(const QUrl &url) {
|
||||
QString value = url.toString().section('/', -1);
|
||||
auto iterator = std::find_if(m_htmlPages.cbegin(), m_htmlPages.cend()
|
||||
, [value](const QString &other)->bool {
|
||||
return ( other.section('/', -1) == value );
|
||||
});
|
||||
if(iterator == m_htmlPages.cend()) {
|
||||
m_textBrowser->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentIndexPage = iterator - m_htmlPages.cbegin();
|
||||
bool isMainPage = (m_currentIndexPage == 0);
|
||||
m_main->setDisabled(isMainPage);
|
||||
m_previous->setEnabled( isMainPage ? false : m_currentIndexPage not_eq 1 );
|
||||
m_next->setEnabled( isMainPage ? false : m_currentIndexPage not_eq (m_htmlPages.size() - 1) );
|
||||
}
|
||||
|
||||
inline bool TextBrowserWidget::unpack(const QString &xmlFileName) {
|
||||
QDomDocument xmlDocument;
|
||||
|
||||
QFile xmlFile(xmlFileName);
|
||||
if(not xmlFile.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSet = xmlDocument.setContent(&xmlFile);
|
||||
xmlFile.close();
|
||||
|
||||
if(not isSet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomElement infoNode = xmlDocument.firstChild().nextSiblingElement("info");
|
||||
|
||||
QDomElement currentDirectoryElement = infoNode.firstChildElement("directory");
|
||||
QStringList searchPaths;
|
||||
while (not currentDirectoryElement.isNull()) {
|
||||
searchPaths.append(currentDirectoryElement.text());
|
||||
currentDirectoryElement = currentDirectoryElement.nextSiblingElement("directory");
|
||||
}
|
||||
|
||||
QDomElement currentPage = infoNode.firstChildElement("order").firstChildElement("page");
|
||||
if(currentPage.isNull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList result;
|
||||
QString currentTagName;
|
||||
bool isExists;
|
||||
while(not currentPage.isNull()) {
|
||||
currentTagName = currentPage.text();
|
||||
isExists = false;
|
||||
|
||||
for(const QString &name : searchPaths) {
|
||||
if(QDir(name).exists(currentTagName)) {
|
||||
isExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(not isExists) {
|
||||
return false;
|
||||
}
|
||||
result.push_back(currentTagName);
|
||||
currentPage = currentPage.nextSiblingElement("page");
|
||||
}
|
||||
|
||||
m_textBrowser->setSearchPaths(searchPaths);
|
||||
m_htmlPages = result;
|
||||
|
||||
return setSourceMainPage();
|
||||
}
|
||||
|
||||
inline void TextBrowserWidget::slotClickedMain() {
|
||||
if(m_currentIndexPage not_eq 0) {
|
||||
m_textBrowser->setSource(m_htmlPages.front());
|
||||
}
|
||||
}
|
||||
|
||||
inline void TextBrowserWidget::slotClickedPrev() {
|
||||
if(m_currentIndexPage not_eq 1) {
|
||||
m_textBrowser->setSource(m_htmlPages[--m_currentIndexPage]);
|
||||
}
|
||||
}
|
||||
|
||||
inline void TextBrowserWidget::slotClickedNext() {
|
||||
if(m_currentIndexPage not_eq (m_htmlPages.size() - 1)) {
|
||||
m_textBrowser->setSource(m_htmlPages[++m_currentIndexPage]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef THEORY_WIDGET_H
|
||||
#define THEORY_WIDGET_H
|
||||
|
||||
#include "ui_textBrowserWidget.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFile>
|
||||
#include <QtXml>
|
||||
|
||||
class TextBrowserWidget : public QWidget
|
||||
, protected Ui::TextBrowserWidget
|
||||
{
|
||||
private:
|
||||
/*
|
||||
* HTML
|
||||
*/
|
||||
QStringList m_htmlPages;
|
||||
int m_currentIndexPage;
|
||||
|
||||
public:
|
||||
TextBrowserWidget(const QString &xmlFile = {}
|
||||
, QWidget *pWidget = nullptr);
|
||||
|
||||
public:
|
||||
bool unpack(const QString &xmlFile);
|
||||
void setFontPointSize(int size) {
|
||||
QFont font = m_textBrowser->font();
|
||||
font.setPointSize(size);
|
||||
m_textBrowser->setFont(font);
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* Business logic
|
||||
*/
|
||||
bool setSourceMainPage() {
|
||||
if(not m_htmlPages.isEmpty()) {
|
||||
m_textBrowser->setSource( QUrl( m_htmlPages.front() ) );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void slotPageChanged(const QUrl &url);
|
||||
void slotClickedMain();
|
||||
void slotClickedPrev();
|
||||
void slotClickedNext();
|
||||
};
|
||||
#endif // THEORY_WIDGET_H
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "mainWindow.h"
|
||||
|
||||
inline void MainWindow::appendStatusbarText(const QString &value) {
|
||||
m_timer->stop();
|
||||
QString newData;
|
||||
if(m_lblStatusbarText->text().size() + value.size() < 150) {
|
||||
newData.append(m_lblStatusbarText->text());
|
||||
}
|
||||
newData.append(value + "; ");
|
||||
m_lblStatusbarText->setText(newData);
|
||||
m_timer->start();
|
||||
}
|
||||
|
||||
inline void MainWindow::saveResult() {
|
||||
QDate currentTime = QDate::currentDate();
|
||||
short day = currentTime.day();
|
||||
short month = currentTime.month();
|
||||
short year = currentTime.year() % 1000;
|
||||
|
||||
constexpr short sizeDay = 5;
|
||||
constexpr short sizeMonth = 4;
|
||||
constexpr short sizeYear = 10;
|
||||
constexpr short sizeCorrect = 8;
|
||||
constexpr short sizeTotal = 8;
|
||||
//constexpr short sizeSubject = 3;
|
||||
//constexpr short sizeComplexity = 2;
|
||||
constexpr short size = {
|
||||
sizeDay + sizeMonth + sizeYear
|
||||
+ sizeCorrect + sizeTotal
|
||||
// + sizeSubject + sizeComplexity
|
||||
};
|
||||
|
||||
std::bitset<size> newData;
|
||||
for(const auto &value : std::initializer_list<std::pair<short, short>>{
|
||||
{day, sizeDay}, {month, sizeMonth}, {year, sizeYear}
|
||||
, {m_numerOfCorrect, sizeCorrect}, {m_numberOfAll, sizeTotal}
|
||||
}) {
|
||||
newData <<= value.second;
|
||||
newData |= value.first;
|
||||
}
|
||||
|
||||
QByteArray byteArray;
|
||||
|
||||
while(newData.any()) {
|
||||
byteArray.push_front( static_cast<char>( newData.to_ullong()) );
|
||||
newData >>= CHAR_BIT;
|
||||
}
|
||||
|
||||
QFile file("save.dat");
|
||||
file.open(QIODevice::Append);
|
||||
file.write(byteArray);
|
||||
file.close();
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *pWidget)
|
||||
: QMainWindow ( pWidget )
|
||||
, m_timer( new QTimer(this) )
|
||||
, m_lblStatusbarText(new QLabel)
|
||||
{
|
||||
setupUi(dynamic_cast<QMainWindow *>(this));
|
||||
|
||||
/*
|
||||
* Size
|
||||
*/
|
||||
|
||||
QSize screen = QApplication::desktop()->screenGeometry().size();
|
||||
move(screen.width() / 30, screen.height() / 20);
|
||||
|
||||
/*
|
||||
* Signals and slots
|
||||
*/
|
||||
|
||||
connect( m_tabWidget, &QTabWidget::tabBarClicked, m_demonstrationTab, &DemonstrationWidget::slotTabSwitched);
|
||||
|
||||
connect( m_actionTheory, &QAction::triggered, this, [this]() {
|
||||
m_stackedWidget->setCurrentIndex(0);
|
||||
});
|
||||
connect( m_actionPractice, &QAction::triggered, this, [this]() {
|
||||
m_stackedWidget->setCurrentIndex(1);
|
||||
});
|
||||
|
||||
connect( m_actionAbout, &QAction::triggered, this, [](){
|
||||
QMessageBox::aboutQt(nullptr);
|
||||
});
|
||||
|
||||
/*
|
||||
* Theory
|
||||
*/
|
||||
|
||||
m_theoryTab->unpack("./TheoryHTML/info.xml");
|
||||
|
||||
/*
|
||||
* Testing page
|
||||
*/
|
||||
|
||||
m_lblStatusbarText->setParent(m_statusbar);
|
||||
QFont font = m_lblStatusbarText->font();
|
||||
font.setPointSize(12);
|
||||
m_lblStatusbarText->setFont(font);
|
||||
|
||||
m_statusbar->addWidget(m_lblStatusbarText);
|
||||
m_timer->setParent(this);
|
||||
m_timer->setInterval(1000 * 5);
|
||||
m_timer->callOnTimeout(m_lblStatusbarText, &QLabel::clear);
|
||||
|
||||
|
||||
connect( m_secondPage, &TestingWidget::signalStartOfTesting, this, [this]() {
|
||||
m_numerOfCorrect = 0;
|
||||
m_numberOfAll = 0;
|
||||
appendStatusbarText("Testing has begun");
|
||||
});
|
||||
connect( m_secondPage, &TestingWidget::signalEndOfTesting, this, [this]() {
|
||||
saveResult();
|
||||
appendStatusbarText("Test ended, results saved");
|
||||
});
|
||||
connect( m_secondPage, &TestingWidget::signalReplyGiven, this, [this](bool result) {
|
||||
++m_numberOfAll;
|
||||
if(result) {
|
||||
++m_numerOfCorrect;
|
||||
appendStatusbarText("Correct answer");
|
||||
}
|
||||
else {
|
||||
appendStatusbarText("False answer");
|
||||
}
|
||||
});
|
||||
connect( m_secondPage, &TestingWidget::signalFileOpened, this, [this](bool flag) {
|
||||
appendStatusbarText(flag ? "File successfully opened" : "File cannot be opened");
|
||||
});
|
||||
connect( m_secondPage, &TestingWidget::signalContentIsSet, this, [this](bool flag) {
|
||||
appendStatusbarText(flag ? "Content of file successfully set" : "Failure to set content of file");
|
||||
});
|
||||
|
||||
/*
|
||||
* Manual window
|
||||
*/
|
||||
connect( m_actionManual, &QAction::triggered, this, [this]() {
|
||||
auto *manualWindow = new QDialog(this, Qt::Dialog);
|
||||
manualWindow->setModal(true);
|
||||
|
||||
auto *centralLayout = new QVBoxLayout;
|
||||
auto *textBrowser = new TextBrowserWidget(":/ManualHTML/info.xml");
|
||||
textBrowser->setFontPointSize(12);
|
||||
centralLayout->addWidget(textBrowser);
|
||||
auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||
connect(buttonBox, &QDialogButtonBox::clicked, manualWindow, &QDialog::close);
|
||||
centralLayout->addWidget(buttonBox);
|
||||
|
||||
manualWindow->setLayout(centralLayout);
|
||||
manualWindow->setMinimumSize({ 800, 600 });
|
||||
manualWindow->setWindowFlags(manualWindow->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
manualWindow->setWindowTitle("Manual");
|
||||
manualWindow->show();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef MAIN_WINDOW_H
|
||||
#define MAIN_WINDOW_H
|
||||
|
||||
#include "ui_mainWindow.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
#include <QArrayData>
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
, protected Ui::MainWindow
|
||||
{
|
||||
private:
|
||||
QTimer *m_timer;
|
||||
QLabel *m_lblStatusbarText;
|
||||
|
||||
size_t m_numerOfCorrect;
|
||||
size_t m_numberOfAll;
|
||||
|
||||
private:
|
||||
void appendStatusbarText(const QString &value);
|
||||
void saveResult();
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *pWidget = nullptr);
|
||||
};
|
||||
|
||||
#endif // MAIN_WINDOW_H
|
||||
@@ -0,0 +1,972 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DemonstrationWidget</class>
|
||||
<widget class="QWidget" name="DemonstrationWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>805</width>
|
||||
<height>460</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QFrame" name="m_frmProgressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<widget class="QLabel" name="m_lblProgressBar">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Progress of inserting elements:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="m_progressBar">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
<underline>false</underline>
|
||||
<strikeout>false</strikeout>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="m_rightScrollArea">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>501</x>
|
||||
<y>0</y>
|
||||
<width>250</width>
|
||||
<height>250</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>234</width>
|
||||
<height>1020</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="scrollAreaWidgetContentsLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="m_gbResolutionOfCollisions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Resolution of collisions</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbChains">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Chains</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbOpenAdressing">
|
||||
<property name="text">
|
||||
<string>Open addressing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="m_gbFunction">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Function</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbEquivalent">
|
||||
<property name="text">
|
||||
<string>Equivalent</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbStandart">
|
||||
<property name="text">
|
||||
<string>Standart</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbFNV1a32bit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FNV1a 32 bit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="m_gbAlgorithm">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Algorithm</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbLinearProbing">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Linear probing</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbPseudorandomProbing">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pseudorandom probing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbQuadraticProbing">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Quadratic probing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbDoubleHashing">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Double hashing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="m_gbInputData">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Additional input data</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QFrame" name="m_frmFirstInputData">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblFirstInputData">
|
||||
<property name="text">
|
||||
<string>Coefficient of the first family function:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_sbFirstInputData</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="m_sbFirstInputData">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="stepType">
|
||||
<enum>QAbstractSpinBox::DefaultStepType</enum>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="m_frmSecondInputData">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
<item>
|
||||
<widget class="QLabel" name="m_lblSecondInputData">
|
||||
<property name="text">
|
||||
<string>Coefficient of the second family function:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_sbSecondInputData</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="m_sbSecondInputData">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="stepType">
|
||||
<enum>QAbstractSpinBox::DefaultStepType</enum>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gbHashTable">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Hash table</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lblNumberOfElements">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bucket quantity:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_sbBucketQuantity</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="m_sbBucketQuantity">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="m_pbReset">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="m_pbApply">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="m_pbStatistics">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Statistics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="m_gbLoadTable">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Load table</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="loadTableLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="makeItemsLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lblFrom">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>From:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_leFrom</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lblQuantity">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Quantity:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_sbQuantity</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="m_sbQuantity">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="m_leFrom">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="inputMethodHints">
|
||||
<set>Qt::ImhNone</set>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pbMakeItems">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Make items</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="insertLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="m_lblInsert">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Value:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_leInsert</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="m_leInsert">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pbInsert">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Insert</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pbFindFree">
|
||||
<property name="text">
|
||||
<string>Find free</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pbStop">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pbFocus">
|
||||
<property name="text">
|
||||
<string>Focus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="spacerOverOutputMessages">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frmOutputMessages">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="midLineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblOutputMessages">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Output messages:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_lblOutputMessages">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Consolas</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="inputMethodHints">
|
||||
<set>Qt::ImhNone</set>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="midLineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QTableView" name="m_tableView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>250</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="tabKeyNavigation">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropOverwriteMode">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="gridStyle">
|
||||
<enum>Qt::SolidLine</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>m_tableView</tabstop>
|
||||
<tabstop>m_rightScrollArea</tabstop>
|
||||
<tabstop>m_rbChains</tabstop>
|
||||
<tabstop>m_rbOpenAdressing</tabstop>
|
||||
<tabstop>m_rbEquivalent</tabstop>
|
||||
<tabstop>m_rbStandart</tabstop>
|
||||
<tabstop>m_rbFNV1a32bit</tabstop>
|
||||
<tabstop>m_rbLinearProbing</tabstop>
|
||||
<tabstop>m_rbPseudorandomProbing</tabstop>
|
||||
<tabstop>m_rbQuadraticProbing</tabstop>
|
||||
<tabstop>m_rbDoubleHashing</tabstop>
|
||||
<tabstop>m_sbFirstInputData</tabstop>
|
||||
<tabstop>m_sbSecondInputData</tabstop>
|
||||
<tabstop>m_sbBucketQuantity</tabstop>
|
||||
<tabstop>m_pbReset</tabstop>
|
||||
<tabstop>m_pbApply</tabstop>
|
||||
<tabstop>m_pbStatistics</tabstop>
|
||||
<tabstop>m_leFrom</tabstop>
|
||||
<tabstop>m_sbQuantity</tabstop>
|
||||
<tabstop>m_pbMakeItems</tabstop>
|
||||
<tabstop>m_leInsert</tabstop>
|
||||
<tabstop>m_pbInsert</tabstop>
|
||||
<tabstop>m_pbFindFree</tabstop>
|
||||
<tabstop>m_pbStop</tabstop>
|
||||
<tabstop>m_pbFocus</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>m_rbChains</sender>
|
||||
<signal>clicked(bool)</signal>
|
||||
<receiver>m_gbAlgorithm</receiver>
|
||||
<slot>setDisabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>861</x>
|
||||
<y>45</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>858</x>
|
||||
<y>225</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>m_rbOpenAdressing</sender>
|
||||
<signal>clicked(bool)</signal>
|
||||
<receiver>m_gbAlgorithm</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>887</x>
|
||||
<y>78</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>892</x>
|
||||
<y>219</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,261 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1093</width>
|
||||
<height>548</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Hash tables</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="m_stackedWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="m_firstPage">
|
||||
<layout class="QVBoxLayout" name="firstPageLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="m_tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="TextBrowserWidget" name="m_theoryTab">
|
||||
<attribute name="title">
|
||||
<string>Theory</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="DemonstrationWidget" name="m_demonstrationTab">
|
||||
<attribute name="title">
|
||||
<string>Demonstration</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="TestingWidget" name="m_secondPage">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="bottomLayout">
|
||||
<item>
|
||||
<spacer name="bottomSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_exitButton">
|
||||
<property name="text">
|
||||
<string>&Exit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="m_menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1093</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="m_actionManual"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="m_actionAbout"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
<addaction name="m_actionTheory"/>
|
||||
<addaction name="m_actionPractice"/>
|
||||
</widget>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="m_statusbar"/>
|
||||
<action name="m_actionNewUserSession">
|
||||
<property name="text">
|
||||
<string>&User session</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>User session</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+N</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionOpen">
|
||||
<property name="text">
|
||||
<string>&Open...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionSave">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Save</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionSaveAs">
|
||||
<property name="text">
|
||||
<string>Save &As...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionOptions">
|
||||
<property name="text">
|
||||
<string>&Options...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionManual">
|
||||
<property name="text">
|
||||
<string>&Manual</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+H</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionAbout">
|
||||
<property name="text">
|
||||
<string>About this &program</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+A</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionTheory">
|
||||
<property name="text">
|
||||
<string>&Theory</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionPractice">
|
||||
<property name="text">
|
||||
<string>&Practice</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+P</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionAllSessions">
|
||||
<property name="text">
|
||||
<string>&General</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="m_actionCurrentSessions">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Current</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TestingWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>DemonstrationWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TextBrowserWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>m_tabWidget</tabstop>
|
||||
<tabstop>m_exitButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>m_exitButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1044</x>
|
||||
<y>503</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>935</x>
|
||||
<y>524</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,381 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TestingWidget</class>
|
||||
<widget class="QWidget" name="TestingWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>716</width>
|
||||
<height>545</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="leftLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblTestingWindow">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-size:10pt;">Testing window:</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_testingTextBrowser</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="m_testingTextBrowser">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="m_frmConfirm">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="m_swInputData">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="m_wChoice">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblChoice">
|
||||
<property name="text">
|
||||
<string>Choose your answer:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex0">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex1">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex2">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex3">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex4">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex5">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex6">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex7">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="m_cbIndex8">
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="m_wIntegerInput">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblInteger">
|
||||
<property name="text">
|
||||
<string>Enter an integer number:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_sbInteger</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="m_sbInteger"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="m_wDoubleInput">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblDouble">
|
||||
<property name="text">
|
||||
<string>Enter a fractional number:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_sbInteger</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="m_sbDouble"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="confirmLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pbConfirm">
|
||||
<property name="text">
|
||||
<string>Confirm answer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="rightLayout">
|
||||
<property name="spacing">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="m_gbTopics">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Choosing a topic</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbAllTopics">
|
||||
<property name="text">
|
||||
<string>Everything</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbDiscreteMathematics">
|
||||
<property name="text">
|
||||
<string>Discrete mathematics</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbHashFunction">
|
||||
<property name="text">
|
||||
<string>Hash function</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbHashTable">
|
||||
<property name="text">
|
||||
<string>Hash table</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbAlgorithm">
|
||||
<property name="text">
|
||||
<string>Algorithm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="m_gbDifficulty">
|
||||
<property name="title">
|
||||
<string>Choice of difficulty</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbAllDifficulties">
|
||||
<property name="text">
|
||||
<string>Everything</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbEasy">
|
||||
<property name="text">
|
||||
<string>Easy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbMedium">
|
||||
<property name="text">
|
||||
<string>Medium</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="m_rbHard">
|
||||
<property name="text">
|
||||
<string>Hard</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pbStart">
|
||||
<property name="text">
|
||||
<string>Start testing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pbStop">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save && Stop testing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>m_testingTextBrowser</tabstop>
|
||||
<tabstop>m_pbStart</tabstop>
|
||||
<tabstop>m_pbStop</tabstop>
|
||||
<tabstop>m_sbInteger</tabstop>
|
||||
<tabstop>m_pbConfirm</tabstop>
|
||||
<tabstop>m_rbAllTopics</tabstop>
|
||||
<tabstop>m_rbDiscreteMathematics</tabstop>
|
||||
<tabstop>m_rbHashFunction</tabstop>
|
||||
<tabstop>m_rbHashTable</tabstop>
|
||||
<tabstop>m_rbAlgorithm</tabstop>
|
||||
<tabstop>m_rbAllDifficulties</tabstop>
|
||||
<tabstop>m_rbEasy</tabstop>
|
||||
<tabstop>m_rbMedium</tabstop>
|
||||
<tabstop>m_rbHard</tabstop>
|
||||
<tabstop>m_sbDouble</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TextBrowserWidget</class>
|
||||
<widget class="QWidget" name="TextBrowserWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="textBrowserButtonsLayout">
|
||||
<item>
|
||||
<spacer name="leftSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_previous">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Previous</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_main">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Main</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_next">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Next</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="rightSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="m_textBrowser">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Times New Roman</family>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "../SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
MainWindow mainWindow;
|
||||
mainWindow.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>ManualHTML/info.xml</file>
|
||||
<file>ManualHTML/Pages/demonstration.html</file>
|
||||
<file>ManualHTML/Pages/main.html</file>
|
||||
<file>ManualHTML/Pages/menubar.html</file>
|
||||
<file>ManualHTML/Pages/theory.html</file>
|
||||
<file>ManualHTML/Pages/theoryPage.html</file>
|
||||
<file>ManualHTML/Pages/testingPage.html</file>
|
||||
<file>ManualHTML/Images/demonstration.png</file>
|
||||
<file>ManualHTML/Images/menubarFirst.png</file>
|
||||
<file>ManualHTML/Images/menubarSecond.png</file>
|
||||
<file>ManualHTML/Images/testingPage.png</file>
|
||||
<file>ManualHTML/Images/theory.png</file>
|
||||
<file>ManualHTML/Images/theoryPage.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,139 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Страница 8</title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<i><b>Страница 8</b></i>
|
||||
</p>
|
||||
<hr />
|
||||
<h1 style="text-align: center">Анализ хеш-таблиц и алгоритмов поиска</h1>
|
||||
<h2 style="text-align: center">Общее описание [2, c. 285-318]</h2>
|
||||
<p style="text-align: justify">
|
||||
Хеш-таблица представляет собой эффективную структуру данных для реализации
|
||||
словарей. Хотя на поиск элемента в хеш-таблице может в наихудшем случае
|
||||
потребоваться столько же времени, сколько на поиск в связанном списке, а
|
||||
именно - <i>Θ(n)</i>, на практике хеширование исключительно
|
||||
эффективно. При вполне обоснованных допущениях среднее время поиска
|
||||
элемента в хеш-таблице составляет <i>O(1)</i>.
|
||||
</p>
|
||||
<h2 style="text-align: center">
|
||||
Таблица с прямой адресацией, как хеш-таблица
|
||||
</h2>
|
||||
<p style="text-align: justify">
|
||||
Хеш-таблица обобщает обычный массив. Возможность прямой индексации
|
||||
элементов обычного массива обеспечивает доступ к произвольной позиции в
|
||||
массиве за время <i>O(1)</i>. Хеширование представляет собой исключительно
|
||||
эффективную и практичную технологию: в среднем все базовые словарные
|
||||
операции выполняются за время <i>O(1)</i><i>.</i>
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Недостаток прямой адресации очевиден: если совокупность ключей
|
||||
<i>U</i> велика, хранение таблицы <i>T</i> размером
|
||||
<i>|U|</i> непрактично, а то и вовсе невозможно - в зависимости от
|
||||
количества доступной памяти и размера совокупности ключей. Кроме того,
|
||||
множество <i>K</i> реально сохранённых ключей может быть мало по сравнению
|
||||
с совокупностью ключей <i>U</i>, а в этом случае память, выделенная для
|
||||
таблицы <i>T</i>, в основном расходуется напрасно.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Когда множество <i>K</i> хранящихся в словаре ключей гораздо меньше
|
||||
совокупности возможных ключей <i>U</i>, для хеш-таблицы требуется
|
||||
существенно меньше места, чем для таблицы с прямой адресацией<sup>1</sup>.
|
||||
Точнее говоря, требования к памяти могут быть снижены
|
||||
до <i>Θ(/K/)</i>, при этом время поиска элемента в хеш-таблице
|
||||
останется равным <i>O(1)</i>. Нужно только заметить, что это граница
|
||||
времени поиска в среднем случае, в то время как в случае таблицы с прямой
|
||||
адресацией эта граница справедлива для наихудшего случая.
|
||||
</p>
|
||||
<h2 style="text-align: center">Хеш-таблица с прямым связыванием</h2>
|
||||
<p>
|
||||
Время, необходимое для вставки в наихудшем случае, равно <i>O(1)</i>.
|
||||
Процедура вставки выполняется очень быстро, в частности, потому, что
|
||||
предполагается, что вставляемый элемент отсутствует в таблице. Время
|
||||
работы поиска в наихудшем случае пропорционально длине списка. Удаление
|
||||
элемента может быть выполнено за время <i>O(1)</i> при использовании
|
||||
дважды связанных списков.
|
||||
</p>
|
||||
<p>
|
||||
Пусть у нас есть хеш-таблица T с m ячейками, в которых хранятся n
|
||||
элементов. В наихудшем случае хеширование с цепочками ведёт себя крайне
|
||||
неприятно: все n ключей хешированы в одну и ту же ячейку, создав список
|
||||
длиной n. Таким образом, время поиска в наихудшем случае равно <i
|
||||
style="text-align: justify"
|
||||
>Θ(n)</i
|
||||
>
|
||||
плюс время вычисления хеш-функции, что ничуть не лучше, чем в случае
|
||||
использования связного списка для хранения всех n элементов. Понятно, что
|
||||
использование хеш-таблиц в наихудшем случае совершенно бессмысленно.
|
||||
</p>
|
||||
<h3>Теорема 8.1<sup>2</sup></h3>
|
||||
<p>
|
||||
В хеш-таблице с разрешением коллизий методом цепочек время неудачного
|
||||
поиска в среднем случае в предположении простого равномерного хеширования
|
||||
составляет <i style="text-align: justify">Θ(1 + a).</i>
|
||||
</p>
|
||||
<h3>Теорема 8.2</h3>
|
||||
<p>
|
||||
В хеш-таблице с разрешением коллизий методом цепочек время успешного
|
||||
поиска в среднем случае в предположении простого равномерного хеширования
|
||||
в среднем равно <i style="text-align: justify">Θ(1 + a).</i>
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Если количество ячеек в хеш-таблице как минимум пропорционально количеству
|
||||
элементов, хранящихся в ней, то <i>n = O(m)</i> и, следовательно,
|
||||
коэффициент заполнения равен <i>n/m = O(m)/m = O(1).</i> Таким
|
||||
образом, поиск элемента в хеш-таблице в среднем требует постоянного
|
||||
времени. Поскольку в худшем случае вставка элемента в хеш-таблицу занимает
|
||||
O(1) времени (как и удаление элемента при использовании дважды связанных
|
||||
списков), можно сделать вывод, что все словарные операции в хеш-таблице в
|
||||
среднем выполняются за время O(1).
|
||||
</p>
|
||||
<h2 style="text-align: center">Хеш-таблица с открытой адресацией</h2>
|
||||
<p style="text-align: justify">
|
||||
Мы проанализируем математическое ожидание количества исследований для
|
||||
хеширования с открытой адресацией в предположении равномерного хеширования
|
||||
и начнём с анализа количества исследований в случае неудачного поиска.
|
||||
</p>
|
||||
<h3>Теорема 8.3</h3>
|
||||
<p>
|
||||
Математическое ожидание количества исследований при неудачном поиске в хеш
|
||||
таблице с открытой адресацией и коэффициентом заполнения
|
||||
<i>a = n/m < 1</i> в предположении равномерного хеширования не
|
||||
превышает <i>1/(1-a).</i>
|
||||
</p>
|
||||
<h3>Следствие 8.1</h3>
|
||||
<p>
|
||||
Вставка элемента в хеш-таблицу с открытой адресацией и коэффициентом
|
||||
заполнения a в предположении равномерного хеширования требует в среднем не
|
||||
более <i>1/(1-a)</i> исследований.
|
||||
</p>
|
||||
<h3>Теорема 8.4</h3>
|
||||
<p>
|
||||
Математическое ожидание количества исследований при удачном поиске в
|
||||
хеш-таблице с открытой адресацией и коэффициентом заполнения <i>a < 1</i>, в
|
||||
предположении равномерного хеширования и равновероятного поиска любого из
|
||||
ключей не превышает
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="8.1.png" width="150" />
|
||||
</div>
|
||||
<p> </p>
|
||||
<hr />
|
||||
<p>
|
||||
<sup>1</sup>В данном контексте автор, упоминая таблицу с прямой
|
||||
адресацией, не применяет термин хеш, так как, предположительно, в примере
|
||||
оригинальной книги не используется хеш-функция для операций поиска
|
||||
элемента или все операции вставки элемента являются инъективными и не
|
||||
нуждаются в решении проблем коллизий.
|
||||
</p>
|
||||
<p>
|
||||
<sup>2</sup>Все доказательства теорем представлены в книге автора с целью
|
||||
описания минимума методического материала
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,149 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Страница 2</title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<i><b>Страница 2</b></i>
|
||||
</p>
|
||||
<hr />
|
||||
<h1 style="text-align: center">Дискретная математика</h1>
|
||||
<h2 style="text-align: center">
|
||||
Функция, как тип бинарных отношений [4, c. 96-100]
|
||||
</h2>
|
||||
<p>
|
||||
Отношения эффективно применяются для описания связей между парами
|
||||
элементов, выбранных из двух множеств <i>А</i> и <i>В</i>. Функции —
|
||||
это частный случай бинарных отношений, на которые наложены дополнительные
|
||||
ограничения.
|
||||
</p>
|
||||
<p>
|
||||
Функцией из множества <i>А</i> в множество <i>В</i> называется бинарное
|
||||
отношение, при котором <i>каждый</i> элемент множества <i>А</i> связан с
|
||||
единственным элементом множества <i>В</i>. Другими словами, для каждого
|
||||
<i>a ∈ A</i> существует ровно одна пара из отношения
|
||||
вида <i>(а, b)</i>.
|
||||
</p>
|
||||
<p>
|
||||
В графических терминах функция описывается таким графом, у которого из
|
||||
каждой вершины, изображающей элементы множества <i>A</i>, выходит
|
||||
<i>ровно одна</i> стрелка.
|
||||
</p>
|
||||
<p>
|
||||
Например, на рис. 2.1 изображен граф, представляющий функцию из множества
|
||||
<i>{а, b, с}</i> в <i>{1, 2}</i>, состоящую из пар <i>(а, 1),</i>
|
||||
<i>(b, 1)</i> и <i>(с, 2)</i>.
|
||||
<div style="text-align: center">
|
||||
<img src="2.1.png" height="150" />
|
||||
<p style="text-align: center">Рисунок 2.1 - функция из множества</p>
|
||||
</div>
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Пусть <i>f</i> - функция из множества <i>A</i> в множество <i>B</i>.
|
||||
Поскольку для каждого <i>x ∈ A</i> существует единственным
|
||||
образом определённый <i>y∈ B</i>, такой, что
|
||||
<i>(x, y) ∈ f</i>, мы будем писать: <i>y = f(x)</i>, и говорить, что
|
||||
функция <i>f</i> <i>отображает </i>множество <i>A</i> в множество
|
||||
<i>B</i>, а <i>f(x)</i> называть <i>образом x</i> при отображении
|
||||
<i>f</i> или <i>значением</i> <i>f</i>, соответствующим аргументу
|
||||
<i>x</i>.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Кроме того, можно написать <i>f : A → B</i>, чтобы
|
||||
подчеркнуть, что функция <i>f</i> переводит элементы из <i>A</i> в
|
||||
элементы из <i>B</i>. Множество <i>A </i>принято называть
|
||||
<i>областью определения</i>, а <i>B</i> -
|
||||
<i>областью значений</i> функции<sup>1</sup> <i>f</i>.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Для уточнения подмножества элементов, в которые переводятся элементы из
|
||||
<i>A</i> функцией <i>f</i>, вводят понятие "образ" или
|
||||
"множество значений функции". А именно,
|
||||
<i>множеством значений</i> функции <i>f</i> называется подмножество в
|
||||
<i>B</i>, состоящее из образов всех
|
||||
элементов <i>x ∈ A</i>. Оно обозначается символом
|
||||
<i>f(A)</i> и формально определяется так:
|
||||
</p>
|
||||
<p style="text-align: center">
|
||||
<i
|
||||
>f(A) = {f(x) : x <i style="text-align: justify">∈ </i
|
||||
>A}</i
|
||||
>
|
||||
</p>
|
||||
<p style="text-align: center"> </p>
|
||||
<h2 style="text-align: center">Свойства функций</h2>
|
||||
<p style="text-align: justify">
|
||||
Пусть <i>f : A → B</i> - функция. Мы будем называть её
|
||||
<i>инъективной </i>или <i>инъекцией</i>, или <i>взаимно однозначной</i>,
|
||||
если
|
||||
</p>
|
||||
<p style="text-align: center">
|
||||
<i
|
||||
>f(a<sub>1</sub>) = f(a<sub>2</sub>) ⇒ a<sub>1 </sub
|
||||
>=<sub> </sub>a<sub>2</sub></i
|
||||
>
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
для всех <i>a<sub>1</sub>, a<sub>2 </sub>∈ A</i>.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Это определение логически эквивалентно тому, что
|
||||
</p>
|
||||
<p style="text-align: center">
|
||||
<i
|
||||
>a<sub>1 </sub>≠ a<sub>2</sub> ⇒ f(a<sub>1</sub>) ≠ f(a<sub>2</sub>),</i
|
||||
>
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
т.е. у инъективной функции нет повторяющихся значений. Иными словами,
|
||||
разные входные данные дают различные выходные данные.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Будем называть функцию <i>f</i> <i>сюръективной </i>или <i>сюръекцией</i>,
|
||||
или <i>функцией "на"</i>, если множество её значений совпадает с
|
||||
областью значений. Это означает, что для каждого
|
||||
<i>b ∈ B</i> найдётся такой <i>a ∈ A</i>,
|
||||
что <i>b = f(a)</i>. Таким образом, каждый элемент области значений
|
||||
является образом какого-то элемента из области определения <i>f</i> .
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Мы называем <i>f</i> <i>биективной </i>функцией или просто
|
||||
<i>биекцией</i>, если она как инъективна, так и сюръективна.
|
||||
</p>
|
||||
<p style="text-align: justify"> </p>
|
||||
<p>На рисунке 2.2 представлены различные виды функций.</p>
|
||||
<div style="text-align: center">
|
||||
<img src="2.2.png" height="350" />
|
||||
<p style="text-align: center">Рисунок 2.2 - различные виды функций</p>
|
||||
</div>
|
||||
<p>Описание:</p>
|
||||
<ul>
|
||||
<li>
|
||||
В случае (a) функция не инъективна, поскольку значение 1 соответствует
|
||||
как a, так и b. Она не является и сюръективной, ввиду того, что в
|
||||
элемент 2 ничего не переходит.
|
||||
</li>
|
||||
<li>
|
||||
В случае (б) функция инъективна, так как не имеет повторяющихся
|
||||
значений. Она же и сюръективна, поскольку множество ее значений
|
||||
совпадает со всей областью значений.
|
||||
</li>
|
||||
<li>
|
||||
Значение 1 эта функция в случае (в) принимает как на а, так и на Ь.
|
||||
Следовательно, она не инъективна. Однако данная функция сюръективна,
|
||||
поскольку в ее множество значений входят все элементы области значений.
|
||||
</li>
|
||||
<li>Последняя функция в случае (г) инъективна, но не сюръективна.</li>
|
||||
<li>Только в случае (б) мы имеем биекцию.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<p>
|
||||
<sup>1</sup>Довольно часто говорят, что функция f определена или задана на
|
||||
множестве A со значениями в множестве B. - Прим. перев.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Страница 6</title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<i><b>Страница 6</b></i>
|
||||
</p>
|
||||
<hr />
|
||||
<h1 style="text-align: center">Решение проблем коллизий</h1>
|
||||
<h2 style="text-align: center">Метод цепочек или прямое связывание [5, c. 170-171]</h2>
|
||||
<p style="text-align: justify">
|
||||
В хеш таблице с прямым связыванием (рис 6.1) значения ключей (бункеры)
|
||||
хранятся в специальных наборах записей, называемых <i>блоками.</i> Каждый
|
||||
из них является вершиной связного списка, в котором находятся привязанные
|
||||
к блоку элементы.
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="6.1.png" height="350" />
|
||||
<p style="text-align: center">Рисунок 6.1 - хеш-таблица с прямым связыванием</p>
|
||||
</div>
|
||||
<p style="text-align: justify">
|
||||
Поиск элементов в хеш-таблице пройдёт быстрее, если связанные списки будут
|
||||
содержать ключи в отсортированном порядке. В этом случае алгоритм сделает
|
||||
вывод, что ключа нет, если дойдёт до значения больше ключевого и не станет
|
||||
просматривать список до конца. Теоретически время его работы составит
|
||||
<i>O(N/B)</i>, но на практике оно будет немного меньше.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Чтобы найти нужный элемент, программе необходимо хешировать ключ и
|
||||
определить, в каком из блоков он может содержаться, а затем двигаться по
|
||||
связному списку до тех пор, пока не будет достигнут его конец или не
|
||||
обнаружится искомое. Если вы доберётесь до конца списка, значит,
|
||||
запрашиваемого элемента в хеш-таблице нет. Как и в случае с добавлением
|
||||
элемента, предстоит выполнить <i>O(N/B)</i> шагов.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Хеш-таблица с прямым связыванием может расширяться и сжиматься<sup>1</sup>
|
||||
по мере необходимости, поэтому вам не нужно специально изменять её размер.
|
||||
Однако если связные списки станут слишком длинными, поиск и удаление
|
||||
элементов займут много времени. В этом случае вам понадобится увеличить
|
||||
таблицу, чтобы создать больше блоков. Поскольку при рехешировании таблицы
|
||||
не надо проводить поиск дубликатов до конца связного списка в каждом
|
||||
блоке, полностью справиться с операцией можно за время <i>O(N)</i>.
|
||||
</p>
|
||||
<hr />
|
||||
<p>
|
||||
<sup>1</sup>Удаление элементов в данном методическом материале
|
||||
рассматриваться не будет
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Страница 3</title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<i><b>Страница 3</b></i>
|
||||
</p>
|
||||
<hr />
|
||||
<h1 style="text-align: center">Дискретная математика</h1>
|
||||
<h2 style="text-align: center">Принцип Дирихле [4, c. 105]</h2>
|
||||
<p>
|
||||
Пусть <i>f : A <i style="text-align: justify">→ </i>B</i> -
|
||||
функция, причём как <i>A</i>, так и <i>B</i> - конечные множества.
|
||||
Предположим, что <i>A</i> состоит из <i>n</i> элементов:
|
||||
<i>a<sub>1</sub>, a<sub>2</sub>,..., a<sub>n</sub></i
|
||||
>. Принцип Дирихле гласит, что если <i>|A| > |B|</i>, то по крайней
|
||||
мере одно значение <i>f</i> встретится более одного раза<sup>1</sup>.
|
||||
Проще говоря, найдётся пара элементов
|
||||
<i
|
||||
>a<sub>i </sub><i style="text-align: center">≠</i
|
||||
><sub> </sub>a<sub>j</sub></i
|
||||
>, для которых <i>f(a<sub>i</sub>) = f(a<sub>j</sub>)</i>.
|
||||
</p>
|
||||
<p>
|
||||
Чтобы убедиться в истинности принципа, предположим, что для любой пары
|
||||
разных индексов
|
||||
<i>i <i style="text-align: center">≠ </i>j</i> мы имеем:
|
||||
<i>f(a<sub>i</sub>) </i><i style="text-align: center">≠ </i
|
||||
><i>f(a<sub>j</sub>)</i>. Тогда множество <i>B</i> содержит по крайней
|
||||
мере <i>n</i> различных элементов:
|
||||
<i>f(a<sub>1</sub>), f(a<sub>2</sub>),..., f(a<sub>n</sub>)</i>. И уж во
|
||||
всяком случае, <i>|B| ≥ n</i>, что противоречит
|
||||
предположению: <i>n = |A| > |B|</i>. Следовательно, есть хотя бы два
|
||||
разных элемента
|
||||
<i
|
||||
>a<sub>i</sub>, a<sub>j </sub
|
||||
><i style="text-align: justify">∈ </i>A</i
|
||||
>, для которых <i>f(a<sub>i</sub>) = f(a<sub>j</sub>)</i>.
|
||||
</p>
|
||||
<hr />
|
||||
<p>
|
||||
<sup>1</sup>Допуская некоторую вольность, принцип Дирихле можно
|
||||
переформулировать в легко запоминающейся форме: нельзя рассадить 10 зайцев
|
||||
в 9 клеток так, чтобы в каждой клетке сидел один заяц - Прим. перев.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Страница 4</title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<i><b>Страница 4</b></i>
|
||||
</p>
|
||||
<hr />
|
||||
<h1 style="text-align: center">Хеш-фукнция</h1>
|
||||
<h2 style="text-align: center">Свойства хеш-функции</h2>
|
||||
<p style="text-align: justify">
|
||||
Хеш-функция (англ. hash function от hash —
|
||||
«превращать в фарш»), или функция свёртки —
|
||||
функция, осуществляющая преобразование массива входных данных
|
||||
произвольной длины в выходную битовую строку установленной
|
||||
длины, выполняемое определённым алгоритмом. Преобразование,
|
||||
производимое хеш-функцией, называется хешированием. Исходные данные
|
||||
называются входным массивом, «ключом» или
|
||||
«сообщением». Результат преобразования называется
|
||||
«хешем», «хеш-кодом», «хеш-суммой»,
|
||||
«сводкой сообщения».[<a
|
||||
href="https://ru.wikipedia.org/wiki/Хеш-таблица"
|
||||
>7</a
|
||||
>]
|
||||
</p>
|
||||
<p style="text-align: justify">Свойства хеш-функции:</p>
|
||||
<ul>
|
||||
<li style="text-align: justify">Должна обладать свойствами функции.</li>
|
||||
<li style="text-align: justify">
|
||||
Не должна обязательно являться инъективной или сюръективной.
|
||||
</li>
|
||||
</ul>
|
||||
<p style="text-align: justify">Определения :</p>
|
||||
<ul>
|
||||
<li style="text-align: justify">
|
||||
Если известна область определения и можно задать отображение в область
|
||||
значений, мощность которого будет больше или эквивалентна мощности
|
||||
области определения, при котором хеш-функция будет являться
|
||||
<i>инъективной</i>, то такая хеш-функция будет являться<i
|
||||
> идеальной хеш-функцией</i
|
||||
>.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Если область определения неизвестна и можно задать отображение в
|
||||
область значений, мощность которого будет больше или эквивалентна
|
||||
мощности области определения, при котором хеш-функция будет
|
||||
являться <i>инъективной</i>, то такая хеш-функция будет являться<i
|
||||
> динамической идеальной хеш-функцией</i
|
||||
>.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Если известна область определения и можно задать отображение в
|
||||
область значений, мощность которого будет эквивалентна мощности
|
||||
области определения, при котором хеш-функция будет
|
||||
являться <i>биективной</i>, то такая хеш-функция будет являться
|
||||
<i>минимальной идеальной хеш-функцией</i>.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Хеш-функция является <i>k-совершенной хеш-функцией</i>,
|
||||
если область определения неизвестна и можно задать отображение в
|
||||
область значений, любой элемент которого будет обладать не более чем k
|
||||
отношениями.
|
||||
</li>
|
||||
</ul>
|
||||
<div style="text-align: justify">
|
||||
Существует несколько терминов, связанных с хеш-функцией:
|
||||
</div>
|
||||
<dl>
|
||||
<dt style="text-align: justify"><i>Хеш</i></dt>
|
||||
<dd style="text-align: justify">
|
||||
элемент области значений, соотнесённый с заранее известным элементом из
|
||||
области определения.
|
||||
</dd>
|
||||
<dt style="text-align: justify"><i>Хеширование</i></dt>
|
||||
<dd style="text-align: justify">это процесс получения хеша.</dd>
|
||||
<dt style="text-align: justify"><i>Коллизия</i></dt>
|
||||
<dd style="text-align: justify">
|
||||
ситуация, при которой нарушается условие инъективности хеш-функции.
|
||||
</dd>
|
||||
</dl>
|
||||
<p style="text-align: justify">
|
||||
Производительность хеширования в среднем случае зависит от того, насколько
|
||||
хорошо хеш-функция приближена к биективной k-совершенной хеш-функции, где
|
||||
разность количества отношейний любых двух элементов области значений
|
||||
стремиться к нулю. Другими словами, каждый элемент области значений
|
||||
обладает минимально возможным количеством отношений. Данное хеширование
|
||||
автор книги [2, с. 291] Томас Кормен называет
|
||||
<i>простым равномерным хешированием</i>.
|
||||
</p>
|
||||
<div style="text-align: justify">
|
||||
Существует множество разнообразных хеш-функций, алгоритмы которых
|
||||
применяются в различных ситуациях, например, когда требуется скорость
|
||||
вычисления хеш-значения, но с повышенным шансом появления коллизии или
|
||||
наоборот.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,120 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Страница 5</title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<i><b>Страница 5</b></i>
|
||||
</p>
|
||||
<hr />
|
||||
<h1 style="text-align: center">Хеш-таблица</h1>
|
||||
<h2 style="text-align: center">Свойства хеш-таблицы</h2>
|
||||
<p style="text-align: justify">
|
||||
Хеш-таблицы являются одним из способов хранения данных при помощи
|
||||
ассоциативного массива [<a
|
||||
href="https://ru.wikipedia.org/wiki/Ассоциативный_массив"
|
||||
target="_blank"
|
||||
>12</a
|
||||
>].
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Хеш-таблицы решают несколько главных проблем при оперировании с данными:
|
||||
</p>
|
||||
<ul>
|
||||
<li style="text-align: justify">
|
||||
<i
|
||||
>Создание отношения (связи) между ключом и абсолютно любым
|
||||
значением.</i
|
||||
>
|
||||
</li>
|
||||
<li style="text-align: justify"><i>Решение проблем коллизий.</i></li>
|
||||
</ul>
|
||||
<p style="text-align: justify">
|
||||
Для большего понимания материала требуется ознакомиться с новыми терминами
|
||||
хеш-таблицы:
|
||||
</p>
|
||||
<dl>
|
||||
<dt><i>Ключ или сообщение</i></dt>
|
||||
<dd>использующийся хеш-таблицей произвольный элемент из области определения хеш-функции.</dd>
|
||||
<dt><i>Бункер или корзина</i></dt>
|
||||
<dd>произвольный элемент, который хранит данные хеш-таблицы.</dd>
|
||||
<dt><i>Коэффициент заполнения</i></dt>
|
||||
<dd>
|
||||
отношение количества заполненных бункеров на количество возможных ключей.
|
||||
</dd>
|
||||
</dl>
|
||||
<p style="text-align: justify">
|
||||
Исходя из определений, бункер - это условная единица хранимой информации в
|
||||
хеш-таблице (ассоциативном массиве данных).
|
||||
</p>
|
||||
<p>
|
||||
<i
|
||||
><span style="text-align: justify"
|
||||
>Решение первой проблемы. </span
|
||||
></i
|
||||
>Хеш-функции в хеш-таблице, нужны по причине получения хеша в процессе
|
||||
хеширования ключа, однако хеш - значение абстрактное, так как невозможно
|
||||
создать такой алгоритм, который бы выдавал хеш, как набор данных,
|
||||
используемый в процессе работы программы или это очень сложно.<br />
|
||||
Для большего понимания нужно вспомнить пример о <span
|
||||
style="text-align: justify"
|
||||
>"продавце в маленьком магазинчике", где "помощница"
|
||||
абстрагирует понятие хеш-функции, которая выдавала для каждого товара
|
||||
конкретную цену, что возможно, но трудозатратно.</span
|
||||
><br />
|
||||
<span style="text-align: justify"
|
||||
>Для этого требуется хеш-функция, где хеш является универсальным
|
||||
идентификатором конкретного бункера, в котором располагается необходимый
|
||||
пользователю набор данных.</span
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
Томас Кормен говорит в книге [2, c.288], что цель хеш-функции состоит в
|
||||
том, чтобы уменьшить рабочий диапазон индексов массива - размер массива
|
||||
может быть равен соотносительно намного меньшему значению, чем мощность
|
||||
множества всех существующих значений ключей, которые могут потенциально
|
||||
использоваться в процессе работы программы.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
<span style="text-align: justify"
|
||||
>Из этого можно выделить несколько особенностей хеш-таблиц:</span
|
||||
>
|
||||
</p>
|
||||
<ul>
|
||||
<li style="text-align: justify">
|
||||
Каждый бункер имеет в качестве уникального идентификатора
|
||||
хеш-значение
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Каждый ключ гарантированно имеет связь только с одним бункером.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Количество бункеров относительно количества ключей сильно ограниченно.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
От хеш-функции зависит коэффициент заполнения.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
По принципу Дирихле коллизия неизбежна в ситуации, когда количество ключей больше, чем количество бункеров.
|
||||
</li>
|
||||
</ul>
|
||||
<p style="text-align: justify">
|
||||
<i>Решение второй проблемы</i>. Хеш-таблицы используют в качестве
|
||||
алгоритма поиска элемента контейнера (бункера) хеш-функцию, которая по
|
||||
принципу Дирихле гарантированно создаст коллизии в ситуации, когда
|
||||
количество ключей больше, чем количество бункеров, а обычно так бывает
|
||||
всегда.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Хеш-таблицы решают данную проблему двумя способами:
|
||||
</p>
|
||||
<ul>
|
||||
<li style="text-align: justify">Метод цепочек или прямым связыванием.</li>
|
||||
<li style="text-align: justify">Открытой адресацией.</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,116 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Страница 1</title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<i><b>Страница 1</b></i>
|
||||
</p>
|
||||
<hr />
|
||||
<h1 style="text-align: center">Введение</h1>
|
||||
<h2 style="text-align: center">Гардероб [3, с. 393-394]</h2>
|
||||
<p style="text-align: justify">
|
||||
Когда вы сдаете в гардероб пальто или сумку, вам выдают номерок. Когда же
|
||||
вы собираетесь покинуть помещение, вы отдаете номерок, и вам возвращают
|
||||
ваше пальто или сумку.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Если вдуматься, какую задачку решает данный процесс, можно увидеть, что
|
||||
это задача о поиске и нахождении объекта. Ваше пальто — это объект,
|
||||
который вы передаете гардеробщику; пальто сначала привязывают к
|
||||
определенному номерку, а затем возвращают вам. Метод работает за счет
|
||||
того, что в гардеробе находятся ряды пронумерованных вешалок для одежды и
|
||||
пронумерованные отделения для сумок. Вашему номерку соответствует
|
||||
определенная вешалка или определенное отделение. Гардеробщик же отвечает
|
||||
за то, чтобы разместить ваш объект в нужном месте и чтобы забрать его с
|
||||
помощью отданного вами номерка.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Когда речь идет о поиске, люди чаще всего представляют себе, что нужно
|
||||
перебирать вещи до тех пор, пока не найдется нужная; процесс становится
|
||||
проще, если вещи отсортированы так, что мы можем искать среди них более
|
||||
слаженно. Гардероб же показывает, что есть и другой способ: присвоить вещи
|
||||
адрес, где она будет располагаться, и затем сразу достать ее из указанного
|
||||
места. В гардеробе адрес указан на номерках, и гардеробщик на самом деле
|
||||
ищет не ваши вещи: он смотрит на номерок, на адрес и идет к указанной
|
||||
вешалке или отделению с вашими вещами.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Весь метод в целом можно назвать определением местонахождения
|
||||
<i>без поиска</i>: мы не ищем объект, а получаем адрес места, где он будет
|
||||
храниться. Соотносим объект с адресом, а затем, когда хотим найти объект,
|
||||
мы идем прямиком к нужному месту.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Теперь рассмотрим данный метод с точки зрения компьютерного мира, где наши
|
||||
объекты представлены в виде записей, содержащих атрибуты. Мы хотим уметь
|
||||
переходить напрямую от записи к адресу, по которому она размещена;
|
||||
адресом будет число, соответствующее области в компьютерной памяти.
|
||||
Главная загвоздка в такой задачке — то, как соотнести адрес с
|
||||
элементом. Нам нужен быстрый и надежный способ, и мы не можем положиться
|
||||
на какого-либо посредника. Когда мы ищем запись, мы ищем ее по одному или
|
||||
большему числу атрибутов, которые формируют ключ записи, поэтому нам нужен
|
||||
метод получения адреса из ключа записи. Так как адрес — это число,
|
||||
нам нужен способ, который перенесет нас от ключей к числам. Иными словами,
|
||||
мы нуждаемся в функции, скажем, <i>f(K)</i>, которая возьмет ключ K записи
|
||||
R и вернет значение <i>a = f(K)</i>. Значение a представляет собой адрес,
|
||||
где будет храниться запись, мы идем по нему и оставляем там нашу запись.
|
||||
Каждый раз, когда нам требуется достать нашу запись с помощью ключа, мы
|
||||
снова прибегаем к функции <i>f(K)</i>, которая вернет то же адресное
|
||||
значение a, откуда мы и заберем нашу запись. Функция должна быть быстрой и
|
||||
достаточно скоро находить нужный адрес: как минимум, не дольше, чем поиск
|
||||
по записям до тех пор, пока не найдется та, которую мы ищем. В противном
|
||||
случае толку от такой функции никакого. Если же мы в самом деле
|
||||
обзаведемся такой функцией, то разрешим нашу задачку с местоположением
|
||||
новым способом: не мы будем искать элемент, а сам элемент расскажет нам,
|
||||
где его найти: расскажет с помощью нашей функции.
|
||||
</p>
|
||||
<h2 style="text-align: center">Продавец</h2>
|
||||
<p style="text-align: justify">
|
||||
Так же стоит привести введение в теоретический материал, описанное автором
|
||||
книги [1, c. 100-101], где описывается пример с "продавцом в
|
||||
маленьком магазинчике".
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
В ситуации, когда клиент покупает
|
||||
у продавца товар необходимо определить ценность предмета.
|
||||
Изначально стоит отметить, что цены в магазинах на один и тот же товар
|
||||
всегда одинаковый в один момент времени, поэтому необходимо хранить
|
||||
информацию о ценах, например, в книге, однако данный метод оперирования
|
||||
информацией будет весьма утомителен и ужасно неэффективен. Для
|
||||
решения этой проблемы продавец нанимает помощницу, которая
|
||||
безошибочно определяет цену на товар, если посмотрит на него или узнает
|
||||
его название.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Автор абстрактно описывает проблему с упорядоченным контейнером данных,
|
||||
где может потребоваться простой поиск, алгоритм которого обладает линейной
|
||||
сложностью. В данном примере контейнер является хранилищем элементов,
|
||||
каждый из которых может повторяться, но обязан иметь только один
|
||||
уникальный идентификатор. Можно с уверенностью выделить две проблемы, от
|
||||
которых можно избавиться в <i>идеальных </i>условиях — затраты на
|
||||
хранение элементов и поиск каждого из них при помощи уникального
|
||||
идентификатора. В приоритете необходимо выполнять успешный поиск элемента,
|
||||
алгоритм которого будет выполняться за константное время.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Решением является использование функции [4, c. 96] из множества <i>A</i> в
|
||||
множество <i>B.</i> Данная функция описывает бинарное отношение, при
|
||||
котором <i>каждый</i> элемент множества <i>А</i> связан с
|
||||
единственным элементом множества <i>B</i>. Данная функция в
|
||||
программировании имеет название хеш-функция. Избавиться от необходимости в
|
||||
хранении множеств элементов, чтобы сохранялась возможность определять
|
||||
новые бинарные отношения, не изменяя другие очень сложно, однако это
|
||||
возможно. Обычно, когда известны все элементы множества <i>А</i> и все
|
||||
элементы множества <i>B</i>, реализуют функцию, при которой любой элемент
|
||||
множества <i>А</i> имеет одно отношение с любым элементом из множества
|
||||
<i>B</i>. Например, данную функцию можно применить в примере с продавцом и
|
||||
помощницей, если каталог товаров не изменяется, но цены на разные товары
|
||||
могут совпадать.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,170 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Теоретический материал</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="text-align: center">Теоретический материал</h1>
|
||||
|
||||
<h2 style="text-align: center">
|
||||
Необходимый минимум теории по теме<br />
|
||||
"Алгоритм вставки в хеш-таблицу"
|
||||
</h2>
|
||||
|
||||
<h3>Описание страницы:</h3>
|
||||
|
||||
<p>
|
||||
Главная страница, предоставляющая пользователю быстрый и удобный поиск
|
||||
нужного разбитого по темам материала.<br />
|
||||
Каждый элемент списка оглавления является гиперссылкой при нажатии на
|
||||
которую можно мгновенно перейти к необходимому разделу информации.<br />
|
||||
Предоставленный пользователю теоретический материал был взят из списка
|
||||
использованной литературы в конце данной страницы.
|
||||
</p>
|
||||
|
||||
<p>Оглавление:</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<a href="introduction.html">Введение.</a>
|
||||
</li>
|
||||
<li>Дискретная математика:
|
||||
<ul>
|
||||
<li>
|
||||
<a href="binaryRelationship.html">Функция.</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="dirichletPrinciple.html">Принцип Дирихле.</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="hashFunction.html">Хеш-функция.</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="hashTable.html">Хеш-таблица.</a>
|
||||
</li>
|
||||
<li>Решение проблем коллизий:
|
||||
<ul>
|
||||
<li>
|
||||
<a href="chainMethod.html">Метод цепочек или прямое связывание.</a>
|
||||
</li>
|
||||
<li><a href = "openAddressing.html">Открытая и прямая адресации.</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href = "analysis.html">Анализ хеш-таблиц и алгоритмов поиска.</a></li>
|
||||
</ol>
|
||||
|
||||
<h3 style="text-align: center">Список использованной литературы</h3>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<em
|
||||
>Бхаргава, А. Грокаем алгоритмы. Иллюстрированное пособие для
|
||||
программистов и любопытствующих / Адитья Бхаргава. — СПб. :
|
||||
Питер, 2017. - 288 с. : ил. — (Библиотека программиста).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Кормен, Т. Х. Алгоритмы: построение и анализ, 3-е изд / Томас Кормен ; пер. с англ. — Москва :
|
||||
ООО "И. Д. Вильямс", 2013. — 1328 с. : ил. — Парал. тит. англ.</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Луридас, П. Алгоритмы для начинающих : теория и практика для
|
||||
разработчика / Панос Луридас ; пер. с англ. Е.М. Егоровой. — Москва :
|
||||
Эксмо, 2020. — 608 с. — (Мировой компьютерный бестселлер).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Хаггарти, Р. Дискретная математика для программистов, 2-е издание, исправленное / Род
|
||||
Стивенс. — Москва : ТЕХНОСФЕРА, 2019. — 400 c.</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Стивенс, Р. Алгоритмы. Теория и практическое применение / Род
|
||||
Стивенс. — Москва : Издательство "Э", 2016. — 544 c. — (Мировой
|
||||
компьютерный бестселлер).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Хеш-таблица [Электронный ресурс]: Википедия. Свободная энциклопедия.
|
||||
— URL: <a
|
||||
href="https://ru.wikipedia.org/wiki/Хеш-таблица"
|
||||
target="_blank"
|
||||
>https://ru.wikipedia.org/wiki/Хеш-таблица</a
|
||||
> (дата обращения: 03.11.2021).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Хеш-функция [Электронный ресурс]: Википедия. Свободная энциклопедия.
|
||||
— URL: <a
|
||||
href="https://ru.wikipedia.org/wiki/Хеш-функция"
|
||||
target="_blank"
|
||||
>https://ru.wikipedia.org/wiki/Хеш-функция</a
|
||||
> (дата обращения: 03.11.2021).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Хеш-функция, что это такое? [Электронный ресурс]: Хабр. Сообщество
|
||||
IT-специалистов. — URL: <a
|
||||
href="https://habr.com/ru/post/534596/"
|
||||
target="_blank"
|
||||
>https://habr.com/ru/post/534596/</a
|
||||
>
|
||||
(дата обращения: 03.11.2021).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Хеш-таблицы [Электронный ресурс]: Хабр. Сообщество IT-специалистов. —
|
||||
URL: <a href="https://habr.com/ru/post/509220/" target="_blank"
|
||||
>https://habr.com/ru/post/509220/</a
|
||||
>
|
||||
(дата обращения: 03.11.2021).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Хеш-таблицы [Электронный ресурс]: CodeChick. Задачи по
|
||||
программированию с проверкой. — URL: <a
|
||||
href="https://codechick.io/tutorials/dsa/dsa-hash-table"
|
||||
target="_blank"
|
||||
>https://codechick.io/tutorials/dsa/dsa-hash-table</a
|
||||
> (дата обращения: 03.11.2021).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Fowler–Noll–Vo hash function [Электронный ресурс]: Википедия.
|
||||
Свободная энциклопедия. — URL: <a
|
||||
href="https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function"
|
||||
target="_blank"
|
||||
>https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function</a
|
||||
> (дата обращения: 03.11.2021).</em
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<em
|
||||
>Ассоциативный массив [Электронный ресурс]: Википедия.
|
||||
Свободная энциклопедия. — URL: <a
|
||||
href="https://ru.wikipedia.org/wiki/Ассоциативный_массив"
|
||||
target="_blank"
|
||||
>https://ru.wikipedia.org/wiki/Ассоциативный_массив</a
|
||||
> (дата обращения: 06.11.2021).</em
|
||||
>
|
||||
</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,274 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Страница 7</title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<i><b>Страница 7</b></i>
|
||||
</p>
|
||||
<hr />
|
||||
<h1 style="text-align: center">Решение проблем коллизий</h1>
|
||||
<h2 style="text-align: center">
|
||||
Открытая и прямая адресации [5, c. 170-179]
|
||||
</h2>
|
||||
<p>Оглавление:</p>
|
||||
<ul>
|
||||
<li><a href="#description">Описание.</a></li>
|
||||
<li><a href="#linear">Линейное пробирование.</a></li>
|
||||
<li><a href="#quadratic">Квадратичное пробирование.</a></li>
|
||||
<li><a href="#pseudorandom">Псевдослучайное пробирование.</a></li>
|
||||
<li><a href="#double">Двойное хеширование.</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<h3 style="text-align: center"><a name="description">Описание</a></h3>
|
||||
<p style="text-align: justify">
|
||||
Безусловно, прямое связывание имеет свои преимущества. Основное из них
|
||||
заключается в том, что общее количество значений не зависит от
|
||||
количества блоков. Однако есть у таких хеш-таблиц и некоторые
|
||||
недостатки. Например, если элементов в блоках накопится слишком много,
|
||||
поиск нужного займет продолжительное время. Чтобы сократить временные
|
||||
затраты, число блоков можно увеличить, но тогда вы рискуете получить ряд
|
||||
пустых, которые потребуют места в памяти и не будут использоваться
|
||||
таблицей.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Еще один способ реализации хеш-таблиц — <i>открытая адресация</i>.
|
||||
В этом случае значения хранятся в массиве, а функция хеширования
|
||||
представляет собой некоторые расчеты.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Хеш-таблица с <i>прямой адресацией</i> отличается от хеш-таблицы с
|
||||
открытой адресацией тем, что в первом случае гарантировано должна
|
||||
использоваться идеальная хеш-функция. Это обусловлено тем, что в данной
|
||||
хеш-таблице должны отсутствовать коллизии, соответственно, как и методы
|
||||
их разрешения. Стоит отметить, что под данное описание подходит
|
||||
<i>идеальное хеширование</i> хеш-таблицы<sup>1</sup>.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
В разных видах открытой адресации используются различные функции
|
||||
хеширования. Неодинакова и политика разрешения коллизий, но в общем
|
||||
случае она выглядит так: для каждого значения в массиве подбирается
|
||||
несколько ячеек, и если первая уже занята, алгоритм пробует использовать
|
||||
вторую, затем третью и так до тех пор, пока не найдет свободную или не
|
||||
придет к выводу, что таковой нет.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Серия ячеек, которую алгоритм подбирает для значения, называется пробной
|
||||
последовательностью. По ее средней длине хорошо оценивать наполненность
|
||||
хештаблицы. В идеале пробная последовательность должна равняться 1 или
|
||||
2, большие цифры говорят о полной таблице.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Иногда политика разрешения коллизий такова, что для элемента может не
|
||||
найтись свободной ячейки, даже когда она есть. Если пробная
|
||||
последовательность повторяет саму себя перед тем, как проверить
|
||||
очередную запись, некоторые записи могут остаться неиспользованными.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Чтобы найти элемент в хеш-таблице, алгоритм следует за пробной
|
||||
последовательностью, пока не произойдет одно из трех событий.
|
||||
</p>
|
||||
<ol>
|
||||
<li style="text-align: justify">
|
||||
Если пробная последовательность сумела отыскать элемент, задача
|
||||
выполнена.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Если пробная последовательность находит пустую запись в массиве,
|
||||
элемента нет.
|
||||
</li>
|
||||
<li style="text-align: justify">
|
||||
Пробная последовательность проверяет <i>M</i> записей (по размеру
|
||||
массива) — и алгоритм приходит к выводу, что значение
|
||||
отсутствует. Последовательность может перебрать не все элементы, но
|
||||
если пройдет по всем, вы будете знать, что они точно пересмотрены или
|
||||
что целевой элемент не найден. Она также может проверить в цикле одну
|
||||
и ту же позицию несколько раз. В любом случае значение не должно
|
||||
присутствовать, поскольку иначе оно бы добавлялось к массиву с
|
||||
использованием той же пробной последовательности.
|
||||
</li>
|
||||
</ol>
|
||||
<p style="text-align: justify">
|
||||
При разумном заполнении хеш-таблицы открытая адресация работает очень
|
||||
быстро. Если длина пробной последовательности равна 1 или 2, добавление
|
||||
и нахождение элементов выполняются за время <i>O(1)</i>. Но если массив
|
||||
из N элементов существенно переполнен, производительность снижается. В
|
||||
наихудшем случае алгоритм придет к выводу, что элемента в массиве нет,
|
||||
за время <i>O(N)</i>. Поиск присутствующих элементов также будет
|
||||
выполняться крайне медленно.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Вы можете увеличить размер массива, чтобы уменьшить коэффициент
|
||||
наполненности хеш-таблицы. Для этого создайте новый массив и рехешируйте
|
||||
элементы в нем. Для каждого из них операция займет <i>O(1)</i> времени,
|
||||
а общая производительность алгоритма составит <i>O(N)</i>.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="text-align: center">
|
||||
<a name="linear">Линейное пробирование</a>
|
||||
</h3>
|
||||
<p style="text-align: justify">
|
||||
В линейном пробировании политика разрешения коллизий добавляет к каждой
|
||||
ячейке постоянное число (чаще всего 1), называемое шагом по индексу,
|
||||
которое генерирует пробную последовательность. При каждом очередном
|
||||
добавлении берется размер массива по модулю, стало быть, при
|
||||
необходимости последовательность возвращается к началу массива.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Предположим, в хеш-таблице 100 элементов, а правило хеширования звучит
|
||||
следующим образом: N связано с ячейкой N mod 100. Тогда пробная
|
||||
последовательность для значения 2197 проверяет ячейки 97, 98, 99, 0, 1,
|
||||
2 и т. д.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
На рисунке 7.1 представлен массив из 10 записей, который уже содержит
|
||||
несколько значений. Чтобы добавить в него новое значение 71, используя
|
||||
линейную пробную последовательность, нужно связать его с ячейкой 71 mod
|
||||
10 = 1. Но эта ячейка уже занята значением 61, поэтому алгоритм
|
||||
переходит к ячейке 2, которая тоже заполнена. Следующей должна быть
|
||||
ячейка 3 — она свободна, и алгоритм размещает там 71.
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="7.1.png" width="800" />
|
||||
<p style="text-align: center">
|
||||
Рисунок 7.1 - линейная пробная последовательность
|
||||
</p>
|
||||
</div>
|
||||
<p style="text-align: justify">
|
||||
Преимущество данного метода — в его простоте. Если необходимо,
|
||||
пробная последовательность пройдет по каждой ячейке массива и вставит
|
||||
элемент в свободное место, если оно еще осталось. Но есть и
|
||||
сопутствующий недостаток — так называемая
|
||||
<i>первичная кластеризация</i>, которая проявляется в образовании
|
||||
больших блоков смежных записей и приводит к длинным пробным
|
||||
последовательностям. В результате при добавлении нового элемента и его
|
||||
хешировании к какой-либо записи в кластере пробная последовательность
|
||||
вынуждена пройти через весь кластер, чтобы найти свободную ячейку.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Чтобы понять, как формируются кластеры, рассмотрим пример пустой
|
||||
хеш-таблицы. Предположим, в ней содержится <i>N</i> записей и существует
|
||||
вероятность <i>1/N</i>, что она закончится в любой данной позиции при
|
||||
добавлении случайного числа. А теперь представим, что <i>K</i> —
|
||||
конечная позиция таблицы. Существует вероятность <i>1/N</i>, что новое
|
||||
случайное число попадет в позицию K и линейное пробирование попытается
|
||||
расположить элемент в позиции <i>K + 1</i>. Но та же вероятность
|
||||
характерна и для случая, при котором новый элемент будет связан с
|
||||
позицией <i>K + 1</i> напрямую. Значит, существует вероятность
|
||||
<i>2/N</i>, что элемент займет конечную позицию <i>K + 1</i> и
|
||||
сформируется малый кластер.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Через какое-то время таких кластеров станет много. Чем больше они будут,
|
||||
тем больше вероятность того, что новый элемент добавится в конец одного
|
||||
из них. В итоге более мелкие кластеры сольются в более крупные, массив
|
||||
заполнится ими — и возникнут длинные пробные последовательности.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="text-align: center">
|
||||
<a name="quadratic">Квадратичное пробирование</a>
|
||||
</h3>
|
||||
<p style="text-align: justify">
|
||||
Возникновение больших кластеров при линейном пробировании связано с тем,
|
||||
что новые элементы связываются с ячейками, стоящими в конце группы, и
|
||||
постепенно увеличивают ее. Предотвратить подобную ситуацию помогает
|
||||
<i>квадратичное пробирование</i>. Для создания пробной
|
||||
последовательности в качестве шага по индексу берется квадрат количества
|
||||
ячеек. Другими словами, если в линейном пробировании существует
|
||||
последовательность <i>K, K + 1, K + 2, K + 3,</i> ... то в квадратичном
|
||||
варианте она будет выглядеть так:
|
||||
<i>K, K + 12, K + 22, K + 32, ...</i> В этом случае, если два
|
||||
элемента окажутся связанными с разными позициями в одном и том же
|
||||
кластере, они не обязательно будут придерживаться одной пробной
|
||||
последовательности и попадут в конец кластера.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
На рисунке 7.2 показана хеш-таблица, в начале которой есть группа из
|
||||
пяти элементов. Новое значение 71 получает пробную последовательность
|
||||
<i>1, 1 + 12 = 2, 1 + 22 = 5, 1 + 32 = 10</i> и не добавляется к
|
||||
существующему кластеру. Значение <i>93 </i>поначалу связано с тем же
|
||||
кластером, но согласно собственной пробной последовательности
|
||||
<i>3, 3 + 12 = 4, 3 + 22 = 7</i> также не попадает в него.
|
||||
</p>
|
||||
<div style="text-align: center">
|
||||
<img src="7.2.png" width="800" />
|
||||
<p style="text-align: center">Рисунок 7.2 - Квадратичное пробирование</p>
|
||||
</div>
|
||||
<p style="text-align: justify">
|
||||
Квадратичное пробирование предотвращает первичную, но не
|
||||
<i>вторичную кластеризацию</i>, при которой значения, связанные с
|
||||
одинаковой начальной позицией в массиве, получают одну и ту же пробную
|
||||
последовательность, иногда очень длинную. В результате образуется точно
|
||||
такая же группа элементов, но уже не собранных вместе, а распределенных
|
||||
по всему массиву.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Еще один недостаток квадратичного пробирования связан с тем, что оно
|
||||
может не найти свободную позицию, даже если в хеш-таблице их несколько.
|
||||
Дело в том, что с каждым разом перемещение по массиву происходит все
|
||||
дальше и дальше, и незаполненная ячейка попросту пропускается.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="text-align: center">
|
||||
<a name="pseudorandom">Псевдослучайное пробирование</a>
|
||||
</h3>
|
||||
<p style="text-align: justify">
|
||||
Это пробирование подобно линейному, за исключением того, что шаг по
|
||||
индексу формирует псевдослучайная функция изначально связанной ячейки.
|
||||
Предположим, что это ячейка <i>K</i>, тогда пробная последовательность
|
||||
будет выглядеть следующим образом: <i>K, K + p, K + 2p, ...</i> где p
|
||||
определяется псевдослучайной функцией.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Подобно квадратичному пробированию, псевдослучайное предотвращает только
|
||||
первичную кластеризацию, но страдает от вторичной: значения, связанные с
|
||||
одной и той же начальной позицией, размещаются в хеш-таблице согласно
|
||||
одной и той же пробной последовательности. Точно так же псевдослучайное
|
||||
пробирование может пропускать некоторые неиспользуемые записи.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="text-align: center">
|
||||
<a name="double">Двойное хеширование</a>
|
||||
</h3>
|
||||
<p style="text-align: justify">
|
||||
Чтобы избавиться от вторичной кластеризации значения, связанные с одной
|
||||
и той же начальной ячейкой, должны получать разные пробные
|
||||
последовательности. И здесь пригодится двойное хеширование. Оно похоже
|
||||
на псевдослучайное пробирование, только шаг для индекса задается не
|
||||
псевдослучайной функцией начальной ячейки, а второй функцией
|
||||
хеширования.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Допустим, значения <i>A</i> и <i>B</i> связаны с позицией <i>K</i>. В
|
||||
псевдослучайном пробировании шаг по индексу <i>p</i> генерируется
|
||||
функцией <i>F<sub>1</sub> (K)</i>, затем оба значения используют пробную
|
||||
последовательность <i>K, K + p, K + 2p, K + 3p, ...</i> В двойном
|
||||
хешировании для связывания начальных значений <i>А</i> и
|
||||
<i>В</i> применяется функция псевдослучайного хеширования
|
||||
<i>F<sub>2</sub></i
|
||||
>. В итоге при одном и том же начальном <i>K</i> образуются две пробные
|
||||
последовательности с различными шагами по индексу:
|
||||
<i>p<sub>A</sub> = F<sub>2</sub> (A)</i> и
|
||||
<i>p<sub>B</sub> = F<sub>2</sub> (B)</i> соответственно.
|
||||
</p>
|
||||
<p style="text-align: justify">
|
||||
Несмотря на то, что двойное хеширование хорошо справляется с первичной и
|
||||
вторичной кластеризациями, оно точно так же, как и псевдослучайное
|
||||
пробирование, может пропускать неиспользуемые записи.
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
<p>
|
||||
<sup>1</sup>Данный метод хеширования хорошо описан в книге Томаса Кормена
|
||||
[2]
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<info>
|
||||
<directory>./TheoryHTML/Pages</directory>
|
||||
<directory>./TheoryHTML/Images</directory>
|
||||
<order>
|
||||
<page>main.html</page>
|
||||
<page>introduction.html</page>
|
||||
<page>binaryRelationship.html</page>
|
||||
<page>dirichletPrinciple.html</page>
|
||||
<page>hashFunction.html</page>
|
||||
<page>hashTable.html</page>
|
||||
<page>chainMethod.html</page>
|
||||
<page>openAddressing.html</page>
|
||||
<page>analysis.html</page>
|
||||
</order>
|
||||
</info>
|
||||