Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.72/29: Рейтинг темы: голосов - 29, средняя оценка - 4.72
Заблокирован

Шаблоны. Хеш-функция

26.05.2012, 21:54. Показов 6173. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрые день.
Есть задание сделать телефонную книгу. Поиск в базе сделать через хеш-функцию.

name - фамилия абонента.
num - номер телефона

Делал вот так () :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
файл LIST.h
 
#pragma once
 
#include <iostream>
#include <string>
 
template<class T, class M>
class List
{
public:
    List();
    ~List();
 
    void push_back(T name, M num);
    void print();
    void push_front(T name, M num);
    void erase();
    //void erase(T val, M name);
    void clear();
    void find(T name, M num);
 
private:
    struct Node
    {
        Node():Name(0), Num(0), next(NULL)
        {
        }
 
        T Name;
        M Num;
        Node* next;
    };
 
    Node* head;
    Node* tail;
};
Реализация:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "List.h"
 
#include <iostream>
#include <string>
 
template<class T, class M>
List<T, M>::List():head(0), tail(0)
{
}
 
template<class T, class M>
List<T, M>::~List()
{
    delete head;
    delete tail;
}
 
template<class T, class M>
void List<T, M>::push_back(T name, M num)
{
    Node* Temp;
 
    Temp = new Node;
    Temp->Name = name;
    Temp->Num = num;
 
    if(head == 0)
    {
        head = Temp;
        tail = Temp;
        return;
    }
    tail->next = Temp;
    tail = Temp;
}
 
template<class T, class M>
void List<T, M>::print()
{
    if(head == 0)
    {
        throw std::string("List is empty!");
    }
 
    for(Node* ptr = head; ptr != 0; ptr = ptr->next)
    {
        std::cout << ptr->Name << ' ' << ptr->Num;
    }
    std::cout << '\n';
}
 
template<class T, class M>
void List<T, M>::push_front(T name, M num)
{
    Node* Temp;
    Temp = new Node;
    Temp->Name = name;
    Temp->Num = num;
    Temp->next = head;
    head = Temp;
}
 
template<class T, class M>
void List<T, M>::erase()
{
    if(head == 0)
    {
        throw std::string("List is empty!\n");
    }
    Node* delptr = head->next;
    head = head->next;
    delete delptr;
}
 
template<class T, class M>
void List<T, M>::clear()
{
    while(head != 0)
        erase();
}
 
template<class T, class M>
void List<T, M>::find(T name, M num)
{
    if(head == 0)
    {
        throw std::string("List is empty!\n");
    }
 
    for(Node* ptr = head; ptr != 0; ptr = ptr->next)
    {
        if(ptr->Name == name)
            std::cout<<"Element "<< name <<" is finded\n";
        return;
    }
    std::cout<<"Element "<< name <<" is not finded\n";
}
Сразу прошу обратить внимание, что класс списка далеко не идеален. Есть проблемы с освобождением памяти. Я это знаю, но в данный момент это не так важно.

Далее реализую Хеш-функцию.

Прототип.
C++
1
2
3
4
5
6
7
8
9
10
Файл Hash.h
 
#pragma once
 
#include "List.h"
 
#define SIZE_TABLE      2
 
unsigned int hs(char* str);
int menu();
Реализация.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
 
#include "Hash.h"
#include "List.h"
 
using namespace std;
 
int main()
{
    int n = 0;
    char* str = NULL;
    str = new char[37];
 
    List<char*, int> symtab[SIZE_TABLE];
 
    unsigned int number = 0;
    unsigned int h = 0;
 
    while (1)
    {
        n = menu();
 
        switch(n)
        {
            // Добавить нового пользователя
        case 1:
            cout << "Vvedite FIO" << endl;
            cin >> str;
            cout << "Vvedite numer" << endl;
            cin >> number;
            h = hs(str);
            (symtab[h]).push_back(str, number);
            break;
            // Найти пользователя
        case 2:
            break;
            // Вывести весь список абонентов
        case 3:
            // Пробегаем по списку.
            for(int k = 0; k < SIZE_TABLE; k++)
            {
                symtab[k].print();
            }
            break;
            // Выход
        case 4:
            exit(1);
            break;
 
        default:
            break;
        }
    }
    
    return 0;
}
 
