Chinaunix首页 | 论坛 | 博客
  • 博客访问: 449958
  • 博文数量: 73
  • 博客积分: 3593
  • 博客等级: 中校
  • 技术积分: 912
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-14 11:32
文章分类

全部博文(73)

文章存档

2013年(2)

2012年(20)

2011年(25)

2010年(12)

2009年(14)

分类: C/C++

2009-11-27 18:04:19

/*
 * hashquad.c 开放定址法解决hash冲突问题
 */

#include
#include

#include "hashquad.h"
#include "fatal.h"

#define MIN_TABLE_SIZE (10)
#define REHASH_FACTOR    (0.7)

enum kind_of_entry { legitimate, empty, deleted };

struct hash_entry
{
    element_type    element;
    enum kind_of_entry    info;
};

typedef struct hash_entry cell;

struct hash_tbl
{
    int table_size;        /* 表容量 */
    int entry_cnt;        /* 已填入的单元数量 */
    cell    *cells;
};

static int
need_rehash( hash_table h )
{
    return ( h->entry_cnt > h->table_size * REHASH_FACTOR );
}

static int
next_prime( 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 cont_outer;
        }
        return N;
cont_outer:    ;
    }
}

static Index
hash( element_type key, int table_size )
{
    return key % table_size;
}

static hash_table
initialize_table( int table_size )
{
    hash_table h;
    int i;

    if ( table_size < MIN_TABLE_SIZE )
        Error("Table size too small!");

    h = malloc( sizeof( struct hash_tbl ) );
    if ( h == NULL )
        Error("Out of space!");

    h->table_size = next_prime( table_size );

    h->cells = malloc( sizeof( cell ) * h->table_size );
    if ( h->cells == NULL ){
        free( h );
        Error("Out of space!");
    }

    for ( i = 0; i < h->table_size; i++){
        h->cells[ i ].info = empty;
    }
    h->entry_cnt = 0;

    return h;
}

static Pos
find( element_type key, hash_table h )
{
    Pos    cur_pos;
    int    collision_num;

    collision_num = 0;
    cur_pos = hash( key, h->table_size );

    /*
    当hash表大部分被占满,这个过程可能很慢。
    也有可能进入死循环! 需要在适当的时候进行rehash!
    */
    while ( h->cells[ cur_pos ].info != empty
        &&  h->cells[ cur_pos ].element != key ){
        cur_pos += 2 * ++collision_num - 1;
        if ( cur_pos >= h->table_size )
            cur_pos -= h->table_size;
    }

    return cur_pos;
}

static void
insert( element_type key, hash_table h )
{
    Pos    p;

    p = find( key, h );
    if ( h->cells[ p ].info != legitimate ){
        h->cells[ p ].info = legitimate;
        h->cells[ p ].element = key;
        h->entry_cnt++;
    }
}

static hash_table
rehash( hash_table h)
{
    int i, old_size;
    cell *old_cells;

    old_cells = h->cells;
    old_size = h->table_size;

    /* 创建一个新的double size的空表 */
    h = initialize_table( 2 * old_size );

    /* 拷贝旧表的数据到新表 */
    for ( i = 0; i < old_size; i++ ){
        if ( old_cells[ i ].info == legitimate )
            insert( old_cells[ i ].element, h );
    }

    free( old_cells );

    return h;
}

/************    The next is test functions    ***************/
#define get_array_size(array)    ( sizeof(array) / sizeof(array[0]) )


void
test_hashquad( void )
{
    int i;
    Pos    p;
    hash_table h;
    element_type datas[100];

    for ( i = 0; i < get_array_size( datas ); i++ ){
        datas[i] = rand() % 1000;
    }

    h = initialize_table( 13 );
    if ( h == NULL )
        Error("Initialize error!");

    for ( i = 0; i < get_array_size( datas ); i++ ){
        insert( datas[i], h );
        /* 在每次插入操作后检查是否需要rehash */
        if ( need_rehash( h ) )
            h = rehash( h );
    }

    p = find( 67, h );
    if ( h->cells[p].info != legitimate ){
        printf("\n\t key value 67 not in hash table!\n");
    }else{
        printf("\n\t key value 67 in hash table!\n");    
    }

    p = find( datas[31], h );
    if ( h->cells[p].info != legitimate ){
        printf("\n\t key value %d not in hash table!\n",datas[31]);
    }else{
        printf("\n\t key value %d in hash table!\n",datas[31]);
    }

    i = i;
    return;
}

/*********************************************************************************************************/
/* hashquad.h */

#ifndef _HASHQUAD_H_
#define _HASHQUAD_H_

typedef int    element_type;
typedef unsigned int Index;
typedef Index    Pos;

struct hash_tbl;
typedef struct hash_tbl *hash_table;

#endif
阅读(2534) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~