我是C编程的新手,我最近才开始学习数据结构和算法.我选择的教科书是C中的数据结构和算法分析,它引入了第5章中的哈希表ADT.这里是其四开放寻址版本的一个实现,其中函数Find将Key和TableSize的值传递给Hash函数,它将散列值作为变量CurrentPos返回.以下是函数Hash和Find:
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;
}
现在问题是,但是这种实现在大多数情况下都能正常工作.它有时会遇到崩溃.当它发生时,我尝试单元测试并发现在一定轮次调用Hash函数后,CurrentPos的值将被指定为一个比Hash函数的实际返回值大得多的整数,它可能是1000加上甚至更大.
例如,如果Key为29918且TableSize为101,则正确答案和是Hash返回的值为22,但在分配行之后:
CurrentPos = Hash(Key, H->TableSize);
无论如何,CurrentPos的值本身都变为1580.
请注意,基于函数time()的种子使用rand()随机分配的Key值小于integer类型的上边界 – 我的意思是应该没有溢出.
我努力寻找手表,但没有其他错误或线索.我很困惑,因为这个错误实际上是随机发生的.有没有人熟悉这个?
最佳答案 如果CollisionNum变得足够大,那么此测试将无法正常工作:
if(CurrentPos >= H->TableSize)
CurrentPos -= H->TableSize;
因为如果CurrentPos> = H-> TableSize * 2,则在减去H-> TableSize之后,CurrentPos仍将超出范围.
您应该将此更改为:
while (CurrentPos >= H->TableSize)
CurrentPos -= H->TableSize;
要么:
CurrentPos = CurrentPos % H->TableSize;
甚至:
CurrentPos %= H->TableSize;