Разрабатываю хеш-таблицу, которая работает с объектами структуры Item. Пытаюсь сделать метод для удаления объекта из таблицы по ключу, но объект всеравно остаеться. Подскажите в чем ошибка.
Структура Item:
#ifndef ITEM_H
#define ITEM_H
#include <string>
using namespace std;
struct Item
{
Item *next;
string name;
int age;
Item(string n, int a) : name(n), age(a) { }
};
#endif // ITEM_H
Класс Hash
#ifndef HASH_H
#define HASH_H
#include <iostream>
#include <vector>
#include "item.h"
class Hash
{
private:
vector<Item*> table;
int hash(string key);
public:
Hash();
~Hash();
void push(string name, int age);
void dell(string name);
Item *find(string name);
};
#endif // HASH_H
Его методы:
#include "hash.h"
int Hash::hash(string key)
{
int hashsum = 0;
for(size_t i=0; i<key.length(); i++)
hashsum += key[i];
return hashsum % table.size();
}
Hash::Hash()
{
table.resize(50);
for(size_t i=0; i<table.size(); i++)
table[i] = nullptr;
}
Hash::~Hash()
{
table.clear();
}
void Hash::push(string name, int age)
{
int hash_index = hash(name);
Item *person = new Item(name, age);
Item *place = table[hash_index];
if(!place)
{
table[hash_index] = person;
return;
}
while(place->next)
place = place->next;
place->next = person;
}
void Hash::dell(string name) // ?
{
Item *search = this->find(name);
if(search)
{
delete search;
search = nullptr;
}
}
Item* Hash::find(string name)
{
int hash_index = hash(name);
Item *result = table[hash_index];
if(!result)
{
cout << "Element not found!" << endl;
return nullptr;
}
while(result->name != name)
{
if(!result->next)
{
cout << "Element not found!" << endl;
return nullptr;
}
result = result->next;
}
return result;
}
main-функция:
#include "hash.h"
using namespace std;
int main()
{
Hash table;
table.push("John", 20);
table.push("Li", 18);
table.push("iL", 55);
table.push("Simon", 24);
// Item *search = table.find("Li");
// if(search) cout << search->age << endl;
table.dell("John");
Item *se = table.find("John");
if(se) cout << se->age << endl;
return 0;
}
Давайте посмотрим на метод dell
.
Item *search = this->find(name);
if (search)
{
delete search;
search = nullptr;
}
Вы обнуляете локальную переменную search
, и какой это имеет эффект на таблицу? Никакого. Вам нужно удалить найденный Item
из вашей таблицы. Вы же убиваете ваш Item
, но в таблице всё ещё есть ссылка на мёртвый Item
. То есть следующая попытка поиска обращается к мёртвой памяти, в которой может располагаться случайное значение.
В реальности вы должны удалить найденный Item
из односвязного списка (для этого обычно используют двойной указатель или указатель на предыдущий элемент), и возможно, если ваш bucket стал пустым, обнулить соответствующий элемент table
.
(Код не даю, задание выглядит как учебное.)
Кроме того, у вашей программы неопределённое поведение из-за того, что вы не инициализируете поле next
у Item
. Добавьте в конструктор инициализацию:
Item(string n, int a) : name(n), age(a), next(nullptr) { }
Переделал table под вектор листов. Вот что вышло:
Структура Item
#ifndef ITEM_H
#define ITEM_H
#include <string>
#include <iostream>
using namespace std;
struct Item
{
string name;
int age;
Item(string n, int a) : name(n), age(a) { }
};
#endif // ITEM_H
Класс Hash
#ifndef HASH_H
#define HASH_H
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include "item.h"
class Hash
{
private:
vector<list<Item*>* > table;
int hash(string key);
public:
Hash();
~Hash();
void push(string key, int value);
void pop(string name);
Item *find(string name);
void show();
};
#endif // HASH_H
Его методы:
#include "hash.h"
int Hash::hash(string key)
{
int hashsum = 0;
for(size_t i=0; i<key.length(); i++)
hashsum += key[i];
return hashsum % table.size();
}
Hash::Hash()
{
table.resize(50);
for(size_t i=0; i<table.size(); i++)
table[i] = nullptr;
}
Hash::~Hash()
{
table.clear();
}
void Hash::push(string key, int value)
{
int index = hash(key);
if(!table[index])
{
table[index] = new list<Item*>;
table[index]->push_back(new Item(key, value));
}
else
table[index]->push_back(new Item(key, value));
}
void Hash::pop(string name)
{
int index = hash(name);
Item *search = this->find(name);
if(!table[index] || !search)
{
cout << "Element not found!" << endl;
return;
}
table[index]->remove(search);
}
Item *Hash::find(string name)
{
int index = hash(name);
if(!table[index])
{
cout << "Element not found!" << endl;
return nullptr;
}
auto it = table[index]->begin();
while(it != table[index]->end())
{
if((*it)->name == name)
return *it;
it++;
}
cout << "Element not found!" << endl;
return nullptr;
}
void Hash::show()
{
for(size_t i=0; i<table.size(); i++)
{
if(table[i])
{
auto it = table[i]->begin();
while(it != table[i]->end())
{
cout << (*it)->name << "\t" << (*it)->age << endl;
it++;
}
}
}
}
main-функция:
#include "hash.h"
using namespace std;
int main()
{
Hash table;
int choice;
string name;
int age;
while(true)
{
cout << "\n1. Insert; 2. Find; 3. Delete; 4. Show; 5. Exit;" << endl;
cout << "Choice: "; cin >> choice;
switch(choice)
{
case 1: {
cout << "Name: "; cin >> name;
cout << "Age: "; cin >> age;
table.push(name, age);
break;
}
case 2: {
cout << "Name: "; cin >> name;
Item *search = table.find(name);
if(search) cout << "Age: " << search->age << endl;
break;
}
case 3: {
cout << "Name: "; cin >> name;
table.pop(name);
break;
}
case 4: {
cout << endl;
table.show();
break;
}
case 5: { exit(0); break; }
default: { break; }
}
}
return 0;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Пытаюсь создать тривиальное приложение на QT: от нажатий кнопки увеличивается счетчик, если увеличивается счетчик, отпечатывает текущее...
при попытке использовать getline в цикле независимо от n дает ввести строку только один разпомогите исправить
Как известно, ideone компилирует исходники на Си++ в utf8Однако, мне нужна строка в utf16 (wstring)