int menu()
{
    int t = 0;
    cout << "Vibirite punkt munu:" << endl;
    cout << "1 - Vvesti novogo abonenta" << endl;
    cout << "2 - Naiti nomer abonenta" << endl;
    cout << "3 - Vivesti spisok svech abonentov" << endl;
    cout << "4 - Vihod" << endl;
 
    cin >> t;
 
    return t;
}
 
// Хеш-функция
unsigned int hs(char* str)
{
    unsigned char* p = NULL;
 
    unsigned int h = 0;
 
    for(p = (unsigned char*)str; *p != '\0'; p++)
    {
        h = 37 * h + (*p);
    }
 
    return (h % SIZE_TABLE);
}
При компиляции выдает ошибки:


Ошибка 3 error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall List<char *,int>::List<char *,int>(void)" (??0?$List@PADH@@QAE@XZ) в функции _main

Ошибка 2 error LNK2019: ссылка на неразрешенный внешний символ "public: void __thiscall List<char *,int>:ush_back(char *,int)" (?push_back@?$List@PADH@@QAEXPADH@Z) в функции _main

Ошибка 1 error LNK2019: ссылка на неразрешенный внешний символ "public: void __thiscall List<char *,int>:rint(void)" (?print@?$List@PADH@@QAEXXZ) в функции _main

Ошибка 4 error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall List<char *,int>::~List<char *,int>(void)" (??1?$List@PADH@@QAE@XZ) в функции _main


Почему так происходит?

Ведь заголовочные файлы включены. Методы в разделе public. Обращение через экземпляр класса.
Все вроде должно работать.

И еще вопрос, подобная реализация хеширования информации имеет право на жизнь ?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.05.2012, 21:54
Ответы с готовыми решениями:

Хеш функция
Всем добрый день! В общем, нужно подсчитать кол-во коллизий. За это отвечает функция size_t collisions_count(), но почему-то не...

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

Хеш-функция, двойное хеширование
Всем привет! Пишу курсач, нужна хеш-функция, которая принимала бы строку и возвращала некий индекс. Написал нечто вроде unsigned...

18
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
27.05.2012, 00:19
Реализацию List засунь в List.h в конец. Некоторые компиляторы не справляются с компиляцией и линковкой кода шаблона, когда он в нескольких файлах.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.05.2012, 02:55
Некоторые компиляторы не справляются с компиляцией и линковкой кода шаблона, когда он в нескольких файлах.
А какие собственно справляются?
0
Higher
 Аватар для diagon
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
27.05.2012, 05:51
Цитата Сообщение от Avazart Посмотреть сообщение
А какие собственно справляются?
comeau и, как ни странно, билдер.
Хотя из нового стандарта экспорт шаблонов вроде как убрали.
0
Заблокирован
27.05.2012, 10:03  [ТС]
Благодарю, все работает.
Как-то этот момент упускают в учебниках.
А как быть тогда с сокрытием реализации кода, если допустим код распространяется в библиотеке?
0
Higher
 Аватар для diagon
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
27.05.2012, 10:06
Цитата Сообщение от Geniok Посмотреть сообщение
А как быть тогда с сокрытием реализации кода, если допустим код распространяется в библиотеке?
Обфускация. По другому никак.
0
Заблокирован
27.05.2012, 10:23  [ТС]
Будьте добры, подскажите еще такой момент.
В функцию добавления элемента в список я передаю указатель.
Поэтому получается такая ситуация, что при добавлении в список во всех элементах списка строка Name указывает на одну и ту же область памяти. То есть по сути имена не сохраняются, сохраняется только последнее введенное имя.
Как можно переписать функцию, чтобы под каждое имя выделялась своя область памяти, но при этом функция оставалась шаблонной ?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.05.2012, 13:49
comeau и, как ни странно, билдер.
Хотя из нового стандарта экспорт шаблонов вроде как убрали.
Вообщето Builder не справляется насколько я знаю...
0
Higher
 Аватар для diagon
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
27.05.2012, 14:31
Цитата Сообщение от Avazart Посмотреть сообщение
Вообщето Builder не справляется насколько я знаю...
Судя по википедии, билдер поддерживает экспорт шаблонов с 2004 года.
Возможно, вы просто неправильно пользуетесь словом export(либо вообще им не пользуетесь).
P.S. еще один компилятор вспомнил - Intel c++.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.05.2012, 15:14
вы просто неправильно пользуетесь словом export(либо вообще им не пользуетесь).
Возможно...пробовал давно еще кажеться на 6-й версии.
Как я понимаю export надо писать в h-файле перед объявлением шаблона ?

Добавлено через 20 минут
Заголовок:
C++
1
2
3
4
5
6
7
8
#ifndef Unit4H
#define Unit4H
//---------------------------------------------------------------------------
export
template<class T>
void swap(T& a,T& b);
//---------------------------------------------------------------------------
#endif
Реализация
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Unit4.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
template<class T>
void swap(T& a,T& b)
{
T temp= a;
a =  b;
b =  temp;
}
//---------------------------------------------------------------------------
Приминение
C++
1
2
3
4
5
6
7
8
9
#include "Unit4.h"
//---------------------------------------------------------------------------
void __fastcall TForm3::FormCreate(TObject *Sender)
{
int a=3,b=5;
swap(a,b);
Caption= a;
}
//---------------------------------------------------------------------------
[ILINK32 Error] Error: Unresolved external 'void swap<int>(int&, int&)' referenced from C:\USERS\FUJITSU\DOCUMENTS\RAD STUDIO\PROJECTS\DEBUG_BUILD\UNIT3.OBJ
Шаблоны классов и функций
0
Заблокирован
27.05.2012, 16:27  [ТС]
Сделал без шаблонов, так как смысла в данном конкретном случае в них нет.
Подскажите пожалуйста насчет освобождения памяти. В каком месте у меня возможна утечка и как лучше всего сделать.

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class List
{
public:
    List();
    ~List();
 
    void push(char* name, int num);
    void print();
    void erase();
    //void erase(T val, M name);
    void clear();
    void find(char* name, int num);
 
private:
    struct Node
    {
        Node():Num(0), next(0)
        {
            Name = new char;
        }
 
        char* Name;
        int Num;
        Node* next;
    };
 
    Node* head;
    Node* tail;
 
    char* strCopy(char* in, char* to);
};
Реализация:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
List::List():head(0), tail(0)
{
}
 
List::~List()
{
    delete head;
    delete tail;
}
 
void List::push(char* name, int num)
{
    Node* Temp = new Node;
 
    Temp->Name = strCopy(Temp->Name, name);
    
    Temp->Num = num;
 
    if(head == 0)
    {
        head = Temp;
        tail = Temp;
        return;
    }
    tail->next = Temp;
    tail = Temp;
}
 
 
void List::print()
{
    if(head == 0)
    {
        throw std::string("List is empty!");
    }
 
    for(Node* ptr = head; ptr != 0; ptr = ptr->next)
    {
            std::cout << ptr->Name << ' ' << ptr->Num;
    }
    std::cout << '\n';
}
 
void List::erase()
{
    if(head == 0)
    {
        return;
    }
    Node* delptr = head->next;
    head = head->next;
    delete delptr;
}
 
void List::clear()
{
    while(head != 0)
        erase();
}
 
 
void List::find(char* name, int num)
{
    if(head == 0)
    {
        return;
    }
 
    for(Node* ptr = head; ptr != 0; ptr = ptr->next)
    {
        if(ptr->Name == name)
            std::cout<<"Element "<< name <<" is finded\n";
        return;
    }
    std::cout<<"Element "<< name <<" is not finded\n";
}
 
char* List::strCopy(char* in, char* to)
{
    char* tmp = in;
 
    while(*in++ = *to++)
        ;
    return tmp;
}
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.05.2012, 16:40
C++
1
2
3
4
5
List::~List()
{
    delete head;
    delete tail;
}
Тут ты ведь удаляешь только крайнии узлы, а внутрении?

Добавлено через 3 минуты
Как вариант в структуре Node сделай деструктор в котором он не только будет удалять себя, но и элемент next.(!=NULL)
в итоге delete head вызовет цепную реакцию.
0
Заблокирован
27.05.2012, 18:33  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
C++
1
2
3
4
5
List::~List()
{
    delete head;
    delete tail;
}
Тут ты ведь удаляешь только крайнии узлы, а внутрении?

Добавлено через 3 минуты
Как вариант в структуре Node сделай деструктор в котором он не только будет удалять себя, но и элемент next.(!=NULL)
в итоге delete head вызовет цепную реакцию.

Спасибо за ответ!
Потому и спросил, что удаляю только крайние узлы, значит то, что в середине остается занято.

