我是C编程的新手,我最近才开始学习数据结构和算法。我选择的教科书是数据结构和C 中的算法分析,它引入了第5章中的哈希表ADT。这是其四开放寻址版本的一个实现,其中函数查找将 Key 和 TableSize 的值传递给 Hash < / strong> function它会将散列值作为变量 CurrentPos 返回。以下是功能哈希和查找:
Index
Hash( ElementType Key, int TableSize )
{
return Key % TableSize;
}
Position
Find(ElementType Key, HashTable H)
{
Position CurrentPos;
int CollisionNum;
CollisionNum = 0;
CurrentPos = Hash(Key, H->TableSize);
while(H->TheCells[CurrentPos].Info != Empty && H->TheCells[CurrentPos].Element != Key)
{
CurrentPos += 2 * ++CollisionNum - 1;
if(CurrentPos >= H->TableSize)
CurrentPos -= H->TableSize;
}
return CurrentPos;
}
这是标题:
typedef int ElementType;
#ifndef _HashQuad_H
#define _HashQuad_H
typedef unsigned int Index;
typedef Index Position;
struct HashTbl;
typedef struct HashTbl *HashTable;
HashTable InitializeTable( int TableSize );
void DestroyTable( HashTable H );
Position Find( ElementType Key, HashTable H );
void Insert( ElementType Key, HashTable H );
ElementType Retrieve( Position P, HashTable H );
HashTable Rehash( HashTable H );
#endif
以下是源文件中的typedef和结构:
struct HashEntry
{
ElementType Element;
enum KindOfEntry Info;
};
typedef struct HashEntry Cell;
/* Cell *TheCells will be an array of */
/* HashEntry cells, allocated later */
struct HashTbl
{
int TableSize;
Cell *TheCells;
};
这是H被初始化的方式
HashTable
InitializeTable( int TableSize )
{
HashTable H;
int i;
if( TableSize < MinTableSize )
{
Error( "Table size too small" );
return NULL;
}
/* Allocate table */
H = malloc( sizeof( struct HashTbl ) );
if( H == NULL )
FatalError( "Out of space!!!" );
H->TableSize = NextPrime( TableSize );
/* Allocate array of Cells */
H->TheCells = malloc( sizeof( Cell ) * H->TableSize );
if( H->TheCells == NULL )
FatalError( "Out of space!!!" );
for( i = 0; i < H->TableSize; i++ )
H->TheCells[ i ].Info = Empty;
return H;
}
现在问题是,但是这种实现在大多数情况下都能正常工作。它有时会遇到崩溃。当它发生时,我尝试单元测试并发现在某一轮调用哈希函数后, CurrentPos 的值将被指定为一个更大的整数比哈希函数的实际返回值,它可能是1000加甚至更大。 例如,如果 Key 为29918且 TableSize 为101,那么正确答案和是哈希返回的值为22,但是在分配之后行:
CurrentPos = Hash(Key, H->TableSize);
CurrentPos 的值无论如何都会自行变为1580。 请注意,基于函数 time()的种子使用 rand()随机分配的 Key 值小于上限类型整数的边界 - 我的意思是应该没有溢出。
我努力寻找手表,但没有其他错误或线索。我很困惑,因为这个错误实际上是随机发生的。有没有人熟悉这个?
答案 0 :(得分:2)
如果CollisionNum
变得足够大,那么此测试将无法正常运行:
if(CurrentPos >= H->TableSize)
CurrentPos -= H->TableSize;
因为如果CurrentPos >= H->TableSize*2
CurrentPos
,则H->TableSize
减去 while (CurrentPos >= H->TableSize)
CurrentPos -= H->TableSize;
之后仍会超出范围。
您应该将其更改为:
CurrentPos = CurrentPos % H->TableSize;
或:
CurrentPos %= H->TableSize;
甚至:
{{1}}