9.6.2 哈希查找之开放定址法解决哈希碰撞

http://blog.csdn.net/johnnyhu90/article/details/10822497

开放定址法:

(1) 线性探测法:逐个探测每个单元(必要时绕回)以查找出一个空单元。典型的冲突函数

    F(i)= i;

缺点: 容易产生一次聚集(primary clustering);

(2) 平方探测法:典型的冲突函数是:F(i) = i2,消除线性探测一次聚集的冲突解决办法。

缺点:容易产生二次聚集(secondary clustering);

定理:使用平方探测,且表的大小为素数,那么当表至少一半空的时候,总能够插入一个新元

具体详细介绍见资源:http://download.csdn.net/detail/johnnyhu90/6191597     一书的117页介绍

下面代码示例:

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
248
249
250
251
252
253
254
255
256
257
258
259
/***********************************************************/
// 程序名称:HashSearch_3.cpp
// 程序目的:哈希表之---分离链接散列法
// 程序来源:数据结构与算法分析(C语言描述) P-120
// 日期:2013-9-1 12:50:33 JohnnyHu修改
/***********************************************************/

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

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

#define MinTableSize  5
#define NUMITEMS  5

typedef  int ElementType;
typedef  unsigned  int Index;
typedef Index Position;
struct hashTbl;
typedef  struct hashTbl* HashTable;

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, HashTable h);
void DestroyTable(HashTable h);
HashTable Rehash(HashTable h);
void PrintfTable(HashTable h);

enum kindOfEntry {legitmate, empty, deleted};  // 合法的、空、删除的

struct hashEntry
{
    ElementType element;
     enum kindOfEntry info;
};
typedef  struct hashEntry Cell;

struct hashTbl
{
     int tableSize;
    Cell* theCells;
};

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

     int insertedNum =  0;         // 标识插入表中元素个数
     for ( int i =  0, j =  1; i < NUMITEMS; i++, j +=  2)
    {
         if( i > currentSize /  2 )
        {
            hashTable = Rehash( hashTable );   // 再散列
            printf(  "插入元素数超过: %d, Rehashing(再散列)...\n" , i);
            currentSize *=  2;
        }

        Insert(j, hashTable);
        insertedNum++;
    }

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

     int keyValue;
    printf( "输入要插入的(int)值(-1则退出输入操作):");
    scanf( "%d", &keyValue);
     while (- 1 != keyValue)
    {
         if( insertedNum > currentSize /  2 )
        {
            hashTable = Rehash( hashTable );   // 再散列
            printf(  "插入元素数超过: %d, Rehashing(再散列)...\n" , insertedNum);
            currentSize *=  2;
        }
        Insert(keyValue, hashTable);
        insertedNum++;

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


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

     // 检测各个值
    Position pos;
     for ( int i= 0, j= 1; i < NUMITEMS; i++, j +=  2)
    {
         if ( Retrieve((pos = Find(j, hashTable)), hashTable)  != 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);   // 哈希表大小是素数

    h->theCells = (Cell*)malloc( sizeof(Cell) * h->tableSize);
     if ( NULL == h->theCells)
        FatalError( "给数组内存分配失败!");

     for ( int i =  0; i < h->tableSize; i++)
        h->theCells[i].info = empty;

     return h;
}

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

Position Find(ElementType key, HashTable h)
{
    Position correntPos;
     int collisionNum;

    collisionNum =  0;
    correntPos = Hash(key, h->tableSize);
     while (h->theCells[correntPos].info != empty &&
            h->theCells[correntPos].element != key)
    {  // 这里进行平方探测
        correntPos +=  2 * ++collisionNum  -  1;
         if (correntPos >= h->tableSize)
            correntPos -= h->tableSize;
    }

     return correntPos;
}

/************************************************************************/
// 哈希表插入
/************************************************************************/

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

    pos = Find(key, h);
     if (h->theCells[pos].info != legitmate)
    {
        h->theCells[pos].info = legitmate;
        h->theCells[pos].element = key;
    }
}

/************************************************************************/
// 开放定址列表再散列
/************************************************************************/

HashTable Rehash(HashTable h)
{
     int oldSize;
    Cell* oldCells;

    oldCells = h->theCells;
    oldSize = h->tableSize;

     // 获得新的空表
    h = InitializeTable( 2 * oldSize);

     for ( int i =  0; i < oldSize; i++)
    {
         if (oldCells[i].info == legitmate)
            Insert(oldCells[i].element, h);
    }

    free(oldCells);

     return h;
}
/************************************************************************/
// 获取键值
/************************************************************************/

ElementType Retrieve(Position p, HashTable h)
{
     return h->theCells[p].element;
}

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

void DestroyTable(HashTable h)
{
    free(h->theCells);
    free(h);

     return;
}

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

void PrintfTable(HashTable h)
{
    Cell* printCells;
    printCells = h->theCells;
     for ( int i= 0; i < h->tableSize; i++)
    {
         if (printCells[i].info == legitmate)
            printf( "hashtable[%d]: [%d]\n", i, printCells[i].element);
         else  if (printCells[i].info == empty)
            printf( "hashtable[%d]: [ ]\n", i);
            
    }
}
输出结果:




kiwisyslog 9.6.2免费版是一款网络日志管理工具,适用于Windows操作系统。该软件为用户提供了一个集中管理和监控网络设备生成的日志的平台。 kiwisyslog 9.6.2免费版具备以下主要功能: 1. 日志收集和分析:软件可以从多种网络设备和应用程序中收集、过滤和分析日志信息。用户可以定制日志收集规则,选择需要监控的设备和关注的事件类型。 2. 实时事件监控:软件能够实时监控网络设备生成的日志,并及时向用户报告重要的事件。用户可以通过定制警报规则和触发条件,实现实时报警功能,以便快速响应网络故障和安全事件。 3. 日志存档和备份:软件提供了一个日志存档和备份系统,可将日志信息保存在安全的位置,以便后续的检索和审计。 4. 多种日志输出方式:软件支持将日志信息输出到各种常见的格式和数据库中,如CSV、TXT、SQL Server等。用户可以根据需要选择适合自己的输出格式。 5. 用户友好的界面:软件提供了一个直观易用的界面,用户可以通过图形化的操作来管理和配置软件。同时,软件还提供了一些实用的工具,如日志搜索和过滤、即时通知等,方便用户进行日常操作。 总之,kiwisyslog 9.6.2免费版是一款功能强大且易于使用的网络日志管理工具,它可以帮助用户集中管理和监控网络设备生成的日志,并及时报警,以提高网络故障和安全事件的处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值