Если вас правильно понял. должно быть что-то типа этого:

C++ (Qt)
1
2
3
4
5
~Node()
    {
            while(next != 0)
                delete next;
    }
?
Если да, то не подходит. компилятор пишет: Ошибка 1 error C2523: List::~Node: несовпадение тегов деструктор
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.05.2012, 18:38
C++
1
2
3
4
5
~Node()
    {
     if(next)  delete next;
     delete Name;  // Name это что один символ??? По вашему коду именно так
    }
Но я не увере потому как у вас я еще заметил erase поэтому это не подойдет, но в любом случае нужен деструктор Node
C++
1
2
3
4
~Node()
 {
     delete Name;  // Name это что один символ??? По вашему коду именно так
  }
Что бы освободить память от создаваемого динамически char объекта
0
What a waste!
 Аватар для gray_fox
1610 / 1302 / 180
Регистрация: 21.04.2012
Сообщений: 2,733
27.05.2012, 18:41
Цитата Сообщение от Geniok Посмотреть сообщение
должно быть что-то типа этого
не, стоит написать деструктор листа, чтобы он проходил по всем нодам и очищал память. примерно так:
C++
1
2
3
4
5
6
7
~List() {
   while (head != 0) {
      Node * tmp = head;
      head = head->next;
      delete tmp;
   }
}
Добавлено через 2 минуты
а в деструкторе нода удалять только то, что выделяли в конструкторе:
C++
1
2
3
~Node() {
   delete[] Name;   // если Name не массив, то delete Name;
}
1
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.05.2012, 18:46
C++
1
2
3
4
List::~List()
{
   clear() // думаю так но вы там проверьте по своему коду
}
0
Заблокирован
27.05.2012, 20:15  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
C++
1
2
3
4
5
~Node()
    {
     if(next)  delete next;
     delete Name;  // Name это что один символ??? По вашему коду именно так
    }
Но я не увере потому как у вас я еще заметил erase поэтому это не подойдет, но в любом случае нужен деструктор Node
C++
1
2
3
4
~Node()
 {
     delete Name;  // Name это что один символ??? По вашему коду именно так
  }
Что бы освободить память от создаваемого динамически char объекта
Name - это массив символов. В Name должна содержаться фамилия. По идее.
Именно поэтому объявление
C++ (Qt)
1
char* Name
а не

C++ (Qt)
1
char Name
Добавлено через 47 секунд
Цитата Сообщение от gray_fox Посмотреть сообщение
не, стоит написать деструктор листа, чтобы он проходил по всем нодам и очищал память. примерно так:
C++
1
2
3
4
5
6
7
~List() {
   while (head != 0) {
      Node * tmp = head;
      head = head->next;
      delete tmp;
   }
}
Добавлено через 2 минуты
а в деструкторе нода удалять только то, что выделяли в конструкторе:
C++
1
2
3
~Node() {
   delete[] Name;   // если Name не массив, то delete Name;
}
Вот теперь понятно. Большое спасибо за помощь!
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
27.05.2012, 20:23
Почему тогда
C++
1
2
3
4
Node():Num(0), next(0)
{
Name = new char;//  А не Name = new char[size]  - читайте про работу со строками и выделение памяти динамически
}
1
Заблокирован
27.05.2012, 21:02  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Почему тогда
C++
1
2
3
4
Node():Num(0), next(0)
{
Name = new char;//  А не Name = new char[size]  - читайте про работу со строками и выделение памяти динамически
}
Вы опять же правы. сначала был массив. а потом когда я сюда код переносил, я массив удалил, но удивительно что в Visual Studio компилируется и прекрасно работает.

Еще раз большое спасибо за замечание, сейчас исправлю.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.05.2012, 21:02
Помогаю со студенческими работами здесь

Объясните как работает хеш-функция
int Hash_Function1(DrugStore object) { int result = 0; for (int i = 0; i &lt; SSize+1; i++) result = result +...

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

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

Нужна хеш-функция для программы на языке С++
К моей программе необходимо прикрутить функцию для вычисления хеша. Подскажите, пожалуйста, работоспособный исходник хеш-функции для...

Метод открытого хеширования и хеш-функция, основанная на методе деления с остатком
Ещё раз здравствуйте! Есть такое задание: Написать программу, которая реализует метод открытого хеширования и хеш-функцией,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru