程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 數據結構-哈希表(C描述)

數據結構-哈希表(C描述)

編輯:關於C語言

1.基於分離鏈解決沖突

1.1主要的存儲結構

struct ListNode
{
    ElementType Element;
    Position    Next;
};

這是存儲數據的結構,實際上是一個鏈表。

typedef struct ListNode *Position;
typedef Position List;
struct HashTbl
{
    int TableSize;//哈希表大小
    List *TheLists;//指針數組
};

這是哈希表主結構,*TheLists是一個指針數組,數組的每一項都鏈接一個上面的ListNode,而這個入口地址相當於鏈表頭節點。

1.2ADT描述

hashsep.h
typedef int ElementType;
#ifndef HASHSEP_H_INCLUDED
#define HASHSEP_H_INCLUDED
typedef unsigned int Index;
struct ListNode;
typedef struct ListNode *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 );
/* Routines such as Delete are MakeEmpty are omitted */
#endif // HASHSEP_H_INCLUDED

1.3實現

hashsep.c
#include "../lib/fatal.h"
#include "hashsep.h"
#include <stdlib.h>
#define MinTableSize 10
struct ListNode
{
    ElementType Element;
    Position    Next;
};
typedef Position List;
/* List *TheList will be an array of lists, allocated later */
/* The lists use headers (for simplicity), */
/* though this wastes space */
struct HashTbl
{
    int TableSize;
    List *TheLists;
};
/* Return next prime; assume N >= 10 */
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: ;
    }
}
/* Hash function for ints */
Index Hash( ElementType Key, int TableSize )
{
    return Key % TableSize;
}
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 lists */
    H->TheLists = malloc( sizeof( List ) * H->TableSize );
    if( H->TheLists == NULL )
        FatalError( "Out of space!!!" );
    /* Allocate list headers */
    for( i = 0; i < H->TableSize; i++ )
    {
        H->TheLists[ i ] = malloc( sizeof( struct ListNode ) );
        if( H->TheLists[ i ] == NULL )
            FatalError( "Out of space!!!" );
        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 )
        /* Probably need strcmp!! */
        P = P->Next;
    return P;
}
void Insert( ElementType Key, HashTable H )
{
    Position Pos, NewCell;
    List L;
    Pos = Find( Key, H );
    if( Pos == NULL )   /* Key is not found */
    {
        NewCell = malloc( sizeof( struct ListNode ) );
        if( NewCell == NULL )
            FatalError( "Out of space!!!" );
        else
        {
            L = H->TheLists[ Hash( Key, H->TableSize ) ];
            NewCell->Next = L->Next;
            NewCell->Element = Key;  /* Probably need strcpy! */
            L->Next = NewCell;
        }
    }
}
ElementType Retrieve( Position P )
{
    return P->Element;
}
void DestroyTable( HashTable H )
{
    int i;
    for( i = 0; i < H->TableSize; i++ )
    {
        Position P = H->TheLists[ i ];
        Position Tmp;
        while( P != NULL )
        {
            Tmp = P->Next;
            free( P );
            P = Tmp;
        }
    }
    free( H->TheLists );
    free( H );
}

2.基於開放定址解決沖突

2.1主要的存儲結構

enum KindOfEntry { Legitimate, Empty, Deleted };

struct HashEntry

{

ElementType      Element;

enum KindOfEntry Info;

};

這是存放數據的結構,Element即用戶數據,Info用於標記當前節點的狀態,由枚舉KindOfEntry指定。

typedef struct HashEntry Cell;
struct HashTbl
{
    int TableSize;//哈希表大小
    Cell *TheCells;
};

這是哈希表主結構,*TheCells是一個指向結構體的指針,每個結構體即是一個用戶數據存儲單元。

2.2ADT描述

hashquad.h
typedef int ElementType;
#ifndef HASHQUAD_H_INCLUDED
#define HASHQUAD_H_INCLUDED
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 );
/* Routines such as Delete are MakeEmpty are omitted */
#endif // HASHQUAD_H_INCLUDED

2.3 實現

這裡解決沖突使用平方探測法,並提供再哈希函數。

hashquad.c
#include "../lib/fatal.h"
#include "hashquad.h"
#include <stdlib.h>
#define MinTableSize 10
enum KindOfEntry { Legitimate, Empty, Deleted };
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;
};
/* Return next prime; assume N >= 10 */
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: ;
    }
}
/* Hash function for ints */
Index Hash( ElementType Key, int TableSize )
{
    return Key % TableSize;
}
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;
}
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 )
    /* Probably need strcmp!! */
    {
        CurrentPos += 2 * ++CollisionNum - 1;
        if( CurrentPos >= H->TableSize )
            CurrentPos -= H->TableSize;
    }
    return CurrentPos;
}
void Insert( ElementType Key, HashTable H )
{
    Position Pos;
    Pos = Find( Key, H );
    if( H->TheCells[ Pos ].Info != Legitimate )
    {
        /* OK to insert here */
        H->TheCells[ Pos ].Info = Legitimate;
        H->TheCells[ Pos ].Element = Key;
        /* Probably need strcpy! */
    }
}
HashTable Rehash( HashTable H )
{
    int i, OldSize;
    Cell *OldCells;
    OldCells = H->TheCells;
    OldSize  = H->TableSize;
    /* Get a new, empty table */
    H = InitializeTable( 2 * OldSize );
    /* Scan through old table, reinserting into new */
    for( i = 0; i < OldSize; i++ )
        if( OldCells[ i ].Info == Legitimate )
            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 );
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved