9.6.1 哈希查找之分离链接哈希表解决哈希碰撞(2)

来源:互联网 发布:售电软件 编辑:程序博客网 时间:2024/05/18 03:21

本例函数比较经典,但个别函数仍需优化:

下面是代码示例:

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/***********************************************************/
// 程序名称:HashSearch_3.cpp
// 程序目的:哈希表之---分离链接散列法
// 程序来源:数据结构与算法分析(C语言描述) P-114
// 日期:2013-8-31 13:27:47 JohnnyHu修改
/***********************************************************/

#include <stdio.h>
#include <stdlib.h>

#define Error( str )        FatalError( str )
#define FatalError( str )   fprintf( stderr, "%s\n", str ), exit( 1 )

#define MinTableSize 10
#define NUMITEMS 20

struct ListNode;
typedef struct ListNode* Position;
struct HashTbl;
typedef struct HashTbl* HashTable;
typedef int ElementType;
typedef unsigned int Index;

Index Hash(ElementType key, int tableSize);
HashTable InitializeTable(int tableSize);
Position Find(ElementType key, HashTable h);
void Insert(ElementType key, HashTable h);
ElementType Retrieve(Position p);
void DestroyTable(HashTable h);
//void Delete(ElementType x, HashTable h);  // 暂不实现
//HashTable MakeEmpty(HashTable h);
void PrintfTable(HashTable h);

struct ListNode
{
    ElementType element;
    Position next;
};
typedef Position List;


struct HashTbl
{
    int tableSize;
    List* theLists;
};

int main(void)
{
    HashTable hashTable;
    int currentSize;
    hashTable = InitializeTable(currentSize = 13);  // 当前哈希表的大小为13

    for (int i = 0, j = 1; i < NUMITEMS; i++, j += 2)
    {
        Insert(j, hashTable);
    }

    printf("输出哈希表中数据: \n");
    PrintfTable(hashTable);

    int keyValue;
    printf("输入要插入的(int)值(-1则退出输入操作):");
    scanf("%d", &keyValue);
    while (-1 != keyValue)
    {
        Insert(keyValue, hashTable);
        printf("输入要插入的(int)值(-1则退出输入操作):");
        scanf("%d", &keyValue);
    }


    printf("执行插入后的哈希表数据:\n");
    PrintfTable(hashTable);

    // 检测各个值
    Position pos;
    for (int i=0, j=1; i < NUMITEMS; i++, j += 2)
    {
        if ( NULL == (pos = Find(j, hashTable)) || Retrieve(pos) != j )
            printf("在%d处出错!\n", j);
    }
    printf("程序执行完毕!\n");

    DestroyTable(hashTable); // 释放内存空间

    return 0;
}

/************************************************************************/
// 返回下一个素数(与n仅接着的素数)
/************************************************************************/

static int NextPrime(int n)
{
    int i;

    if( n % 2 == 0 )
        n++;
    for( ; ; n += 2 )
    {
        for( i = 3; i * i <= n; i += 2 )
            if( n % i == 0 )
                goto ContOuter;  /* Sorry about this! */
        return n;
        ContOuter: ;
    }
}

/************************************************************************/
// 哈希函数
/************************************************************************/

Index Hash(ElementType key, int tableSize)
{
    return key % tableSize;
}

/************************************************************************/
// 初始化哈希表
/************************************************************************/

HashTable InitializeTable(int tableSize)
{   
    if (tableSize < MinTableSize)
    {
        Error("要创建的表太小!");
        return NULL;
    }

    HashTable h;
    h = (HashTable)malloc(sizeof(struct HashTbl));
    if (NULL == h)
        FatalError("内存分配失败!");

    h->tableSize = NextPrime(tableSize);        // 设置表的大小为一素数

    // 指定list的一个数组
    h->theLists = (List*)malloc(sizeof(List) * h->tableSize);
    if (NULL == h->theLists)
        FatalError("数组内存分配失败!");

    // 给每个表分配一个表头 (for语句待优化)
    for (int i = 0; i < h->tableSize; i++)
    {
        h->theLists[i] = (Position)malloc(sizeof(struct ListNode));
        if ( h->theLists[i] == NULL ) 
            FatalError("内存分配失败!");
        else
            h->theLists[i]->next = NULL;
    }

    return h;
}

/************************************************************************/
// 哈希表查找
/************************************************************************/

Position Find(ElementType key, HashTable h)
{
    Position p;
    List l;

    l = h->theLists[Hash(key, h->tableSize)];
    p = l->next;
    while (p != NULL && p->element != key)
        p = p->next;

    return p;
}

/************************************************************************/
// 哈希表插入(待优化)
/************************************************************************/

void Insert(ElementType key, HashTable h)
{
    Position pos, newCell;
    List l;

    pos = Find(key, h);
    if (NULL == pos)  // 没找到键值
    {
        newCell = (Position)malloc(sizeof(struct ListNode));
        if (NULL == newCell)
            FatalError("内存分配失败!");
        else
        { // 放的表的前端
            l = h->theLists[Hash(key, h->tableSize)];
            newCell->next = l->next;
            newCell->element = key;
            l->next = newCell;
        }
    }
}

/************************************************************************/
// 获取键值
/************************************************************************/

ElementType Retrieve(Position p)
{
    return p->element;
}

/************************************************************************/
// 哈希表销毁
/************************************************************************/

void DestroyTable(HashTable h)
{
    for (int i = 0; i < h->tableSize; i++)
    {
        Position p = h->theLists[i];
        Position tmp;

        while(NULL != p)
        {
            tmp = p->next;
            free(p);
            p = tmp;
        }
    }

    free(h->theLists);
    free(h);

    return;
}

/************************************************************************/
// Fuction: 打印哈希表
// target:   测试哈希表中数据
// Author:   Johnny Hu
// Date:     2013-9-1 6:36:38
/************************************************************************/

void PrintfTable(HashTable h)
{
    HashTable& hashTable = h;
    for (int i=0; i < hashTable->tableSize; i++)
    {
        List theNode;
        theNode = hashTable->theLists[i]->next;  // 头结点

        printf("hashTable[%d]:\t", i);
        while (NULL != theNode->next)
        {
            printf("[%d]\t", theNode->element);
            theNode = theNode->next;
        }
        printf("[%d] \n", theNode->element);

    }
}
输出结果:



原创粉丝点击