commit 49ecd4784c1acab324ff66868c48c84131462803
Author: user
Date: Sun Jul 12 14:22:00 2026 +0400
Initial commit
diff --git a/HashTable.pro b/HashTable.pro
new file mode 100644
index 0000000..7992869
--- /dev/null
+++ b/HashTable.pro
@@ -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
+
+
diff --git a/Installer/script.iss b/Installer/script.iss
new file mode 100644
index 0000000..99c8f96
--- /dev/null
+++ b/Installer/script.iss
@@ -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
\ No newline at end of file
diff --git a/QuestionsXML/questions.xml b/QuestionsXML/questions.xml
new file mode 100644
index 0000000..217421f
--- /dev/null
+++ b/QuestionsXML/questions.xml
@@ -0,0 +1,101 @@
+
+
+
+
+ Соотнесите подходящие варианты ответа с высказыванием.
+ Метод решения коллизий в хеш-таблице.
+ Прямая адрессация.
+ Открытая адрессация.
+ Регистровая адресация.
+ Метод цепочек.
+ Ничего из вышеперечисленного.
+
+
+
+ Выберите несколько правильных ответов.
+ С какими данными оперирует хеш-функция в процессе хеширования?
+ Хеш-память.
+ Хеш-значение.
+ Кеш-память.
+ Множество ключей.
+ Множество значений.
+
+
+
+ Выберите несколько правильных ответов.
+ На что влияет коэффициент заполнения?
+ Поиск неиспользующегося бункера, при гарантии его существования.
+ Поиск использующегося бункера по его ключу.
+ Скорость хеширования.
+ Количество используемых бункеров.
+ Количество возможных ключей.
+
+
+
+ Выберите несколько правильных ответов.
+ Какие алгоритмы поиска бункера при решении коллизий открытой адресацией используют ровно одну хеш-функцию?
+ Линейное пробирование.
+ Квадратичное пробирование.
+ Псевдослучайное пробирование.
+ Двойное хеширование.
+ Ничего из перечисленного.
+
+
+
+ Введите правильное целочисленое число.
+ Чему равна дисперсия, как мера разброса элементов хеш-таблицы от средней условной величины при идеальном хешировании?
+ 0
+
+
+
+ Выберите варианты ответов, которые подходят по смыслу с заданным текстом.
+ Сопоставьте - идеальное хеширование.
+ Словарь.
+ Прямая адрессация.
+ Открытая адрессация.
+ Регистровая адресация.
+ Метод цепочек.
+ Ничего из вышеперечисленного.
+
+
+
+ Определите про какие алгоритмы поиска бункера при решении коллизий открытой адресацией идёт речь?
+ Политика разрешения коллизий использует шаг по индексу, который зависит от информации (позиция или данные) бункера.
+ Линейное пробирование.
+ Квадратичное пробирование.
+ Псевдослучайное пробирование.
+ Двойное хеширование.
+ Ничего из вышеперечисленного.
+
+
+
+ Определите про какие алгоритмы поиска бункера при решении коллизий открытой адресацией идёт речь?
+ Политика разрешения коллизий использует шаг по индексу, который зависит от количества итераций и/или размера хеш-таблицы.
+ Линейное пробирование.
+ Квадратичное пробирование.
+ Псевдослучайное пробирование.
+ Двойное хеширование.
+ Ничего из вышеперечисленного.
+
+
+
+ Напишите правильный ответ.
+ Рассмотрим хеш-функцию, которая равномерно распределяет значения по хеш-таблице.
+ Размер хеш-таблицы равен 20.
+ После какого количества вставок вероятность того, что при попытке вставить в хеш-таблицу новое значение произойдёт коллизия, превысит 0.5?
+ 11
+
+
+
+ Напишите правильный ответ.
+ Чему будет равен коэффициент заполненности, если в хеш-таблица с 25 цепочками поместить 2000 элементов?
+ 80
+
+
+
+ Напишите правильный ответ.
+ Определите коэффициет заполнения хеш-таблицы с решением коллизий методом открытой адресациии, если её размер равняется 50, но свободных бункеров - 20.
+ 0,60
+
+
+
\ No newline at end of file
diff --git a/SourceCode/BusinessLogic/Convert/convert.cpp b/SourceCode/BusinessLogic/Convert/convert.cpp
new file mode 100644
index 0000000..ae32a71
--- /dev/null
+++ b/SourceCode/BusinessLogic/Convert/convert.cpp
@@ -0,0 +1,22 @@
+#include "convert.h"
+
+BEGIN_NAMESPACE(BusinessLogic)
+BEGIN_NAMESPACE(Convert)
+
+size_t FromStdString::operator()(const std::array &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
diff --git a/SourceCode/BusinessLogic/Convert/convert.h b/SourceCode/BusinessLogic/Convert/convert.h
new file mode 100644
index 0000000..ea49c12
--- /dev/null
+++ b/SourceCode/BusinessLogic/Convert/convert.h
@@ -0,0 +1,24 @@
+#ifndef CONVERT_H
+#define CONVERT_H
+
+#include "../businessLogic.h"
+
+#include
+#include
+#include
+#include
+#include
+
+BEGIN_NAMESPACE(BusinessLogic)
+BEGIN_NAMESPACE(Convert)
+
+class FromStdString
+{
+public:
+ size_t operator()(const std::array &, size_t) const;
+};
+
+END_NAMESPACE // Convert
+END_NAMESPACE // BusinessLogic
+
+#endif // CONVERT_H
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorDoubleHashing.h b/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorDoubleHashing.h
new file mode 100644
index 0000000..259ab5e
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorDoubleHashing.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 create() const override {
+ return std::unique_ptr(new Product(m_firstHashFunction, m_secondHashFunction));
+ }
+};
+
+END_NAMESPACE // DoubleHashing
+END_NAMESPACE // Algorithm
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !CREATOR_ALGHORITHM_DOUBLE_HASHING_H
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorFamily.h b/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorFamily.h
new file mode 100644
index 0000000..8809ebd
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorFamily.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
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorPseudorandomProbing.h b/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorPseudorandomProbing.h
new file mode 100644
index 0000000..089e2e6
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/Family/creatorPseudorandomProbing.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 create() const override {
+ return std::unique_ptr(new Product(m_hashFunctionNumber));
+ }
+
+};
+
+END_NAMESPACE // PseudorandomProbing
+END_NAMESPACE // Algorithm
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !CREATOR_ALGHORITHM_PSEUDORANDOM_PROBING_H
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/Family/doubleHashing.h b/SourceCode/BusinessLogic/Hash/Algorithm/Family/doubleHashing.h
new file mode 100644
index 0000000..89390ad
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/Family/doubleHashing.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
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/Family/family.h b/SourceCode/BusinessLogic/Hash/Algorithm/Family/family.h
new file mode 100644
index 0000000..2f9eeed
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/Family/family.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
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/Family/pseudorandomProbing.h b/SourceCode/BusinessLogic/Hash/Algorithm/Family/pseudorandomProbing.h
new file mode 100644
index 0000000..d790ef7
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/Family/pseudorandomProbing.h
@@ -0,0 +1,44 @@
+#ifndef ALGHORITHM_PSEUDORANDOM_PROBING_H
+#define ALGHORITHM_PSEUDORANDOM_PROBING_H
+
+#include "family.h"
+
+#include
+
+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
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorLinearProbing.h b/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorLinearProbing.h
new file mode 100644
index 0000000..391b99f
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorLinearProbing.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 create() const override {
+ return std::unique_ptr(new Product(m_coefficient));
+ }
+
+};
+
+END_NAMESPACE // LinearProbing
+END_NAMESPACE // Algorithm
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !CREATOR_ALGHORITHM_LINEAR_PROBING_H
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorOne.h b/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorOne.h
new file mode 100644
index 0000000..de371a4
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorOne.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
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorQuadraticProbing.h b/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorQuadraticProbing.h
new file mode 100644
index 0000000..58c8add
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/One/creatorQuadraticProbing.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 create() const override {
+ return std::unique_ptr(new Product());
+ }
+};
+
+END_NAMESPACE // LinearProbing
+END_NAMESPACE // Algorithm
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !CREATOR_ALGHORITHM_QUADRATIC_PROBING_H
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/One/linearProbing.h b/SourceCode/BusinessLogic/Hash/Algorithm/One/linearProbing.h
new file mode 100644
index 0000000..a686dd4
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/One/linearProbing.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
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/One/one.h b/SourceCode/BusinessLogic/Hash/Algorithm/One/one.h
new file mode 100644
index 0000000..4878f09
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/One/one.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
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/One/quadraticProbing.h b/SourceCode/BusinessLogic/Hash/Algorithm/One/quadraticProbing.h
new file mode 100644
index 0000000..a36e9cb
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/One/quadraticProbing.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
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/abstract.h b/SourceCode/BusinessLogic/Hash/Algorithm/abstract.h
new file mode 100644
index 0000000..5bd4297
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/abstract.h
@@ -0,0 +1,101 @@
+#ifndef ALGHORITHM_ABSTRACT_H
+#define ALGHORITHM_ABSTRACT_H
+
+#include "../../Convert/convert.h"
+
+#include
+#include
+#include
+#include
+#include
+
+BEGIN_NAMESPACE(BusinessLogic)
+BEGIN_NAMESPACE(Hash)
+BEGIN_NAMESPACE(Algorithm)
+BEGIN_NAMESPACE(Abstract)
+
+class Product
+{
+public:
+ using value_type = std::array;
+
+private:
+ const std::vector *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(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 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::max();
+ }
+};
+
+END_NAMESPACE // Abstract
+END_NAMESPACE // Algorithm
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !ALGHORITHM_ABSTRACT_H
diff --git a/SourceCode/BusinessLogic/Hash/Algorithm/creatorAbstract.h b/SourceCode/BusinessLogic/Hash/Algorithm/creatorAbstract.h
new file mode 100644
index 0000000..7250a43
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Algorithm/creatorAbstract.h
@@ -0,0 +1,29 @@
+#ifndef CREATOR_ALGHORITHM_ABSTRACT_H
+#define CREATOR_ALGHORITHM_ABSTRACT_H
+
+#include "../../../BusinessLogic/businessLogic.h"
+
+#include
+
+BEGIN_NAMESPACE(BusinessLogic)
+BEGIN_NAMESPACE(Hash)
+BEGIN_NAMESPACE(Algorithm)
+BEGIN_NAMESPACE(Abstract)
+
+class Creator
+{
+protected:
+ Creator()
+ {
+ }
+
+public:
+ virtual std::unique_ptr create() const = 0;
+};
+
+END_NAMESPACE // Abstract
+END_NAMESPACE // Algorithm
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !CREATOR_ALGHORITHM_ABSTRACT_H
diff --git a/SourceCode/BusinessLogic/Hash/Factory/abstract.h b/SourceCode/BusinessLogic/Hash/Factory/abstract.h
new file mode 100644
index 0000000..505fb35
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Factory/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;
+ using AAC_type = std::shared_ptr;
+
+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 getAlgorithm() const = 0;
+};
+
+END_NAMESPACE // Factory
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !FACTORY_ABSTRACT_H
\ No newline at end of file
diff --git a/SourceCode/BusinessLogic/Hash/Factory/family.h b/SourceCode/BusinessLogic/Hash/Factory/family.h
new file mode 100644
index 0000000..ba5857b
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Factory/family.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;
+ using FAC_type = std::shared_ptr;
+
+ 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(m_functionCreator->create());
+ }
+ virtual std::unique_ptr getAlgorithm() const override {
+ std::unique_ptr algorithm = m_algorithmCreator->create();
+ dynamic_cast(algorithm.get())->setHashFunction(getFunction());
+ return algorithm;
+ }
+};
+
+END_NAMESPACE // Factory
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !FACTORY_FAMILY_H
diff --git a/SourceCode/BusinessLogic/Hash/Factory/one.h b/SourceCode/BusinessLogic/Hash/Factory/one.h
new file mode 100644
index 0000000..a9b2a3f
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Factory/one.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;
+ using OAC_type = std::shared_ptr;
+
+ 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(m_functionCreator->create());
+ }
+ virtual std::unique_ptr getAlgorithm() const override {
+ std::unique_ptr algorithm = m_algorithmCreator->create();
+ dynamic_cast(algorithm.get())->setHashFunction(getFunction());
+ return algorithm;
+ }
+};
+
+END_NAMESPACE // Factory
+END_NAMESPACE // Hash
+END_NAMESPACE // BusinessLogic
+
+#endif // !FACTORY_ONE_H
diff --git a/SourceCode/BusinessLogic/Hash/Function/Family/creatorFamily.h b/SourceCode/BusinessLogic/Hash/Function/Family/creatorFamily.h
new file mode 100644
index 0000000..019d4cc
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/Family/creatorFamily.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
diff --git a/SourceCode/BusinessLogic/Hash/Function/Family/creatorFnv1a.h b/SourceCode/BusinessLogic/Hash/Function/Family/creatorFnv1a.h
new file mode 100644
index 0000000..3ca1c90
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/Family/creatorFnv1a.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
diff --git a/SourceCode/BusinessLogic/Hash/Function/Family/family.h b/SourceCode/BusinessLogic/Hash/Function/Family/family.h
new file mode 100644
index 0000000..b6d8763
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/Family/family.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;
+
+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
diff --git a/SourceCode/BusinessLogic/Hash/Function/Family/fnv1a.h b/SourceCode/BusinessLogic/Hash/Function/Family/fnv1a.h
new file mode 100644
index 0000000..5c0f0e5
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/Family/fnv1a.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;
+
+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(value);
+ return static_cast(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
diff --git a/SourceCode/BusinessLogic/Hash/Function/One/creatorEquivalent.h b/SourceCode/BusinessLogic/Hash/Function/One/creatorEquivalent.h
new file mode 100644
index 0000000..dd98a69
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/One/creatorEquivalent.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
diff --git a/SourceCode/BusinessLogic/Hash/Function/One/creatorOne.h b/SourceCode/BusinessLogic/Hash/Function/One/creatorOne.h
new file mode 100644
index 0000000..3d06deb
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/One/creatorOne.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
diff --git a/SourceCode/BusinessLogic/Hash/Function/One/creatorStandart.h b/SourceCode/BusinessLogic/Hash/Function/One/creatorStandart.h
new file mode 100644
index 0000000..5287f84
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/One/creatorStandart.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
diff --git a/SourceCode/BusinessLogic/Hash/Function/One/equivalent.h b/SourceCode/BusinessLogic/Hash/Function/One/equivalent.h
new file mode 100644
index 0000000..9243ada
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/One/equivalent.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;
+
+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
diff --git a/SourceCode/BusinessLogic/Hash/Function/One/one.h b/SourceCode/BusinessLogic/Hash/Function/One/one.h
new file mode 100644
index 0000000..84bd552
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/One/one.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;
+
+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
diff --git a/SourceCode/BusinessLogic/Hash/Function/One/standart.h b/SourceCode/BusinessLogic/Hash/Function/One/standart.h
new file mode 100644
index 0000000..0d3a988
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/One/standart.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;
+
+class Product final : public One::Product, public Singleton
+{
+private:
+ std::hash m_standartHashFunction;
+
+private:
+ friend const Product &Singleton::getInstance();
+ Product()
+ : One::Product(
+ std::bind(&std::hash::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
diff --git a/SourceCode/BusinessLogic/Hash/Function/Pattern/creatorFamilyToOne.h b/SourceCode/BusinessLogic/Hash/Function/Pattern/creatorFamilyToOne.h
new file mode 100644
index 0000000..c242dd8
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/Pattern/creatorFamilyToOne.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 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
diff --git a/SourceCode/BusinessLogic/Hash/Function/Pattern/familyToOne.h b/SourceCode/BusinessLogic/Hash/Function/Pattern/familyToOne.h
new file mode 100644
index 0000000..e4380d7
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/Pattern/familyToOne.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
diff --git a/SourceCode/BusinessLogic/Hash/Function/abstract.h b/SourceCode/BusinessLogic/Hash/Function/abstract.h
new file mode 100644
index 0000000..8211502
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/abstract.h
@@ -0,0 +1,30 @@
+#ifndef FUNCTION_ABSTRACT_H
+#define FUNCTION_ABSTRACT_H
+
+#include "../../businessLogic.h"
+#include "../../Pattern/singleton.h"
+
+#include
+#include
+
+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
diff --git a/SourceCode/BusinessLogic/Hash/Function/creatorAbstract.h b/SourceCode/BusinessLogic/Hash/Function/creatorAbstract.h
new file mode 100644
index 0000000..1a7c5cd
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Function/creatorAbstract.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
diff --git a/SourceCode/BusinessLogic/Hash/Table/Pattern/subscriber.h b/SourceCode/BusinessLogic/Hash/Table/Pattern/subscriber.h
new file mode 100644
index 0000000..125b5b2
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Table/Pattern/subscriber.h
@@ -0,0 +1,58 @@
+#ifndef SUBSCRIBER_H
+#define SUBSCRIBER_H
+
+#include "../../../businessLogic.h"
+
+#include
+#include
+#include
+#include
+
+BEGIN_NAMESPACE(BusinessLogic)
+BEGIN_NAMESPACE(Hash)
+BEGIN_NAMESPACE(Table)
+BEGIN_NAMESPACE(Pattern)
+
+class InterfaceSubscriber
+{
+public:
+ virtual void successfulInsertion(const Table::Abstract *, const std::array &, std::pair, size_t) = 0;
+ virtual void unsuccessfulInsertion(const Table::Abstract *, const std::array &) = 0;
+};
+
+class Publisher
+{
+private:
+ std::vector 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 &value, std::pair 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 &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
diff --git a/SourceCode/BusinessLogic/Hash/Table/abstract.h b/SourceCode/BusinessLogic/Hash/Table/abstract.h
new file mode 100644
index 0000000..ec53e8c
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Table/abstract.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
+#include
+#include
+#include
+#include
+#include
+#include
+
+BEGIN_NAMESPACE(BusinessLogic)
+BEGIN_NAMESPACE(Hash)
+BEGIN_NAMESPACE(Table)
+
+class Abstract : public Pattern::Publisher
+{
+public:
+ using value_type = std::array;
+ 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
diff --git a/SourceCode/BusinessLogic/Hash/Table/chains.h b/SourceCode/BusinessLogic/Hash/Table/chains.h
new file mode 100644
index 0000000..dc87bcb
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Table/chains.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>;
+ 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::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 ¤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
diff --git a/SourceCode/BusinessLogic/Hash/Table/openAddress.h b/SourceCode/BusinessLogic/Hash/Table/openAddress.h
new file mode 100644
index 0000000..88628e4
--- /dev/null
+++ b/SourceCode/BusinessLogic/Hash/Table/openAddress.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;
+ 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 m_algorithm;
+
+public:
+ OpenAddressing(size_t size, const factory_type &factory, size_t alphabetPower = std::numeric_limits::max())
+ : Abstract(alphabetPower)
+ , m_numberOfCollision(size, std::numeric_limits::max())
+ , m_algorithm(factory.getAlgorithm())
+ {
+ constexpr std::array 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::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::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
diff --git a/SourceCode/BusinessLogic/Pattern/singleton.h b/SourceCode/BusinessLogic/Pattern/singleton.h
new file mode 100644
index 0000000..ed51914
--- /dev/null
+++ b/SourceCode/BusinessLogic/Pattern/singleton.h
@@ -0,0 +1,37 @@
+#ifndef SINGLETON_H
+#define SINGLETON_H
+
+#include "../businessLogic.h"
+
+#include
+
+BEGIN_NAMESPACE(BusinessLogic)
+BEGIN_NAMESPACE(Pattern)
+
+template
+class Singleton {
+private:
+ static std::unique_ptr m_singleton;
+
+public:
+ static const T &getInstance() {
+ if (m_singleton == nullptr) {
+ m_singleton = std::unique_ptr(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
+std::unique_ptr Singleton::m_singleton = nullptr;
+
+END_NAMESPACE // Pattern
+END_NAMESPACE // BusinessLogic
+
+#endif // SINGLETON_H
diff --git a/SourceCode/BusinessLogic/Statistics/dispersion.cpp b/SourceCode/BusinessLogic/Statistics/dispersion.cpp
new file mode 100644
index 0000000..9268aea
--- /dev/null
+++ b/SourceCode/BusinessLogic/Statistics/dispersion.cpp
@@ -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(size);
+ averageOfSquares += ( container[i] ) * ( container[i] ) / static_cast(size);
+ }
+ return averageOfSquares - average * average;
+}
+
+END_NAMESPACE // Statistics
+END_NAMESPACE // BusinessLogic
diff --git a/SourceCode/BusinessLogic/Statistics/dispersion.h b/SourceCode/BusinessLogic/Statistics/dispersion.h
new file mode 100644
index 0000000..bb9751d
--- /dev/null
+++ b/SourceCode/BusinessLogic/Statistics/dispersion.h
@@ -0,0 +1,25 @@
+#ifndef DISPERSION_H
+#define DISPERSION_H
+
+#include "../businessLogic.h"
+
+#include
+#include
+#include
+
+BEGIN_NAMESPACE(BusinessLogic)
+BEGIN_NAMESPACE(Statistics)
+
+class Dispersion {
+public: // Types
+ using value_type = size_t;
+ using container_type = std::vector;
+
+public:
+ long double operator()(const container_type &container, size_t size) const;
+};
+
+END_NAMESPACE // Statistics
+END_NAMESPACE // BusinessLogic
+
+#endif // DISPERSION_H
diff --git a/SourceCode/BusinessLogic/businessLogic.h b/SourceCode/BusinessLogic/businessLogic.h
new file mode 100644
index 0000000..48f6755
--- /dev/null
+++ b/SourceCode/BusinessLogic/businessLogic.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
+ class Singleton;
+ }
+
+ namespace Convert
+ {
+ class FromStdString;
+ }
+
+ namespace Statistics
+ {
+ class Dispersion;
+ }
+}
+
+#endif // BUSINESS_LOGIC_H
diff --git a/SourceCode/BusinessLogic/debug.cpp b/SourceCode/BusinessLogic/debug.cpp
new file mode 100644
index 0000000..c257293
--- /dev/null
+++ b/SourceCode/BusinessLogic/debug.cpp
@@ -0,0 +1,197 @@
+#include "hashHeaderFiles.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "Convert/convert.h"
+
+using namespace BusinessLogic::Hash;
+using namespace Function::Pattern;
+using namespace Table::Pattern;
+
+using factory_ptr = std::shared_ptr;
+
+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(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 &, std::pair, 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 &) override {
+ ++m_numberOfFailures;
+ }
+ virtual void filledInPart(const Table::Abstract *) override {
+ m_lastCoefficients = 0;
+ }
+};
+
+void runTable(std::unique_ptr table, size_t target) {
+ /* 26 letters */
+ constexpr char firstChar = ' ';
+ constexpr char endChar = '~';
+ size_t progress = 0;
+ std::array 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();
+ auto equivalent = std::make_shared();
+ auto standart = std::make_shared();
+
+ auto doubleHashing = std::make_shared(0, 1);
+ auto pseudorandomProbing = std::make_shared(0);
+ auto linearProbing = std::make_shared();
+ auto quadraticProbing = std::make_shared();
+
+ /* 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(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(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, quantityOfTables> results;
+ for(std::shared_ptr ¤t : results) {
+ current = std::make_shared(static_cast(numberOfInserts * alpha));
+ }
+
+/*
+ * Constants
+*/
+
+
+
+ std::array, quantityOfTables> tables {
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac1, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac2, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac3, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac4, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac5, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac6, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac7, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac8, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac9, alphabetPower) ),
+ std::unique_ptr( new Table::OpenAddressing(numberOfInserts, fac10, alphabetPower) ),
+ std::unique_ptr( new Table::Chains (numberOfBins, *equivalent, alphabetPower) ),
+ std::unique_ptr( new Table::Chains (numberOfBins, *standart, alphabetPower) ),
+ std::unique_ptr( new Table::Chains (numberOfBins, *simpleFNV1a, alphabetPower) ),
+ std::unique_ptr( 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;
+}
diff --git a/SourceCode/BusinessLogic/hashHeaderFiles.h b/SourceCode/BusinessLogic/hashHeaderFiles.h
new file mode 100644
index 0000000..0efc586
--- /dev/null
+++ b/SourceCode/BusinessLogic/hashHeaderFiles.h
@@ -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
diff --git a/SourceCode/ManualHTML/Images/demonstration.png b/SourceCode/ManualHTML/Images/demonstration.png
new file mode 100644
index 0000000..4759c8b
Binary files /dev/null and b/SourceCode/ManualHTML/Images/demonstration.png differ
diff --git a/SourceCode/ManualHTML/Images/menubarFirst.png b/SourceCode/ManualHTML/Images/menubarFirst.png
new file mode 100644
index 0000000..3a28472
Binary files /dev/null and b/SourceCode/ManualHTML/Images/menubarFirst.png differ
diff --git a/SourceCode/ManualHTML/Images/menubarSecond.png b/SourceCode/ManualHTML/Images/menubarSecond.png
new file mode 100644
index 0000000..24e8985
Binary files /dev/null and b/SourceCode/ManualHTML/Images/menubarSecond.png differ
diff --git a/SourceCode/ManualHTML/Images/testingPage.png b/SourceCode/ManualHTML/Images/testingPage.png
new file mode 100644
index 0000000..0e880af
Binary files /dev/null and b/SourceCode/ManualHTML/Images/testingPage.png differ
diff --git a/SourceCode/ManualHTML/Images/theory.png b/SourceCode/ManualHTML/Images/theory.png
new file mode 100644
index 0000000..b0fbb3a
Binary files /dev/null and b/SourceCode/ManualHTML/Images/theory.png differ
diff --git a/SourceCode/ManualHTML/Images/theoryPage.png b/SourceCode/ManualHTML/Images/theoryPage.png
new file mode 100644
index 0000000..f409a2a
Binary files /dev/null and b/SourceCode/ManualHTML/Images/theoryPage.png differ
diff --git a/SourceCode/ManualHTML/Pages/demonstration.html b/SourceCode/ManualHTML/Pages/demonstration.html
new file mode 100644
index 0000000..d0c2de2
--- /dev/null
+++ b/SourceCode/ManualHTML/Pages/demonstration.html
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+ Demonstration
+
+
+ Руководство пользователя
+ Система демонстрации
+
+ Данный раздел - описание существующих возможностей взаимодействия с
+ системой демонстрации изученного материала.
+ На рисунке 3.1 виден весь основной интерфейс пользователя, необходимый для
+ полноценного комфортного взаимодействия с данной системой.
+
+
+

+
+ Рисунок 2.1 - система демонстрации вставки элемента в хеш-таблицу
+
+
+
+ Каждая цифра указывает на определённый интерфейс пользователя, где даётся
+ его описание:
+
+
+ -
+ Табличное представление модели, которое заполняется ранее
+ вставленными в хеш-таблицу элементами в порядке их хранения в самой
+ хей-таблице.
+
+ -
+ График, показывающий тенденцию изменения коэффициента простого
+ равномерного хеширования на протяжении процесса вставки элементов в
+ хеш-таблицу.
+
+ -
+ График, показывающий тенденцию изменения количества коллизий на
+ протяжении процесса вставки элементов в хеш-таблицу.
+
+ -
+ Группирующий блок, позволяющий изменять способ решения проблем
+ коллизий хеш-таблицы.
+
+ -
+ Группирующий блок, позволяющий изменять применяемую в процессе вставки
+ элемента хеш-функцию.
+
+ -
+ Группирующий блок, позволяющий изменять применяемую в процессе вставки
+ элемента алгоритм, применяемый в попытке решения колизии на основе
+ таблицы с открытой адрессацией.
+
+ -
+ Сгруппированный интерфейс, позволяющий создать новую хеш-таблицу с
+ указанием размера первоначального контейнера, сбросить действительную
+ хеш-таблицу, запросить последнюю статистику по операциям вставки
+ элементов
+
+ -
+ Сгруппированный интерфейс, позволяющий создавать инструкции по вставке
+ новых элементов в хеш таблицу несколькими способами: n-ое количество
+ элементов разных элементов и один единственный, где задаётся первый
+ элемент. Так же существует возможность поиска первого несуществующего
+ элемента хеш-таблице, остановки процесса вставки элементов в
+ хеш-таблцицу, фокусирования графиков для полного отображения информации.
+ Каждая функция соответствует своей кнопке данного сгруппированного
+ интерфейса.
+
+ -
+ Вывод информации о действиях пользователя и результатах хеширования
+ элементов.
+
+ -
+ Масштабирование всех видов, вплоть до освобождения места для
+ определённого вида с целью его более детального рассмотрения.
+ Существвует возможность полного масштабирования одного вида, взамен
+ скрытия всех остальных.
+
+
+
+
diff --git a/SourceCode/ManualHTML/Pages/main.html b/SourceCode/ManualHTML/Pages/main.html
new file mode 100644
index 0000000..407a2d3
--- /dev/null
+++ b/SourceCode/ManualHTML/Pages/main.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+ Main
+
+
+ Руководство пользователя
+
+ Предоставление помощи пользователю
+ в использовании демонстрационной программы:
+ "Алгоритм вставки в хеш-таблицу"
+
+
+ Данное руководство предназначено пользователю для лучшего понимания работы
+ программы и взаимодействия с ней.
+
+ Оглавление:
+
+ -
+ Раздел теории
+
+
+ - Раздел тестирования
+ - Полоса или строка меню
+
+
+
diff --git a/SourceCode/ManualHTML/Pages/menubar.html b/SourceCode/ManualHTML/Pages/menubar.html
new file mode 100644
index 0000000..cf33894
--- /dev/null
+++ b/SourceCode/ManualHTML/Pages/menubar.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+ Menubar
+
+
+ Руководство пользователя
+ Полоска или строка меню
+
+ Данный раздел - описание существующих возможностей взаимодействия с
+ посолкой или строкой меню данной программы.
+ На рисунке 5.1 и 5.2 отображены подменю, каждое из которых группирует
+ определённые действия.
+
+
+

+
+ Рисунок 5.1 - подменю выбора текущего раздела
+
+
+
+
+
Рисунок 5.2 - подменю предоставления помощи
+
+
+ Первое подменю (см. рис. 5.1) необходимо для переключения разделов -
+ раздел теории, который включает две системы (система теории и система
+ демонстрации) и раздел тестирования.
+
+
+ Каждая цифра указывает на определённый интерфейс пользователя, где даётся
+ его описание:
+
+
+ -
+ Действие подменю, необходимое для переключения вида на раздел теории.
+
+ -
+ Действие подменю, необходимое для переключения вида на раздел практики.
+
+ -
+ Действие подменю, необходимое для открытия модального диалогового окна -
+ руководства пользователя.
+
+ -
+ Действие подменю, необходимое для открытия модального диалогового окна,
+ которое содержит информацию об использующимся программой фреймворке
+ Qt.
+
+
+
+
diff --git a/SourceCode/ManualHTML/Pages/testingPage.html b/SourceCode/ManualHTML/Pages/testingPage.html
new file mode 100644
index 0000000..25eb3f6
--- /dev/null
+++ b/SourceCode/ManualHTML/Pages/testingPage.html
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+ PracticPage
+
+
+ Руководство пользователя
+ Система тестирования
+
+ Данный раздел - описание существующих возможностей взаимодействия с
+ системой тестирования.
+ На рисунке 4.1 виден весь основной интерфейс пользователя, необходимый для
+ полноценного комфортного взаимодействия с данной системой.
+
+
+

+
Рисунок 4.1 - система тестирования
+
+
+ Каждая цифра указывает на определённый интерфейс пользователя, где даётся
+ его описание:
+
+
+ -
+ Отображаемый текст, как текущий вопрос с описанием ввода правильного
+ ответа и самого тестового задания.
+
+ -
+ Панель ввода правильного ответа. Может представлять
+ определённое количество флагов для указания множественного
+ ответа из множества альтернатив (от 5-и до 9-и), поле ввода целого
+ числа или числа с плавающей точкой.
+
+ -
+ Нажимная кнопка для подтверждения ответа и проверки его на корректность.
+
+ -
+ Выходная информация, как способ идентификации успешного / безуспешного
+ начала тестирования с указанием конкретной ошибки, завершения
+ тестирования и успешного / безуспешного ответа на предыдущий вопрос.
+
+ -
+ Нажимная кнопка, реализующая начало тестирования.
+
+ -
+ Нажимная кнопка, реализующая предварительное завершение тестирования.
+
+ -
+ Группирующий интерфейс необходимый для выбора типа предоставляемых
+ вопросов в процессе тестирования.
+
+ -
+ Группирующий интерфейс необходимый для выбора сложности
+ предоставляемых вопросов в процессе тестирования.
+
+
+
+ Стоит отметить, что результат тестирования сохраняется в бинарном файле
+ (формат записи смотри в технической документации), когда тестирование
+ завершается после окончания подходящих под критерии вопросов или решения
+ пользователя, при нажатии соответствующей кнопки.
+
+
+
diff --git a/SourceCode/ManualHTML/Pages/theory.html b/SourceCode/ManualHTML/Pages/theory.html
new file mode 100644
index 0000000..494e169
--- /dev/null
+++ b/SourceCode/ManualHTML/Pages/theory.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+ Theory
+
+
+ Руководство пользователя
+ Система теории
+
+ Данный раздел - описание существующих возможностей взаимодействия с
+ системой изучения теоретического материала.
+ На рисунке 2.1 виден весь основной интерфейс пользователя, необходимый для
+ полноценного комфортного взаимодействия с данной системой.
+
+
+

+
+ Рисунок 2.1 - система изучения теоретического материала
+
+
+
+ Каждая цифра указывает на определённый интерфейс пользователя, где даётся
+ его описание:
+
+
+ -
+ Нажимная кнопка, при нажатии которой пользователь переходит на следующую
+ страницу теоретического материала. Доступна, если отображается не
+ главная и не последняя страницы.
+
+ -
+ Нажимная кнопка, при нажатии которой пользователь переходит на главную
+ страницу теоретического материала. Доступна, если не отображается
+ главная страница.
+
+ -
+ Нажимная кнопка, при нажатии которой пользователь переходит на
+ предыдущую страницу теоретического материала. Доступна, если
+ отображается не главная и не первая страницы.
+
+ -
+ Нажимная кнопка, позволяющая отобразить предыдущую небольшую
+ доступную часть отображаемой страницы.
+
+ -
+ Ползунок, при перемещении которого можно перейти к любой части
+ отображаемой страницы.
+
+ -
+ Нажимная кнопка, позволяющая отобразить следующую небольшую
+ доступную часть отображаемой страницы.
+
+ -
+ Гиперссылка оглавления, при нажатии на которую пользователь может
+ перейти к любой интересующей его теме, которая описывается в отдельной
+ страцице.
+
+
+
+
diff --git a/SourceCode/ManualHTML/Pages/theoryPage.html b/SourceCode/ManualHTML/Pages/theoryPage.html
new file mode 100644
index 0000000..bad99ce
--- /dev/null
+++ b/SourceCode/ManualHTML/Pages/theoryPage.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+ TheoryPage
+
+
+ Руководство пользователя
+ Раздел теории
+
+ Данный раздел - первое, что видит пользователь, при первом запуске
+ программы.
+ На рисунке 1.1 виден весь основной интерфейс пользователя, необходимый для
+ перехода в ту или иную систему.
+
+
+

+
Рисунок 1.1 - раздел теории и практики
+
+ Всего существует три системы:
+
+ - Теории.
+ - Демонстрации.
+ - Тестирования.
+
+
+ Основой графического интерфейса пользователя являются нажимаемые кнопки,
+ переключающие между собой вкладки, флажки множественного или одиночного
+ выборов, и другие элементы, которые будут обсуждаться по мере описания
+ данного руководства. Каждая цифра указывает на определённый интерфейс
+ пользователя, где даётся его описание:
+
+
+ -
+ Раздел изучения теоретического материала, необходимый для понимания темы
+ "Алгоритм вставки элемента в хеш-таблицу".
+
+ -
+ Раздел демонстрации вставки элемента в хеш-таблицу.
+
+ -
+ Полоса или строка меню, как единственный способ переключения фокуса
+ между системами теории, которая подразумевает включение системы
+ демонстрации, и тестирования.
+
+
+
+
diff --git a/SourceCode/ManualHTML/info.xml b/SourceCode/ManualHTML/info.xml
new file mode 100644
index 0000000..5ed8729
--- /dev/null
+++ b/SourceCode/ManualHTML/info.xml
@@ -0,0 +1,13 @@
+
+
+ :/ManualHTML/Pages
+ :/ManualHTML/Images
+
+ main.html
+ theoryPage.html
+ theory.html
+ demonstration.html
+ testingPage.html
+ menubar.html
+
+
diff --git a/SourceCode/UserInterface/ClassesUI/Validator/validator.h b/SourceCode/UserInterface/ClassesUI/Validator/validator.h
new file mode 100644
index 0000000..cc99f55
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Validator/validator.h
@@ -0,0 +1,21 @@
+#ifndef LATIN_VALIDATOR_H
+#define LATIN_VALIDATOR_H
+
+#include
+
+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
diff --git a/SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.cpp b/SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.cpp
new file mode 100644
index 0000000..a10b9ab
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.cpp
@@ -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(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 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(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(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(
+ progress * static_cast(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") +
+ "
" +
+ 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 factory;
+ bool functionTypeIsFamily =
+ getCurrentFunctionType() == RelationshipType::Family;
+ if (getCurrentAlgorythmType() == RelationshipType::One) {
+ factory = std::make_unique(
+ functionTypeIsFamily
+ ? m_complicatedFunction // The complicated function must be prepared
+ : std::dynamic_pointer_cast(m_pFunction),
+ std::dynamic_pointer_cast(m_pAlgorithm));
+ } else if (functionTypeIsFamily) {
+ factory = std::make_unique(
+ std::dynamic_pointer_cast(m_pFunction),
+ std::dynamic_pointer_cast(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();
+ } else if (m_rbStandart->isChecked()) {
+ m_pFunction = std::make_shared();
+ } else { // m_rbFNV1a32bit->isChecked()
+ m_pFunction = std::make_shared();
+ }
+}
+
+inline void DemonstrationWidget::updateAlgorithmCreator() {
+ using namespace BusinessLogic::Hash::Algorithm;
+ if (m_rbLinearProbing->isChecked()) {
+ m_pAlgorithm = std::make_shared();
+ } else if (m_rbQuadraticProbing->isChecked()) {
+ m_pAlgorithm = std::make_shared();
+ } else if (m_rbPseudorandomProbing->isChecked()) {
+ m_pAlgorithm = std::make_shared(
+ m_sbFirstInputData->value());
+ } else { // m_rbDoubleHashing->isChecked()
+ m_pAlgorithm = std::make_shared(
+ 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(
+ std::dynamic_pointer_cast(m_pFunction),
+ m_sbFirstInputData->value());
+ }
+
+ size_t bucketQuantity = m_sbBucketQuantity->value();
+ try {
+ if (tableTypeIsChain) {
+ m_pTable = std::make_unique(
+ bucketQuantity,
+ functionTypeIsFamily
+ ? *m_complicatedFunction
+ : *std::dynamic_pointer_cast(m_pFunction),
+ m_alphabetPower);
+ } else {
+ auto factory = getCurrentFactory();
+ m_pTable = std::make_unique(
+ 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{
+ 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{
+ m_leFrom, m_sbQuantity, m_pbMakeItems, m_leInsert, m_pbInsert,
+ m_pbReset, m_pbStatistics, m_pbFindFree}) {
+ widget->setEnabled(flag);
+ }
+ m_pbStop->setDisabled(flag);
+}
diff --git a/SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.h b/SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.h
new file mode 100644
index 0000000..d274746
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.h
@@ -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
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+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 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(target);
+ QChart *chart = view->chart();
+
+ switch (event->type()) {
+ case QEvent::Wheel: {
+ QWheelEvent *currentEvent = dynamic_cast(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 m_pFunction;
+ std::shared_ptr
+ m_complicatedFunction;
+ std::shared_ptr
+ m_pAlgorithm;
+ size_t m_alphabetPower;
+ std::unique_ptr m_pTable;
+ TableInformation m_tableInformation;
+
+ /*
+ * HTML tags
+ */
+ static constexpr auto m_fontBeginColorHTML = R"()";
+ static constexpr auto m_fontEndHTML = R"()";
+
+public:
+ DemonstrationWidget(QWidget *pWidget = nullptr);
+
+public: // Custom slots
+ virtual void successfulInsertion(const table_type *, const value_type &,
+ std::pair, 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("");
+ auto children = splitter->children();
+ QList sizes{dynamic_cast(children[0])->minimumHeight(),
+ dynamic_cast(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
diff --git a/SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.cpp b/SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.cpp
new file mode 100644
index 0000000..0eacc6f
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.cpp
@@ -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(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(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(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("%1
").arg(element.text()));
+ } break;
+ case TagXML::Text: {
+ currentQuestion.append(QString(R"(
+
+
+
+ %2
+
+
+
+ )")
+ .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(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 &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(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();
+}
diff --git a/SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.h b/SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.h
new file mode 100644
index 0000000..b674109
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.h
@@ -0,0 +1,71 @@
+#ifndef TESTING_WIDGET_H
+#define TESTING_WIDGET_H
+
+#include "ui_testingWidget.h"
+
+#include
+
+#include
+#include
+#include
+
+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> 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
diff --git a/SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.cpp b/SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.cpp
new file mode 100644
index 0000000..7fd8842
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.cpp
@@ -0,0 +1,112 @@
+#include "textBrowserWidget.h"
+
+TextBrowserWidget::TextBrowserWidget(const QString &xmlFile, QWidget *pWidget)
+ : QWidget(pWidget)
+{
+ setupUi(dynamic_cast(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]);
+ }
+}
diff --git a/SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.h b/SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.h
new file mode 100644
index 0000000..3dbe0c4
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.h
@@ -0,0 +1,50 @@
+#ifndef THEORY_WIDGET_H
+#define THEORY_WIDGET_H
+
+#include "ui_textBrowserWidget.h"
+
+#include
+#include
+#include
+
+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
diff --git a/SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.cpp b/SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.cpp
new file mode 100644
index 0000000..97e1fe5
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.cpp
@@ -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 newData;
+ for(const auto &value : std::initializer_list>{
+ {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( 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(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();
+ });
+}
diff --git a/SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.h b/SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.h
new file mode 100644
index 0000000..ded194d
--- /dev/null
+++ b/SourceCode/UserInterface/ClassesUI/Windows/MainWindow/mainWindow.h
@@ -0,0 +1,29 @@
+#ifndef MAIN_WINDOW_H
+#define MAIN_WINDOW_H
+
+#include "ui_mainWindow.h"
+
+#include
+#include
+#include
+#include
+
+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
diff --git a/SourceCode/UserInterface/FilesUI/demonstrationWidget.ui b/SourceCode/UserInterface/FilesUI/demonstrationWidget.ui
new file mode 100644
index 0000000..2b163f1
--- /dev/null
+++ b/SourceCode/UserInterface/FilesUI/demonstrationWidget.ui
@@ -0,0 +1,972 @@
+
+
+ DemonstrationWidget
+
+
+
+ 0
+ 0
+ 805
+ 460
+
+
+
+
+ 0
+ 0
+
+
+
+ Form
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Plain
+
+
+ 1
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Progress of inserting elements:
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ false
+ false
+ false
+ false
+ true
+
+
+
+ 100000
+
+
+ 0
+
+
+
+
+
+
+
+
+ 501
+ 0
+ 250
+ 250
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 250
+ 0
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 234
+ 1020
+
+
+
+
+ 0
+ 0
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Resolution of collisions
+
+
+
-
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Chains
+
+
+ true
+
+
+
+ -
+
+
+ Open addressing
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Function
+
+
+
-
+
+
+ Equivalent
+
+
+ true
+
+
+
+ -
+
+
+ Standart
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ FNV1a 32 bit
+
+
+
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+ Algorithm
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Linear probing
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Pseudorandom probing
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Quadratic probing
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Double hashing
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Additional input data
+
+
+
-
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ Coefficient of the first family function:
+
+
+ true
+
+
+ m_sbFirstInputData
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ 100000000
+
+
+ 1
+
+
+ QAbstractSpinBox::DefaultStepType
+
+
+ 0
+
+
+ 16
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+ Coefficient of the second family function:
+
+
+ true
+
+
+ m_sbSecondInputData
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ 100000000
+
+
+ 1
+
+
+ QAbstractSpinBox::DefaultStepType
+
+
+ 1
+
+
+ 16
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Hash table
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Bucket quantity:
+
+
+ m_sbBucketQuantity
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 1
+
+
+ 10000
+
+
+ 1
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Reset
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Apply
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+ Statistics
+
+
+
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+ Load table
+
+
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 0
+
+
+
+ From:
+
+
+ m_leFrom
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 0
+
+
+
+ Quantity:
+
+
+ m_sbQuantity
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 1
+
+
+ 10000
+
+
+ 1
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 150
+ 16777215
+
+
+
+ Qt::ImhNone
+
+
+ 4
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Make items
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 0
+
+
+
+ Value:
+
+
+ m_leInsert
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 4
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Insert
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
-
+
+
+ Find free
+
+
+
+ -
+
+
+ false
+
+
+ Stop
+
+
+
+
+
+ -
+
+
+ Focus
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::MinimumExpanding
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::Box
+
+
+ QFrame::Plain
+
+
+ 1
+
+
+ 0
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Output messages:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ Consolas
+ 10
+ 75
+ true
+
+
+
+ Qt::DefaultContextMenu
+
+
+ false
+
+
+
+
+
+ Qt::ImhNone
+
+
+ QFrame::Box
+
+
+ QFrame::Plain
+
+
+ 1
+
+
+ 0
+
+
+
+
+
+ Qt::RichText
+
+
+ true
+
+
+ 0
+
+
+ Qt::NoTextInteraction
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 500
+ 250
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 300
+ 200
+
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+ QAbstractItemView::SingleSelection
+
+
+ QAbstractItemView::ScrollPerPixel
+
+
+ QAbstractItemView::ScrollPerPixel
+
+
+ Qt::SolidLine
+
+
+ false
+
+
+ false
+
+
+
+
+ m_tableView
+ m_rightScrollArea
+ m_rbChains
+ m_rbOpenAdressing
+ m_rbEquivalent
+ m_rbStandart
+ m_rbFNV1a32bit
+ m_rbLinearProbing
+ m_rbPseudorandomProbing
+ m_rbQuadraticProbing
+ m_rbDoubleHashing
+ m_sbFirstInputData
+ m_sbSecondInputData
+ m_sbBucketQuantity
+ m_pbReset
+ m_pbApply
+ m_pbStatistics
+ m_leFrom
+ m_sbQuantity
+ m_pbMakeItems
+ m_leInsert
+ m_pbInsert
+ m_pbFindFree
+ m_pbStop
+ m_pbFocus
+
+
+
+
+ m_rbChains
+ clicked(bool)
+ m_gbAlgorithm
+ setDisabled(bool)
+
+
+ 861
+ 45
+
+
+ 858
+ 225
+
+
+
+
+ m_rbOpenAdressing
+ clicked(bool)
+ m_gbAlgorithm
+ setEnabled(bool)
+
+
+ 887
+ 78
+
+
+ 892
+ 219
+
+
+
+
+
diff --git a/SourceCode/UserInterface/FilesUI/mainWindow.ui b/SourceCode/UserInterface/FilesUI/mainWindow.ui
new file mode 100644
index 0000000..c2c2b40
--- /dev/null
+++ b/SourceCode/UserInterface/FilesUI/mainWindow.ui
@@ -0,0 +1,261 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1093
+ 548
+
+
+
+ Hash tables
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Plain
+
+
+ 1
+
+
+ 0
+
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ 0
+
+
+
+ Theory
+
+
+
+
+ Demonstration
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ &Exit
+
+
+
+
+
+
+
+
+
+
+
+ &User session
+
+
+ User session
+
+
+ Ctrl+N
+
+
+
+
+ &Open...
+
+
+ Ctrl+O
+
+
+
+
+ true
+
+
+ &Save
+
+
+ Ctrl+S
+
+
+
+
+ Save &As...
+
+
+
+
+ &Options...
+
+
+
+
+ &Manual
+
+
+ Ctrl+H
+
+
+
+
+ About this &program
+
+
+ Ctrl+A
+
+
+
+
+ &Theory
+
+
+ Ctrl+T
+
+
+
+
+ &Practice
+
+
+ Ctrl+P
+
+
+
+
+ &General
+
+
+
+
+ false
+
+
+ &Current
+
+
+
+
+
+ TestingWidget
+ QWidget
+ SourceCode/UserInterface/ClassesUI/Widgets/Testing/testingWidget.h
+ 1
+
+
+ DemonstrationWidget
+ QWidget
+ SourceCode/UserInterface/ClassesUI/Widgets/Demonstration/demonstrationWidget.h
+ 1
+
+
+ TextBrowserWidget
+ QWidget
+ SourceCode/UserInterface/ClassesUI/Widgets/TextBrowser/textBrowserWidget.h
+ 1
+
+
+
+ m_tabWidget
+ m_exitButton
+
+
+
+
+ m_exitButton
+ clicked()
+ MainWindow
+ close()
+
+
+ 1044
+ 503
+
+
+ 935
+ 524
+
+
+
+
+
diff --git a/SourceCode/UserInterface/FilesUI/testingWidget.ui b/SourceCode/UserInterface/FilesUI/testingWidget.ui
new file mode 100644
index 0000000..43f26f3
--- /dev/null
+++ b/SourceCode/UserInterface/FilesUI/testingWidget.ui
@@ -0,0 +1,381 @@
+
+
+ TestingWidget
+
+
+
+ 0
+ 0
+ 716
+ 545
+
+
+
+ Form
+
+
+ -
+
+
-
+
+
+ <html><head/><body><p><span style=" font-size:10pt;">Testing window:</span></p></body></html>
+
+
+ m_testingTextBrowser
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+ 1
+
+
+ 0
+
+
+
+
-
+
+
+ Choose your answer:
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+ -
+
+
+ CheckBox
+
+
+
+
+
+
+
+ -
+
+
+ Enter an integer number:
+
+
+ m_sbInteger
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ Enter a fractional number:
+
+
+ m_sbInteger
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Confirm answer
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ 7
+
+
+ QLayout::SetDefaultConstraint
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Choosing a topic
+
+
+
-
+
+
+ Everything
+
+
+ true
+
+
+
+ -
+
+
+ Discrete mathematics
+
+
+ false
+
+
+
+ -
+
+
+ Hash function
+
+
+
+ -
+
+
+ Hash table
+
+
+
+ -
+
+
+ Algorithm
+
+
+
+
+
+
+ -
+
+
+ Choice of difficulty
+
+
+
-
+
+
+ Everything
+
+
+ true
+
+
+
+ -
+
+
+ Easy
+
+
+
+ -
+
+
+ Medium
+
+
+
+ -
+
+
+ Hard
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Start testing
+
+
+
+ -
+
+
+ false
+
+
+ Save && Stop testing
+
+
+
+
+
+
+
+
+ m_testingTextBrowser
+ m_pbStart
+ m_pbStop
+ m_sbInteger
+ m_pbConfirm
+ m_rbAllTopics
+ m_rbDiscreteMathematics
+ m_rbHashFunction
+ m_rbHashTable
+ m_rbAlgorithm
+ m_rbAllDifficulties
+ m_rbEasy
+ m_rbMedium
+ m_rbHard
+ m_sbDouble
+
+
+
+
diff --git a/SourceCode/UserInterface/FilesUI/textBrowserWidget.ui b/SourceCode/UserInterface/FilesUI/textBrowserWidget.ui
new file mode 100644
index 0000000..00a05c7
--- /dev/null
+++ b/SourceCode/UserInterface/FilesUI/textBrowserWidget.ui
@@ -0,0 +1,91 @@
+
+
+ TextBrowserWidget
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Form
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ false
+
+
+ Previous
+
+
+
+ -
+
+
+ false
+
+
+ Main
+
+
+
+ -
+
+
+ false
+
+
+ Next
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+
+ Times New Roman
+ 16
+
+
+
+
+
+
+
+
+
diff --git a/SourceCode/main.cpp b/SourceCode/main.cpp
new file mode 100644
index 0000000..531ee0d
--- /dev/null
+++ b/SourceCode/main.cpp
@@ -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();
+}
diff --git a/SourceCode/resources.qrc b/SourceCode/resources.qrc
new file mode 100644
index 0000000..bb6e571
--- /dev/null
+++ b/SourceCode/resources.qrc
@@ -0,0 +1,17 @@
+
+
+ ManualHTML/info.xml
+ ManualHTML/Pages/demonstration.html
+ ManualHTML/Pages/main.html
+ ManualHTML/Pages/menubar.html
+ ManualHTML/Pages/theory.html
+ ManualHTML/Pages/theoryPage.html
+ ManualHTML/Pages/testingPage.html
+ ManualHTML/Images/demonstration.png
+ ManualHTML/Images/menubarFirst.png
+ ManualHTML/Images/menubarSecond.png
+ ManualHTML/Images/testingPage.png
+ ManualHTML/Images/theory.png
+ ManualHTML/Images/theoryPage.png
+
+
diff --git a/TheoryHTML/Images/2.1.png b/TheoryHTML/Images/2.1.png
new file mode 100644
index 0000000..9192e82
Binary files /dev/null and b/TheoryHTML/Images/2.1.png differ
diff --git a/TheoryHTML/Images/2.2.png b/TheoryHTML/Images/2.2.png
new file mode 100644
index 0000000..1eb085c
Binary files /dev/null and b/TheoryHTML/Images/2.2.png differ
diff --git a/TheoryHTML/Images/6.1.png b/TheoryHTML/Images/6.1.png
new file mode 100644
index 0000000..c4b92ab
Binary files /dev/null and b/TheoryHTML/Images/6.1.png differ
diff --git a/TheoryHTML/Images/7.1.png b/TheoryHTML/Images/7.1.png
new file mode 100644
index 0000000..c77346f
Binary files /dev/null and b/TheoryHTML/Images/7.1.png differ
diff --git a/TheoryHTML/Images/7.2.png b/TheoryHTML/Images/7.2.png
new file mode 100644
index 0000000..a5e9f03
Binary files /dev/null and b/TheoryHTML/Images/7.2.png differ
diff --git a/TheoryHTML/Images/8.1.png b/TheoryHTML/Images/8.1.png
new file mode 100644
index 0000000..5343bb5
Binary files /dev/null and b/TheoryHTML/Images/8.1.png differ
diff --git a/TheoryHTML/Pages/analysis.html b/TheoryHTML/Pages/analysis.html
new file mode 100644
index 0000000..7c97a8b
--- /dev/null
+++ b/TheoryHTML/Pages/analysis.html
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+ Страница 8
+
+
+
+ Страница 8
+
+
+ Анализ хеш-таблиц и алгоритмов поиска
+ Общее описание [2, c. 285-318]
+
+ Хеш-таблица представляет собой эффективную структуру данных для реализации
+ словарей. Хотя на поиск элемента в хеш-таблице может в наихудшем случае
+ потребоваться столько же времени, сколько на поиск в связанном списке, а
+ именно - Θ(n), на практике хеширование исключительно
+ эффективно. При вполне обоснованных допущениях среднее время поиска
+ элемента в хеш-таблице составляет O(1).
+
+
+ Таблица с прямой адресацией, как хеш-таблица
+
+
+ Хеш-таблица обобщает обычный массив. Возможность прямой индексации
+ элементов обычного массива обеспечивает доступ к произвольной позиции в
+ массиве за время O(1). Хеширование представляет собой исключительно
+ эффективную и практичную технологию: в среднем все базовые словарные
+ операции выполняются за время O(1).
+
+
+ Недостаток прямой адресации очевиден: если совокупность ключей
+ U велика, хранение таблицы T размером
+ |U| непрактично, а то и вовсе невозможно - в зависимости от
+ количества доступной памяти и размера совокупности ключей. Кроме того,
+ множество K реально сохранённых ключей может быть мало по сравнению
+ с совокупностью ключей U, а в этом случае память, выделенная для
+ таблицы T, в основном расходуется напрасно.
+
+
+ Когда множество K хранящихся в словаре ключей гораздо меньше
+ совокупности возможных ключей U, для хеш-таблицы требуется
+ существенно меньше места, чем для таблицы с прямой адресацией1.
+ Точнее говоря, требования к памяти могут быть снижены
+ до Θ(/K/), при этом время поиска элемента в хеш-таблице
+ останется равным O(1). Нужно только заметить, что это граница
+ времени поиска в среднем случае, в то время как в случае таблицы с прямой
+ адресацией эта граница справедлива для наихудшего случая.
+
+ Хеш-таблица с прямым связыванием
+
+ Время, необходимое для вставки в наихудшем случае, равно O(1).
+ Процедура вставки выполняется очень быстро, в частности, потому, что
+ предполагается, что вставляемый элемент отсутствует в таблице. Время
+ работы поиска в наихудшем случае пропорционально длине списка. Удаление
+ элемента может быть выполнено за время O(1) при использовании
+ дважды связанных списков.
+
+
+ Пусть у нас есть хеш-таблица T с m ячейками, в которых хранятся n
+ элементов. В наихудшем случае хеширование с цепочками ведёт себя крайне
+ неприятно: все n ключей хешированы в одну и ту же ячейку, создав список
+ длиной n. Таким образом, время поиска в наихудшем случае равно Θ(n)
+ плюс время вычисления хеш-функции, что ничуть не лучше, чем в случае
+ использования связного списка для хранения всех n элементов. Понятно, что
+ использование хеш-таблиц в наихудшем случае совершенно бессмысленно.
+
+ Теорема 8.12
+
+ В хеш-таблице с разрешением коллизий методом цепочек время неудачного
+ поиска в среднем случае в предположении простого равномерного хеширования
+ составляет Θ(1 + a).
+
+ Теорема 8.2
+
+ В хеш-таблице с разрешением коллизий методом цепочек время успешного
+ поиска в среднем случае в предположении простого равномерного хеширования
+ в среднем равно Θ(1 + a).
+
+
+ Если количество ячеек в хеш-таблице как минимум пропорционально количеству
+ элементов, хранящихся в ней, то n = O(m) и, следовательно,
+ коэффициент заполнения равен n/m = O(m)/m = O(1). Таким
+ образом, поиск элемента в хеш-таблице в среднем требует постоянного
+ времени. Поскольку в худшем случае вставка элемента в хеш-таблицу занимает
+ O(1) времени (как и удаление элемента при использовании дважды связанных
+ списков), можно сделать вывод, что все словарные операции в хеш-таблице в
+ среднем выполняются за время O(1).
+
+ Хеш-таблица с открытой адресацией
+
+ Мы проанализируем математическое ожидание количества исследований для
+ хеширования с открытой адресацией в предположении равномерного хеширования
+ и начнём с анализа количества исследований в случае неудачного поиска.
+
+ Теорема 8.3
+
+ Математическое ожидание количества исследований при неудачном поиске в хеш
+ таблице с открытой адресацией и коэффициентом заполнения
+ a = n/m < 1 в предположении равномерного хеширования не
+ превышает 1/(1-a).
+
+ Следствие 8.1
+
+ Вставка элемента в хеш-таблицу с открытой адресацией и коэффициентом
+ заполнения a в предположении равномерного хеширования требует в среднем не
+ более 1/(1-a) исследований.
+
+ Теорема 8.4
+
+ Математическое ожидание количества исследований при удачном поиске в
+ хеш-таблице с открытой адресацией и коэффициентом заполнения a < 1, в
+ предположении равномерного хеширования и равновероятного поиска любого из
+ ключей не превышает
+
+
+

+
+
+
+
+ 1В данном контексте автор, упоминая таблицу с прямой
+ адресацией, не применяет термин хеш, так как, предположительно, в примере
+ оригинальной книги не используется хеш-функция для операций поиска
+ элемента или все операции вставки элемента являются инъективными и не
+ нуждаются в решении проблем коллизий.
+
+
+ 2Все доказательства теорем представлены в книге автора с целью
+ описания минимума методического материала
+
+
+
diff --git a/TheoryHTML/Pages/binaryRelationship.html b/TheoryHTML/Pages/binaryRelationship.html
new file mode 100644
index 0000000..37fe6c4
--- /dev/null
+++ b/TheoryHTML/Pages/binaryRelationship.html
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+ Страница 2
+
+
+
+ Страница 2
+
+
+ Дискретная математика
+
+ Функция, как тип бинарных отношений [4, c. 96-100]
+
+
+ Отношения эффективно применяются для описания связей между парами
+ элементов, выбранных из двух множеств А и В. Функции —
+ это частный случай бинарных отношений, на которые наложены дополнительные
+ ограничения.
+
+
+ Функцией из множества А в множество В называется бинарное
+ отношение, при котором каждый элемент множества А связан с
+ единственным элементом множества В. Другими словами, для каждого
+ a ∈ A существует ровно одна пара из отношения
+ вида (а, b).
+
+
+ В графических терминах функция описывается таким графом, у которого из
+ каждой вершины, изображающей элементы множества A, выходит
+ ровно одна стрелка.
+
+
+ Например, на рис. 2.1 изображен граф, представляющий функцию из множества
+ {а, b, с} в {1, 2}, состоящую из пар (а, 1),
+ (b, 1) и (с, 2).
+
+

+
Рисунок 2.1 - функция из множества
+
+
+
+ Пусть f - функция из множества A в множество B.
+ Поскольку для каждого x ∈ A существует единственным
+ образом определённый y∈ B, такой, что
+ (x, y) ∈ f, мы будем писать: y = f(x), и говорить, что
+ функция f отображает множество A в множество
+ B, а f(x) называть образом x при отображении
+ f или значением f, соответствующим аргументу
+ x.
+
+
+ Кроме того, можно написать f : A → B, чтобы
+ подчеркнуть, что функция f переводит элементы из A в
+ элементы из B. Множество A принято называть
+ областью определения, а B -
+ областью значений функции1 f.
+
+
+ Для уточнения подмножества элементов, в которые переводятся элементы из
+ A функцией f, вводят понятие "образ" или
+ "множество значений функции". А именно,
+ множеством значений функции f называется подмножество в
+ B, состоящее из образов всех
+ элементов x ∈ A. Оно обозначается символом
+ f(A) и формально определяется так:
+
+
+ f(A) = {f(x) : x ∈ A}
+
+
+ Свойства функций
+
+ Пусть f : A → B - функция. Мы будем называть её
+ инъективной или инъекцией, или взаимно однозначной,
+ если
+
+
+ f(a1) = f(a2) ⇒ a1 = a2
+
+
+ для всех a1, a2 ∈ A.
+
+
+ Это определение логически эквивалентно тому, что
+
+
+ a1 ≠ a2 ⇒ f(a1) ≠ f(a2),
+
+
+ т.е. у инъективной функции нет повторяющихся значений. Иными словами,
+ разные входные данные дают различные выходные данные.
+
+
+ Будем называть функцию f сюръективной или сюръекцией,
+ или функцией "на", если множество её значений совпадает с
+ областью значений. Это означает, что для каждого
+ b ∈ B найдётся такой a ∈ A,
+ что b = f(a). Таким образом, каждый элемент области значений
+ является образом какого-то элемента из области определения f .
+
+
+ Мы называем f биективной функцией или просто
+ биекцией, если она как инъективна, так и сюръективна.
+
+
+ На рисунке 2.2 представлены различные виды функций.
+
+

+
Рисунок 2.2 - различные виды функций
+
+ Описание:
+
+ -
+ В случае (a) функция не инъективна, поскольку значение 1 соответствует
+ как a, так и b. Она не является и сюръективной, ввиду того, что в
+ элемент 2 ничего не переходит.
+
+ -
+ В случае (б) функция инъективна, так как не имеет повторяющихся
+ значений. Она же и сюръективна, поскольку множество ее значений
+ совпадает со всей областью значений.
+
+ -
+ Значение 1 эта функция в случае (в) принимает как на а, так и на Ь.
+ Следовательно, она не инъективна. Однако данная функция сюръективна,
+ поскольку в ее множество значений входят все элементы области значений.
+
+ - Последняя функция в случае (г) инъективна, но не сюръективна.
+ - Только в случае (б) мы имеем биекцию.
+
+
+
+ 1Довольно часто говорят, что функция f определена или задана на
+ множестве A со значениями в множестве B. - Прим. перев.
+
+
+
diff --git a/TheoryHTML/Pages/chainMethod.html b/TheoryHTML/Pages/chainMethod.html
new file mode 100644
index 0000000..c514c5f
--- /dev/null
+++ b/TheoryHTML/Pages/chainMethod.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+ Страница 6
+
+
+
+ Страница 6
+
+
+ Решение проблем коллизий
+ Метод цепочек или прямое связывание [5, c. 170-171]
+
+ В хеш таблице с прямым связыванием (рис 6.1) значения ключей (бункеры)
+ хранятся в специальных наборах записей, называемых блоками. Каждый
+ из них является вершиной связного списка, в котором находятся привязанные
+ к блоку элементы.
+
+
+

+
Рисунок 6.1 - хеш-таблица с прямым связыванием
+
+
+ Поиск элементов в хеш-таблице пройдёт быстрее, если связанные списки будут
+ содержать ключи в отсортированном порядке. В этом случае алгоритм сделает
+ вывод, что ключа нет, если дойдёт до значения больше ключевого и не станет
+ просматривать список до конца. Теоретически время его работы составит
+ O(N/B), но на практике оно будет немного меньше.
+
+
+ Чтобы найти нужный элемент, программе необходимо хешировать ключ и
+ определить, в каком из блоков он может содержаться, а затем двигаться по
+ связному списку до тех пор, пока не будет достигнут его конец или не
+ обнаружится искомое. Если вы доберётесь до конца списка, значит,
+ запрашиваемого элемента в хеш-таблице нет. Как и в случае с добавлением
+ элемента, предстоит выполнить O(N/B) шагов.
+
+
+ Хеш-таблица с прямым связыванием может расширяться и сжиматься1
+ по мере необходимости, поэтому вам не нужно специально изменять её размер.
+ Однако если связные списки станут слишком длинными, поиск и удаление
+ элементов займут много времени. В этом случае вам понадобится увеличить
+ таблицу, чтобы создать больше блоков. Поскольку при рехешировании таблицы
+ не надо проводить поиск дубликатов до конца связного списка в каждом
+ блоке, полностью справиться с операцией можно за время O(N).
+
+
+
+ 1Удаление элементов в данном методическом материале
+ рассматриваться не будет
+
+
+
diff --git a/TheoryHTML/Pages/dirichletPrinciple.html b/TheoryHTML/Pages/dirichletPrinciple.html
new file mode 100644
index 0000000..644bfec
--- /dev/null
+++ b/TheoryHTML/Pages/dirichletPrinciple.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+ Страница 3
+
+
+
+ Страница 3
+
+
+ Дискретная математика
+ Принцип Дирихле [4, c. 105]
+
+ Пусть f : A → B -
+ функция, причём как A, так и B - конечные множества.
+ Предположим, что A состоит из n элементов:
+ a1, a2,..., an. Принцип Дирихле гласит, что если |A| > |B|, то по крайней
+ мере одно значение f встретится более одного раза1.
+ Проще говоря, найдётся пара элементов
+ ai ≠ aj, для которых f(ai) = f(aj).
+
+
+ Чтобы убедиться в истинности принципа, предположим, что для любой пары
+ разных индексов
+ i ≠ j мы имеем:
+ f(ai) ≠ f(aj). Тогда множество B содержит по крайней
+ мере n различных элементов:
+ f(a1), f(a2),..., f(an). И уж во
+ всяком случае, |B| ≥ n, что противоречит
+ предположению: n = |A| > |B|. Следовательно, есть хотя бы два
+ разных элемента
+ ai, aj ∈ A, для которых f(ai) = f(aj).
+
+
+
+ 1Допуская некоторую вольность, принцип Дирихле можно
+ переформулировать в легко запоминающейся форме: нельзя рассадить 10 зайцев
+ в 9 клеток так, чтобы в каждой клетке сидел один заяц - Прим. перев.
+
+
+
diff --git a/TheoryHTML/Pages/hashFunction.html b/TheoryHTML/Pages/hashFunction.html
new file mode 100644
index 0000000..c50ec6a
--- /dev/null
+++ b/TheoryHTML/Pages/hashFunction.html
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+ Страница 4
+
+
+
+ Страница 4
+
+
+ Хеш-фукнция
+ Свойства хеш-функции
+
+ Хеш-функция (англ. hash function от hash —
+ «превращать в фарш»), или функция свёртки —
+ функция, осуществляющая преобразование массива входных данных
+ произвольной длины в выходную битовую строку установленной
+ длины, выполняемое определённым алгоритмом. Преобразование,
+ производимое хеш-функцией, называется хешированием. Исходные данные
+ называются входным массивом, «ключом» или
+ «сообщением». Результат преобразования называется
+ «хешем», «хеш-кодом», «хеш-суммой»,
+ «сводкой сообщения».[7]
+
+ Свойства хеш-функции:
+
+ - Должна обладать свойствами функции.
+ -
+ Не должна обязательно являться инъективной или сюръективной.
+
+
+ Определения :
+
+ -
+ Если известна область определения и можно задать отображение в область
+ значений, мощность которого будет больше или эквивалентна мощности
+ области определения, при котором хеш-функция будет являться
+ инъективной, то такая хеш-функция будет являться идеальной хеш-функцией.
+
+ -
+ Если область определения неизвестна и можно задать отображение в
+ область значений, мощность которого будет больше или эквивалентна
+ мощности области определения, при котором хеш-функция будет
+ являться инъективной, то такая хеш-функция будет являться динамической идеальной хеш-функцией.
+
+ -
+ Если известна область определения и можно задать отображение в
+ область значений, мощность которого будет эквивалентна мощности
+ области определения, при котором хеш-функция будет
+ являться биективной, то такая хеш-функция будет являться
+ минимальной идеальной хеш-функцией.
+
+ -
+ Хеш-функция является k-совершенной хеш-функцией,
+ если область определения неизвестна и можно задать отображение в
+ область значений, любой элемент которого будет обладать не более чем k
+ отношениями.
+
+
+
+ Существует несколько терминов, связанных с хеш-функцией:
+
+
+ - Хеш
+ -
+ элемент области значений, соотнесённый с заранее известным элементом из
+ области определения.
+
+ - Хеширование
+ - это процесс получения хеша.
+ - Коллизия
+ -
+ ситуация, при которой нарушается условие инъективности хеш-функции.
+
+
+
+ Производительность хеширования в среднем случае зависит от того, насколько
+ хорошо хеш-функция приближена к биективной k-совершенной хеш-функции, где
+ разность количества отношейний любых двух элементов области значений
+ стремиться к нулю. Другими словами, каждый элемент области значений
+ обладает минимально возможным количеством отношений. Данное хеширование
+ автор книги [2, с. 291] Томас Кормен называет
+ простым равномерным хешированием.
+
+
+ Существует множество разнообразных хеш-функций, алгоритмы которых
+ применяются в различных ситуациях, например, когда требуется скорость
+ вычисления хеш-значения, но с повышенным шансом появления коллизии или
+ наоборот.
+
+
+
diff --git a/TheoryHTML/Pages/hashTable.html b/TheoryHTML/Pages/hashTable.html
new file mode 100644
index 0000000..39ad099
--- /dev/null
+++ b/TheoryHTML/Pages/hashTable.html
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+ Страница 5
+
+
+
+ Страница 5
+
+
+ Хеш-таблица
+ Свойства хеш-таблицы
+
+ Хеш-таблицы являются одним из способов хранения данных при помощи
+ ассоциативного массива [12].
+
+
+ Хеш-таблицы решают несколько главных проблем при оперировании с данными:
+
+
+ -
+ Создание отношения (связи) между ключом и абсолютно любым
+ значением.
+
+ - Решение проблем коллизий.
+
+
+ Для большего понимания материала требуется ознакомиться с новыми терминами
+ хеш-таблицы:
+
+
+ - Ключ или сообщение
+ - использующийся хеш-таблицей произвольный элемент из области определения хеш-функции.
+ - Бункер или корзина
+ - произвольный элемент, который хранит данные хеш-таблицы.
+ - Коэффициент заполнения
+ -
+ отношение количества заполненных бункеров на количество возможных ключей.
+
+
+
+ Исходя из определений, бункер - это условная единица хранимой информации в
+ хеш-таблице (ассоциативном массиве данных).
+
+
+ Решение первой проблемы. Хеш-функции в хеш-таблице, нужны по причине получения хеша в процессе
+ хеширования ключа, однако хеш - значение абстрактное, так как невозможно
+ создать такой алгоритм, который бы выдавал хеш, как набор данных,
+ используемый в процессе работы программы или это очень сложно.
+ Для большего понимания нужно вспомнить пример о "продавце в маленьком магазинчике", где "помощница"
+ абстрагирует понятие хеш-функции, которая выдавала для каждого товара
+ конкретную цену, что возможно, но трудозатратно.
+ Для этого требуется хеш-функция, где хеш является универсальным
+ идентификатором конкретного бункера, в котором располагается необходимый
+ пользователю набор данных.
+
+
+ Томас Кормен говорит в книге [2, c.288], что цель хеш-функции состоит в
+ том, чтобы уменьшить рабочий диапазон индексов массива - размер массива
+ может быть равен соотносительно намного меньшему значению, чем мощность
+ множества всех существующих значений ключей, которые могут потенциально
+ использоваться в процессе работы программы.
+
+
+ Из этого можно выделить несколько особенностей хеш-таблиц:
+
+
+ -
+ Каждый бункер имеет в качестве уникального идентификатора
+ хеш-значение
+
+ -
+ Каждый ключ гарантированно имеет связь только с одним бункером.
+
+ -
+ Количество бункеров относительно количества ключей сильно ограниченно.
+
+ -
+ От хеш-функции зависит коэффициент заполнения.
+
+ -
+ По принципу Дирихле коллизия неизбежна в ситуации, когда количество ключей больше, чем количество бункеров.
+
+
+
+ Решение второй проблемы. Хеш-таблицы используют в качестве
+ алгоритма поиска элемента контейнера (бункера) хеш-функцию, которая по
+ принципу Дирихле гарантированно создаст коллизии в ситуации, когда
+ количество ключей больше, чем количество бункеров, а обычно так бывает
+ всегда.
+
+
+ Хеш-таблицы решают данную проблему двумя способами:
+
+
+ - Метод цепочек или прямым связыванием.
+ - Открытой адресацией.
+
+
+
diff --git a/TheoryHTML/Pages/introduction.html b/TheoryHTML/Pages/introduction.html
new file mode 100644
index 0000000..1ae6bce
--- /dev/null
+++ b/TheoryHTML/Pages/introduction.html
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+ Страница 1
+
+
+
+ Страница 1
+
+
+ Введение
+ Гардероб [3, с. 393-394]
+
+ Когда вы сдаете в гардероб пальто или сумку, вам выдают номерок. Когда же
+ вы собираетесь покинуть помещение, вы отдаете номерок, и вам возвращают
+ ваше пальто или сумку.
+
+
+ Если вдуматься, какую задачку решает данный процесс, можно увидеть, что
+ это задача о поиске и нахождении объекта. Ваше пальто — это объект,
+ который вы передаете гардеробщику; пальто сначала привязывают к
+ определенному номерку, а затем возвращают вам. Метод работает за счет
+ того, что в гардеробе находятся ряды пронумерованных вешалок для одежды и
+ пронумерованные отделения для сумок. Вашему номерку соответствует
+ определенная вешалка или определенное отделение. Гардеробщик же отвечает
+ за то, чтобы разместить ваш объект в нужном месте и чтобы забрать его с
+ помощью отданного вами номерка.
+
+
+ Когда речь идет о поиске, люди чаще всего представляют себе, что нужно
+ перебирать вещи до тех пор, пока не найдется нужная; процесс становится
+ проще, если вещи отсортированы так, что мы можем искать среди них более
+ слаженно. Гардероб же показывает, что есть и другой способ: присвоить вещи
+ адрес, где она будет располагаться, и затем сразу достать ее из указанного
+ места. В гардеробе адрес указан на номерках, и гардеробщик на самом деле
+ ищет не ваши вещи: он смотрит на номерок, на адрес и идет к указанной
+ вешалке или отделению с вашими вещами.
+
+
+ Весь метод в целом можно назвать определением местонахождения
+ без поиска: мы не ищем объект, а получаем адрес места, где он будет
+ храниться. Соотносим объект с адресом, а затем, когда хотим найти объект,
+ мы идем прямиком к нужному месту.
+
+
+ Теперь рассмотрим данный метод с точки зрения компьютерного мира, где наши
+ объекты представлены в виде записей, содержащих атрибуты. Мы хотим уметь
+ переходить напрямую от записи к адресу, по которому она размещена;
+ адресом будет число, соответствующее области в компьютерной памяти.
+ Главная загвоздка в такой задачке — то, как соотнести адрес с
+ элементом. Нам нужен быстрый и надежный способ, и мы не можем положиться
+ на какого-либо посредника. Когда мы ищем запись, мы ищем ее по одному или
+ большему числу атрибутов, которые формируют ключ записи, поэтому нам нужен
+ метод получения адреса из ключа записи. Так как адрес — это число,
+ нам нужен способ, который перенесет нас от ключей к числам. Иными словами,
+ мы нуждаемся в функции, скажем, f(K), которая возьмет ключ K записи
+ R и вернет значение a = f(K). Значение a представляет собой адрес,
+ где будет храниться запись, мы идем по нему и оставляем там нашу запись.
+ Каждый раз, когда нам требуется достать нашу запись с помощью ключа, мы
+ снова прибегаем к функции f(K), которая вернет то же адресное
+ значение a, откуда мы и заберем нашу запись. Функция должна быть быстрой и
+ достаточно скоро находить нужный адрес: как минимум, не дольше, чем поиск
+ по записям до тех пор, пока не найдется та, которую мы ищем. В противном
+ случае толку от такой функции никакого. Если же мы в самом деле
+ обзаведемся такой функцией, то разрешим нашу задачку с местоположением
+ новым способом: не мы будем искать элемент, а сам элемент расскажет нам,
+ где его найти: расскажет с помощью нашей функции.
+
+ Продавец
+
+ Так же стоит привести введение в теоретический материал, описанное автором
+ книги [1, c. 100-101], где описывается пример с "продавцом в
+ маленьком магазинчике".
+
+
+ В ситуации, когда клиент покупает
+ у продавца товар необходимо определить ценность предмета.
+ Изначально стоит отметить, что цены в магазинах на один и тот же товар
+ всегда одинаковый в один момент времени, поэтому необходимо хранить
+ информацию о ценах, например, в книге, однако данный метод оперирования
+ информацией будет весьма утомителен и ужасно неэффективен. Для
+ решения этой проблемы продавец нанимает помощницу, которая
+ безошибочно определяет цену на товар, если посмотрит на него или узнает
+ его название.
+
+
+ Автор абстрактно описывает проблему с упорядоченным контейнером данных,
+ где может потребоваться простой поиск, алгоритм которого обладает линейной
+ сложностью. В данном примере контейнер является хранилищем элементов,
+ каждый из которых может повторяться, но обязан иметь только один
+ уникальный идентификатор. Можно с уверенностью выделить две проблемы, от
+ которых можно избавиться в идеальных условиях — затраты на
+ хранение элементов и поиск каждого из них при помощи уникального
+ идентификатора. В приоритете необходимо выполнять успешный поиск элемента,
+ алгоритм которого будет выполняться за константное время.
+
+
+ Решением является использование функции [4, c. 96] из множества A в
+ множество B. Данная функция описывает бинарное отношение, при
+ котором каждый элемент множества А связан с
+ единственным элементом множества B. Данная функция в
+ программировании имеет название хеш-функция. Избавиться от необходимости в
+ хранении множеств элементов, чтобы сохранялась возможность определять
+ новые бинарные отношения, не изменяя другие очень сложно, однако это
+ возможно. Обычно, когда известны все элементы множества А и все
+ элементы множества B, реализуют функцию, при которой любой элемент
+ множества А имеет одно отношение с любым элементом из множества
+ B. Например, данную функцию можно применить в примере с продавцом и
+ помощницей, если каталог товаров не изменяется, но цены на разные товары
+ могут совпадать.
+
+
+
diff --git a/TheoryHTML/Pages/main.html b/TheoryHTML/Pages/main.html
new file mode 100644
index 0000000..a53dde1
--- /dev/null
+++ b/TheoryHTML/Pages/main.html
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+ Теоретический материал
+
+
+ Теоретический материал
+
+
+ Необходимый минимум теории по теме
+ "Алгоритм вставки в хеш-таблицу"
+
+
+ Описание страницы:
+
+
+ Главная страница, предоставляющая пользователю быстрый и удобный поиск
+ нужного разбитого по темам материала.
+ Каждый элемент списка оглавления является гиперссылкой при нажатии на
+ которую можно мгновенно перейти к необходимому разделу информации.
+ Предоставленный пользователю теоретический материал был взят из списка
+ использованной литературы в конце данной страницы.
+
+
+ Оглавление:
+
+
+ -
+ Введение.
+
+ - Дискретная математика:
+
+
+ -
+ Хеш-функция.
+
+
+ -
+ Хеш-таблица.
+
+ - Решение проблем коллизий:
+
+
+ - Анализ хеш-таблиц и алгоритмов поиска.
+
+
+ Список использованной литературы
+
+
+ -
+ Бхаргава, А. Грокаем алгоритмы. Иллюстрированное пособие для
+ программистов и любопытствующих / Адитья Бхаргава. — СПб. :
+ Питер, 2017. - 288 с. : ил. — (Библиотека программиста).
+
+ -
+ Кормен, Т. Х. Алгоритмы: построение и анализ, 3-е изд / Томас Кормен ; пер. с англ. — Москва :
+ ООО "И. Д. Вильямс", 2013. — 1328 с. : ил. — Парал. тит. англ.
+
+ -
+ Луридас, П. Алгоритмы для начинающих : теория и практика для
+ разработчика / Панос Луридас ; пер. с англ. Е.М. Егоровой. — Москва :
+ Эксмо, 2020. — 608 с. — (Мировой компьютерный бестселлер).
+
+ -
+ Хаггарти, Р. Дискретная математика для программистов, 2-е издание, исправленное / Род
+ Стивенс. — Москва : ТЕХНОСФЕРА, 2019. — 400 c.
+
+ -
+ Стивенс, Р. Алгоритмы. Теория и практическое применение / Род
+ Стивенс. — Москва : Издательство "Э", 2016. — 544 c. — (Мировой
+ компьютерный бестселлер).
+
+ -
+ Хеш-таблица [Электронный ресурс]: Википедия. Свободная энциклопедия.
+ — URL: https://ru.wikipedia.org/wiki/Хеш-таблица (дата обращения: 03.11.2021).
+
+ -
+ Хеш-функция [Электронный ресурс]: Википедия. Свободная энциклопедия.
+ — URL: https://ru.wikipedia.org/wiki/Хеш-функция (дата обращения: 03.11.2021).
+
+ -
+ Хеш-функция, что это такое? [Электронный ресурс]: Хабр. Сообщество
+ IT-специалистов. — URL: https://habr.com/ru/post/534596/
+ (дата обращения: 03.11.2021).
+
+ -
+ Хеш-таблицы [Электронный ресурс]: Хабр. Сообщество IT-специалистов. —
+ URL: https://habr.com/ru/post/509220/
+ (дата обращения: 03.11.2021).
+
+ -
+ Хеш-таблицы [Электронный ресурс]: CodeChick. Задачи по
+ программированию с проверкой. — URL: https://codechick.io/tutorials/dsa/dsa-hash-table (дата обращения: 03.11.2021).
+
+ -
+ Fowler–Noll–Vo hash function [Электронный ресурс]: Википедия.
+ Свободная энциклопедия. — URL: https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function (дата обращения: 03.11.2021).
+
+ -
+ Ассоциативный массив [Электронный ресурс]: Википедия.
+ Свободная энциклопедия. — URL: https://ru.wikipedia.org/wiki/Ассоциативный_массив (дата обращения: 06.11.2021).
+
+
+
+
diff --git a/TheoryHTML/Pages/openAddressing.html b/TheoryHTML/Pages/openAddressing.html
new file mode 100644
index 0000000..3b608a8
--- /dev/null
+++ b/TheoryHTML/Pages/openAddressing.html
@@ -0,0 +1,274 @@
+
+
+
+
+
+
+ Страница 7
+
+
+
+ Страница 7
+
+
+ Решение проблем коллизий
+
+ Открытая и прямая адресации [5, c. 170-179]
+
+ Оглавление:
+
+
+
+
+ Безусловно, прямое связывание имеет свои преимущества. Основное из них
+ заключается в том, что общее количество значений не зависит от
+ количества блоков. Однако есть у таких хеш-таблиц и некоторые
+ недостатки. Например, если элементов в блоках накопится слишком много,
+ поиск нужного займет продолжительное время. Чтобы сократить временные
+ затраты, число блоков можно увеличить, но тогда вы рискуете получить ряд
+ пустых, которые потребуют места в памяти и не будут использоваться
+ таблицей.
+
+
+ Еще один способ реализации хеш-таблиц — открытая адресация.
+ В этом случае значения хранятся в массиве, а функция хеширования
+ представляет собой некоторые расчеты.
+
+
+ Хеш-таблица с прямой адресацией отличается от хеш-таблицы с
+ открытой адресацией тем, что в первом случае гарантировано должна
+ использоваться идеальная хеш-функция. Это обусловлено тем, что в данной
+ хеш-таблице должны отсутствовать коллизии, соответственно, как и методы
+ их разрешения. Стоит отметить, что под данное описание подходит
+ идеальное хеширование хеш-таблицы1.
+
+
+ В разных видах открытой адресации используются различные функции
+ хеширования. Неодинакова и политика разрешения коллизий, но в общем
+ случае она выглядит так: для каждого значения в массиве подбирается
+ несколько ячеек, и если первая уже занята, алгоритм пробует использовать
+ вторую, затем третью и так до тех пор, пока не найдет свободную или не
+ придет к выводу, что таковой нет.
+
+
+ Серия ячеек, которую алгоритм подбирает для значения, называется пробной
+ последовательностью. По ее средней длине хорошо оценивать наполненность
+ хештаблицы. В идеале пробная последовательность должна равняться 1 или
+ 2, большие цифры говорят о полной таблице.
+
+
+ Иногда политика разрешения коллизий такова, что для элемента может не
+ найтись свободной ячейки, даже когда она есть. Если пробная
+ последовательность повторяет саму себя перед тем, как проверить
+ очередную запись, некоторые записи могут остаться неиспользованными.
+
+
+ Чтобы найти элемент в хеш-таблице, алгоритм следует за пробной
+ последовательностью, пока не произойдет одно из трех событий.
+
+
+ -
+ Если пробная последовательность сумела отыскать элемент, задача
+ выполнена.
+
+ -
+ Если пробная последовательность находит пустую запись в массиве,
+ элемента нет.
+
+ -
+ Пробная последовательность проверяет M записей (по размеру
+ массива) — и алгоритм приходит к выводу, что значение
+ отсутствует. Последовательность может перебрать не все элементы, но
+ если пройдет по всем, вы будете знать, что они точно пересмотрены или
+ что целевой элемент не найден. Она также может проверить в цикле одну
+ и ту же позицию несколько раз. В любом случае значение не должно
+ присутствовать, поскольку иначе оно бы добавлялось к массиву с
+ использованием той же пробной последовательности.
+
+
+
+ При разумном заполнении хеш-таблицы открытая адресация работает очень
+ быстро. Если длина пробной последовательности равна 1 или 2, добавление
+ и нахождение элементов выполняются за время O(1). Но если массив
+ из N элементов существенно переполнен, производительность снижается. В
+ наихудшем случае алгоритм придет к выводу, что элемента в массиве нет,
+ за время O(N). Поиск присутствующих элементов также будет
+ выполняться крайне медленно.
+
+
+ Вы можете увеличить размер массива, чтобы уменьшить коэффициент
+ наполненности хеш-таблицы. Для этого создайте новый массив и рехешируйте
+ элементы в нем. Для каждого из них операция займет O(1) времени,
+ а общая производительность алгоритма составит O(N).
+
+
+
+
+
+ В линейном пробировании политика разрешения коллизий добавляет к каждой
+ ячейке постоянное число (чаще всего 1), называемое шагом по индексу,
+ которое генерирует пробную последовательность. При каждом очередном
+ добавлении берется размер массива по модулю, стало быть, при
+ необходимости последовательность возвращается к началу массива.
+
+
+ Предположим, в хеш-таблице 100 элементов, а правило хеширования звучит
+ следующим образом: N связано с ячейкой N mod 100. Тогда пробная
+ последовательность для значения 2197 проверяет ячейки 97, 98, 99, 0, 1,
+ 2 и т. д.
+
+
+ На рисунке 7.1 представлен массив из 10 записей, который уже содержит
+ несколько значений. Чтобы добавить в него новое значение 71, используя
+ линейную пробную последовательность, нужно связать его с ячейкой 71 mod
+ 10 = 1. Но эта ячейка уже занята значением 61, поэтому алгоритм
+ переходит к ячейке 2, которая тоже заполнена. Следующей должна быть
+ ячейка 3 — она свободна, и алгоритм размещает там 71.
+
+
+

+
+ Рисунок 7.1 - линейная пробная последовательность
+
+
+
+ Преимущество данного метода — в его простоте. Если необходимо,
+ пробная последовательность пройдет по каждой ячейке массива и вставит
+ элемент в свободное место, если оно еще осталось. Но есть и
+ сопутствующий недостаток — так называемая
+ первичная кластеризация, которая проявляется в образовании
+ больших блоков смежных записей и приводит к длинным пробным
+ последовательностям. В результате при добавлении нового элемента и его
+ хешировании к какой-либо записи в кластере пробная последовательность
+ вынуждена пройти через весь кластер, чтобы найти свободную ячейку.
+
+
+ Чтобы понять, как формируются кластеры, рассмотрим пример пустой
+ хеш-таблицы. Предположим, в ней содержится N записей и существует
+ вероятность 1/N, что она закончится в любой данной позиции при
+ добавлении случайного числа. А теперь представим, что K —
+ конечная позиция таблицы. Существует вероятность 1/N, что новое
+ случайное число попадет в позицию K и линейное пробирование попытается
+ расположить элемент в позиции K + 1. Но та же вероятность
+ характерна и для случая, при котором новый элемент будет связан с
+ позицией K + 1 напрямую. Значит, существует вероятность
+ 2/N, что элемент займет конечную позицию K + 1 и
+ сформируется малый кластер.
+
+
+ Через какое-то время таких кластеров станет много. Чем больше они будут,
+ тем больше вероятность того, что новый элемент добавится в конец одного
+ из них. В итоге более мелкие кластеры сольются в более крупные, массив
+ заполнится ими — и возникнут длинные пробные последовательности.
+
+
+
+
+
+ Возникновение больших кластеров при линейном пробировании связано с тем,
+ что новые элементы связываются с ячейками, стоящими в конце группы, и
+ постепенно увеличивают ее. Предотвратить подобную ситуацию помогает
+ квадратичное пробирование. Для создания пробной
+ последовательности в качестве шага по индексу берется квадрат количества
+ ячеек. Другими словами, если в линейном пробировании существует
+ последовательность K, K + 1, K + 2, K + 3, ... то в квадратичном
+ варианте она будет выглядеть так:
+ K, K + 12, K + 22, K + 32, ... В этом случае, если два
+ элемента окажутся связанными с разными позициями в одном и том же
+ кластере, они не обязательно будут придерживаться одной пробной
+ последовательности и попадут в конец кластера.
+
+
+ На рисунке 7.2 показана хеш-таблица, в начале которой есть группа из
+ пяти элементов. Новое значение 71 получает пробную последовательность
+ 1, 1 + 12 = 2, 1 + 22 = 5, 1 + 32 = 10 и не добавляется к
+ существующему кластеру. Значение 93 поначалу связано с тем же
+ кластером, но согласно собственной пробной последовательности
+ 3, 3 + 12 = 4, 3 + 22 = 7 также не попадает в него.
+
+
+

+
Рисунок 7.2 - Квадратичное пробирование
+
+
+ Квадратичное пробирование предотвращает первичную, но не
+ вторичную кластеризацию, при которой значения, связанные с
+ одинаковой начальной позицией в массиве, получают одну и ту же пробную
+ последовательность, иногда очень длинную. В результате образуется точно
+ такая же группа элементов, но уже не собранных вместе, а распределенных
+ по всему массиву.
+
+
+ Еще один недостаток квадратичного пробирования связан с тем, что оно
+ может не найти свободную позицию, даже если в хеш-таблице их несколько.
+ Дело в том, что с каждым разом перемещение по массиву происходит все
+ дальше и дальше, и незаполненная ячейка попросту пропускается.
+
+
+
+
+
+ Это пробирование подобно линейному, за исключением того, что шаг по
+ индексу формирует псевдослучайная функция изначально связанной ячейки.
+ Предположим, что это ячейка K, тогда пробная последовательность
+ будет выглядеть следующим образом: K, K + p, K + 2p, ... где p
+ определяется псевдослучайной функцией.
+
+
+ Подобно квадратичному пробированию, псевдослучайное предотвращает только
+ первичную кластеризацию, но страдает от вторичной: значения, связанные с
+ одной и той же начальной позицией, размещаются в хеш-таблице согласно
+ одной и той же пробной последовательности. Точно так же псевдослучайное
+ пробирование может пропускать некоторые неиспользуемые записи.
+
+
+
+
+
+ Чтобы избавиться от вторичной кластеризации значения, связанные с одной
+ и той же начальной ячейкой, должны получать разные пробные
+ последовательности. И здесь пригодится двойное хеширование. Оно похоже
+ на псевдослучайное пробирование, только шаг для индекса задается не
+ псевдослучайной функцией начальной ячейки, а второй функцией
+ хеширования.
+
+
+ Допустим, значения A и B связаны с позицией K. В
+ псевдослучайном пробировании шаг по индексу p генерируется
+ функцией F1 (K), затем оба значения используют пробную
+ последовательность K, K + p, K + 2p, K + 3p, ... В двойном
+ хешировании для связывания начальных значений А и
+ В применяется функция псевдослучайного хеширования
+ F2. В итоге при одном и том же начальном K образуются две пробные
+ последовательности с различными шагами по индексу:
+ pA = F2 (A) и
+ pB = F2 (B) соответственно.
+
+
+ Несмотря на то, что двойное хеширование хорошо справляется с первичной и
+ вторичной кластеризациями, оно точно так же, как и псевдослучайное
+ пробирование, может пропускать неиспользуемые записи.
+
+
+
+
+ 1Данный метод хеширования хорошо описан в книге Томаса Кормена
+ [2]
+
+
+
diff --git a/TheoryHTML/info.xml b/TheoryHTML/info.xml
new file mode 100644
index 0000000..4115598
--- /dev/null
+++ b/TheoryHTML/info.xml
@@ -0,0 +1,16 @@
+
+
+ ./TheoryHTML/Pages
+ ./TheoryHTML/Images
+
+ main.html
+ introduction.html
+ binaryRelationship.html
+ dirichletPrinciple.html
+ hashFunction.html
+ hashTable.html
+ chainMethod.html
+ openAddressing.html
+ analysis.html
+
+
\ No newline at end of file