Я рехеширую ключи, после увеличения вместимости базы данных, в этот момент у меня теряются данные, не могу понять почему
Функции подписаны, потерю зафиксировал при занесении элемента в список List(Для повторяющихся ключей) Проблема возникает в функции рехеширования, имена не отображаются, а я работаю с ними, как мне это исправить?
//headers.h
#pragma once
#include <iostream>
#include <string>
#include <map> // Для записи кол-ва повторений одинаковых ключей
#include <fstream>
enum Gender {male, female};
class Data {
private:
std::string name = "";
int age;
Gender gender;
double salary;
public:
Data() {};
Data(int age, Gender gender, double salary) : age(age), gender(gender), salary(salary) {}
~Data() {
name = "";
age = 0;
gender = male;
salary = 0;
}
friend class BD;
friend class List;
friend std::ostream& operator <<(std::ostream& out, const Data& data);
friend std::istream& operator >>(std::istream& in, Data& data);
void GetInfo();
Data& operator =(const Data& a);
};
class Node {
Data data;
Node* pNext;
Node* pPrev;
public:
Node() : pNext(nullptr), pPrev(nullptr) {}
Node(Node* prev, const Data& info) : data(info) {
pNext = prev->pNext; // сохраняем указатель на текущий
prev->pNext = this; // привязываем текущий к предыдущему как следующий
pPrev = prev; // привязываем предыдущий к текущему как предыдущий
pNext->pPrev = this; // привязываем к следующему текущий как предыдущий
}
~Node() {
if (pPrev != nullptr) pPrev->pNext = pNext;
if (pNext != nullptr) pNext->pPrev = pPrev;
pNext = nullptr; pPrev = nullptr;
}
friend class List;
};
class List {
Node Head;
Node Tail;
int size;
public:
List() {
Head.pNext = &Tail;
Tail.pPrev = &Head;
size = 0;
}
// Описание функций в List.cpp файле
void AddToHead(const Data& data);
void AddToTail(const Data& data);
void GetAllInfo();
void GetInfo(const std::string& name);
void WriteFile();
friend std::ostream& operator<<(std::ostream& out, const Data& data);
friend class BD;
};
class BD {
private:
Data* elements;
int* listskey; // Зачем-то нужно, уже не помню
int countlists; // сторонняя переменная
List l1;
std::map<int, int> repeatkeys; // запись сколько раз повторяется каждый ключ
bool repeat; // переменная для проверки на повтор ключа
int capacity = 4; // вместимость базы
int size = 0; // кол-во записей
int rehashingcount = 0; // кол-во рехеширований из-за увилечения вместимости
public:
BD() : elements(new Data[4]) {}
// Описание функций в HeshBD.cpp файле
int hashing(const std::string& name);
void rehashing(const int& rehashingcount);
void realloc();
void check();
void GetAllInfo(const BD& a);
void GetInfo(const std::string& name);
void KeyListsArr(int key);
void WriteFile();
void ReadFile(List& list2);
friend std::ostream& operator <<(std::ostream& out, const Data& data);
friend std::istream& operator >>(std::istream& in, Data& data);
friend class Data;
Data& operator [] (const std::string& name);
};
//HeshBD.cpp
#include "Headers.h"
//Функция хеширования ключа
int BD::hashing(const std::string& name) {
int temp = 0;
for (size_t i = 0; i < name.length(); i++) {
temp += static_cast<int>(name[i]);
}
return temp % capacity;
}
//Функция рехеширования после увеличения вместимости базы
void BD::rehashing(const int& rehashingcount) {
int PrevCapacity = capacity / 2 ;
Data* Temp = new Data[PrevCapacity];
for (size_t i = 0; i < PrevCapacity; i++) {
Temp[i] = elements[i];
}
delete[] elements;
for (size_t i = 0; i < PrevCapacity; i++) {
if (!(Temp[i].name.empty())) {
int temp = hashing(Temp[i].name);
elements[temp] = Temp[i];
}
}
}
//Функция увеличения вместимости базы
void BD::realloc() {
rehashingcount++;
Data* New = new Data[(capacity) * 2];
for (size_t i = 0; i < capacity; i++) {
New[i] = elements[i];
}
delete[] elements;
elements = std::move(New);
capacity *= 2;
rehashing(rehashingcount);
}
//Функция проверки необходимости увеличивать базу
void BD::check() {
double count = 0;
for (size_t i = 0; i < capacity; i++) {
if (elements[i].name.empty()) count++;
}
if (static_cast<double>(count / capacity) < static_cast<double>(static_cast<double>(3) / 4)) this->realloc();
}
//Функция, записывающая повторяющиеся ключи
void BD::KeyListsArr(int key) {
if (countlists > 1) {
int* temp = new int[countlists - 1];
for (size_t i = 0; i < countlists - 1; i++) {
temp[i] = listskey[i];
}
delete[] listskey;
listskey = new int[countlists];
for (size_t i = 0; i < countlists - 1; i++) {
listskey[i] = temp[i];
}
delete[] temp;
listskey[countlists - 1] = key;
}
else {
listskey = new int[countlists];
listskey[countlists - 1] = key;
}
}
//Функция вывода всей информации из базы в консоль
void BD::GetAllInfo(const BD& a) {
if(!repeatkeys.empty()) l1.GetAllInfo();
std::cout << "From BD:\n";
for (size_t i = 0; i < capacity; i++) {
if (!elements[i].name.empty()) {
std::cout << "Name: " << elements[i].name << std::endl;
std::string gend = "female";
if (elements[i].gender == 0) gend = "male";
std::cout << "Data: " << elements[i].age << "\t" << gend << "\t" << elements[i].salary << "\n\n";
}
}//Отделить вывод для ключей, в которых содержится список
}
//Функция вывода информации по имени
void BD::GetInfo(const std::string& name) {
setlocale(LC_ALL, "rus");
int key = hashing(name);
std::cout << "Searching by name:\n";
if (!repeatkeys.count(key)) {
if (elements[key].name == name) {
std::cout << "Name: " << elements[key].name << std::endl;
std::string gend = "female";
if (elements[key].gender == 0) gend = "male";
std::cout << "Data: " << elements[key].age << "\t" << gend << "\t" << elements[key].salary << "\n\n";
}
else {
std::cout << "Name: " << name << std::endl;
std::cout << "Data: " << "Not Found!\n\n";
}
}
else { // Найти элемент в списке List
l1.GetInfo(name);
}
}
//Функция вывода информации элемента Data
void Data::GetInfo() {
std::cout << "Name: " << name << std::endl;
std::string gend = "female";
if (gender == 0) gend = "male";
std::cout << "Data: " << age << "\t" << gend << "\t" << salary << "\n\n";
}
//Функция записи базы вместе со списком в файл
void BD::WriteFile() {
setlocale(LC_ALL, "rus");
std::ofstream file("BD.txt");
if (!file) {
std::cout << "Ошибка открытия файла\n";
}
else {
if(!repeatkeys.empty()) l1.WriteFile();
for (size_t i = 0; i < capacity; i++) {
int key = hashing(elements[i].name);
file << elements[i];
}
}
file.close();
}
// Для присваивания значения элементам Data
Data& Data::operator =(const Data& data) {
age = data.age;
gender = data.gender;
salary = data.salary;
/*else pub();*/
return *this;
}
// Для присвоения значения ключа
Data& BD::operator [] (const std::string& name) {
check();
int key = hashing(name);
if (repeat == 1) {
int temp = listskey[countlists - 1];
l1.AddToTail(elements[temp]);
//countlists++;
repeatkeys[temp] += 1;
repeat = 0;
}
if (elements[key].name.empty()) {
this->elements[key].name = name;
size++;
return elements[key];
}
else {
if (elements[key].name == name) {
elements[key].name = name;
elements[key].age = 0;
elements[key].gender = male;
elements[key].salary = 0;
return elements[key];
}
else {
bool other1 = 0;
for (size_t i = 0; i < countlists; i++) {
if (listskey[i] == key) other1 = 1;
}
if(other1) {
repeat = 1;
}
else {
if (repeatkeys[key] < 2) repeat = 1;
countlists++;
KeyListsArr(key);
l1.AddToTail(elements[key]);
}
repeatkeys[key] += 1;
elements[key].name = name;
elements[key].age = 0;
elements[key].gender = male;
elements[key].salary = 0;
size++;
return elements[key];
}
//Перехеширование массива ключей, которые повторяются
}
}
//Для записи в файл
std::ostream& operator<<(std::ostream& out, const Data& data) {
if (!data.name.empty()) {
out << "Name: " << data.name << "\t";
std::string gend = "female";
if (data.gender == 0) gend = "male";
out << "Data: " << data.age << "\t" << gend << "\t" << data.salary << "\n";
}
return out;
}
//List.cpp
#include "Headers.h"
//Функция, добавляющая элемент в начало списка
void List::AddToHead(const Data& data) {
new Node(&Head, data);
size++;
}
//Функция, добавляющая элемент в конец списка
void List::AddToTail(const Data& data) {
new Node(Tail.pPrev, data);
size++;
}
//Функция вывода всей информации из списка
void List::GetAllInfo() {
std::cout << "From List:\n";
Node Temp = Tail;
for (size_t i = 0; i < size; i++) {
Tail.pPrev->data.GetInfo();
Tail.pPrev = Tail.pPrev->pPrev;
}
Tail = Temp;
}
//Функция вывода информации по имени
void List::GetInfo(const std::string& name) {
Node Temp = Tail;
for (size_t i = 0; i < size; i++) {
if (Tail.pPrev->data.name == name) { Tail.pPrev->data.GetInfo(); break; }
else Tail.pPrev = Tail.pPrev->pPrev;
}
Tail = Temp;
}
//Функция записи списка в файл
void List::WriteFile() {
Node Temp = Tail;
std::ofstream file("list.txt");
if (!file) {
std::cout << "Ошибка записи в List.txt\n";
}
else {
for (size_t i = 0; i < size; i++) {
file << Tail.pPrev->data;
Tail.pPrev = Tail.pPrev->pPrev;
}
file.close();
}
Tail = Temp;
}
//main.cpp
#include "Headers.h"
int main() {
BD bd; //создание пустой базы
bd["Ivanov"] = Data(30, male, 30000); //если Ivanov-а в базе еще нет, то
bd["Muraev"] = Data(18, male, 0);
bd["Param"] = Data(27, male, 30000);
bd["Purum"] = Data(30, male, 2);
bd["Ivbnov"] = Data(31, female, 4);
bd["Ivcnov"] = Data(27, female, 3);
bd["Ivdnov"] = Data(27, female, 3);
bd["Ivenov"] = Data(27, female, 3);
bd["Ivfnov"] = Data(27, female, 3);
//bd["Muraev"] = Data(18, male, 2);
//bd["vonavI"] = Data(131, male, 4);
//bd["vearuM"] = Data(19, female, 1);
//bd["Param"] = Data(78, male, 0.5);
//добавление, если уже есть, то замена его реквизитов
bd.GetAllInfo(bd); //вывод информации обо всех сотрудниках
bd.GetInfo("Ivanov");
bd.GetInfo("vonavI");
bd.WriteFile();
return 0;
}