Mastering Algorithms with C(ohtbl)

(1)ohtbl.h

/*****************************************************************************
*                                                                            *
*  ------------------------------- ohtbl.h --------------------------------  *
*                                                                            *
*****************************************************************************/

#ifndef OHTBL_H
#define OHTBL_H

#include <stdlib.h>
#include <string.h>

#include "ohtbl.h"

/*****************************************************************************
*                                                                            *
*  Define a structure for open-addressed hash tables.                        *
*                                                                            *
*****************************************************************************/

typedef struct OHTbl_ {

int                positions;
void               *vacated;

int                (*h1)(const void *key);
int                (*h2)(const void *key);
int                (*match)(const void *key1, const void *key2);
void               (*destroy)(void *data);

int                size;
void               **table;

} OHTbl;

/*****************************************************************************
*                                                                            *
*  --------------------------- Public Interface ---------------------------  *
*                                                                            *
*****************************************************************************/

int ohtbl_init(OHTbl *htbl, int positions, int (*h1)(const void *key), int
   (*h2)(const void *key), int (*match)(const void *key1, const void *key2),
   void (*destroy)(void *data));

void ohtbl_destroy(OHTbl *htbl);

int ohtbl_insert(OHTbl *htbl, const void *data);

int ohtbl_remove(OHTbl *htbl, void **data);

int ohtbl_lookup(const OHTbl *htbl, void **data);

#define ohtbl_size(htbl) ((htbl)->size)

/*****************************************************************************
*                                                                            *
*  ------------------------------- ohtbl.c --------------------------------  *
*                                                                            *
*****************************************************************************/

/*****************************************************************************
*                                                                            *
*  Reserve a sentinel memory address for vacated elements.                   *
*                                                                            *
*****************************************************************************/

static char        vacated;

/*****************************************************************************
*                                                                            *
*  ------------------------------ ohtbl_init ------------------------------  *
*                                                                            *
*****************************************************************************/

int ohtbl_init(OHTbl *htbl, int positions, int (*h1)(const void *key), int
   (*h2)(const void *key), int (*match)(const void *key1, const void *key2),
   void (*destroy)(void *data)) {

int                i;

/*****************************************************************************
*                                                                            *
*  Allocate space for the hash table.                                        *
*                                                                            *
*****************************************************************************/

if ((htbl->table = (void **)malloc(positions * sizeof(void *))) == NULL) 
   return -1;

/*****************************************************************************
*                                                                            *
*  Initialize each position.                                                 *
*                                                                            *
*****************************************************************************/

htbl->positions = positions;

for (i = 0; i < htbl->positions; i++)
   htbl->table[i] = NULL;

/*****************************************************************************
*                                                                            *
*  Set the vacated member to the sentinel memory address reserved for this.  *
*                                                                            *
*****************************************************************************/

htbl->vacated = &vacated;

/*****************************************************************************
*                                                                            *
*  Encapsulate the functions.                                                *
*                                                                            *
*****************************************************************************/

htbl->h1 = h1;
htbl->h2 = h2;
htbl->match = match;
htbl->destroy = destroy;

/*****************************************************************************
*                                                                            *
*  Initialize the number of elements in the table.                           *
*                                                                            *
*****************************************************************************/

htbl->size = 0;

return 0;

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- ohtbl_destroy -----------------------------  *
*                                                                            *
*****************************************************************************/

void ohtbl_destroy(OHTbl *htbl) {

int                i;
 
if (htbl->destroy != NULL) {

   /**************************************************************************
   *                                                                         *
   *  Call a user-defined function to free dynamically allocated data.       *
   *                                                                         *
   **************************************************************************/

   for (i = 0; i < htbl->positions; i++) {

      if (htbl->table[i] != NULL && htbl->table[i] != htbl->vacated)
         htbl->destroy(htbl->table[i]);

   }

}

/*****************************************************************************
*                                                                            *
*  Free the storage allocated for the hash table.                            *
*                                                                            *
*****************************************************************************/

free(htbl->table);

/*****************************************************************************
*                                                                            *
*  No operations are allowed now, but clear the structure as a precaution.   *
*                                                                            *
*****************************************************************************/

memset(htbl, 0, sizeof(OHTbl));

return;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- ohtbl_insert -----------------------------  *
*                                                                            *
*****************************************************************************/

int ohtbl_insert(OHTbl *htbl, const void *data) {

void               *temp;

int                position,
                   i;
 
/*****************************************************************************
*                                                                            *
*  Do not exceed the number of positions in the table.                       *
*                                                                            *
*****************************************************************************/

if (htbl->size == htbl->positions)
   return -1;

/*****************************************************************************
*                                                                            *
*  Do nothing if the data is already in the table.                           *
*                                                                            *
*****************************************************************************/

temp = (void *)data;

if (ohtbl_lookup(htbl, &temp) == 0)
   return 1;

/*****************************************************************************
*                                                                            *
*  Use double hashing to hash the key.                                       *
*                                                                            *
*****************************************************************************/

for (i = 0; i < htbl->positions; i++) {

   position = (htbl->h1(data) + (i * htbl->h2(data))) % htbl->positions;

   if (htbl->table[position] == NULL || htbl->table[position] == htbl->
      vacated) {

      /***********************************************************************
      *                                                                      *
      *  Insert the data into the table.                                     *
      *                                                                      *
      ***********************************************************************/

      htbl->table[position] = (void *)data;
      htbl->size++;
      return 0;

   }

}

/*****************************************************************************
*                                                                            *
*  Return that the hash functions were selected incorrectly.                 *
*                                                                            *
*****************************************************************************/

return -1;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- ohtbl_remove -----------------------------  *
*                                                                            *
*****************************************************************************/

int ohtbl_remove(OHTbl *htbl, void **data) {

int                position,
                   i;
 
/*****************************************************************************
*                                                                            *
*  Use double hashing to hash the key.                                       *
*                                                                            *
*****************************************************************************/

for (i = 0; i < htbl->positions; i++) {

   position = (htbl->h1(*data) + (i * htbl->h2(*data))) % htbl->positions;

   if (htbl->table[position] == NULL) {

      /***********************************************************************
      *                                                                      *
      *  Return that the data was not found.                                 *
      *                                                                      *
      ***********************************************************************/

      return -1;

      }

   else if (htbl->table[position] == htbl->vacated) {

      /***********************************************************************
      *                                                                      *
      *  Search beyond vacated positions.                                    *
      *                                                                      *
      ***********************************************************************/

      continue;

      }

   else if (htbl->match(htbl->table[position], *data)) {

      /***********************************************************************
      *                                                                      *
      *  Pass back the data from the table.                                  *
      *                                                                      *
      ***********************************************************************/

      *data = htbl->table[position];
      htbl->table[position] = htbl->vacated;
      htbl->size--;
      return 0;

   }

}

/*****************************************************************************
*                                                                            *
*  Return that the data was not found.                                       *
*                                                                            *
*****************************************************************************/

return -1;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- ohtbl_lookup -----------------------------  *
*                                                                            *
*****************************************************************************/

int ohtbl_lookup(const OHTbl *htbl, void **data) {

int                position,
                   i;
 
/*****************************************************************************
*                                                                            *
*  Use double hashing to hash the key.                                       *
*                                                                            *
*****************************************************************************/

for (i = 0; i < htbl->positions; i++) {

   position = (htbl->h1(*data) + (i * htbl->h2(*data))) % htbl->positions;

   if (htbl->table[position] == NULL) {

      /***********************************************************************
      *                                                                      *
      *  Return that the data was not found.                                 *
      *                                                                      *
      ***********************************************************************/

      return -1;

      }

   else if (htbl->match(htbl->table[position], *data)) {

      /***********************************************************************
      *                                                                      *
      *  Pass back the data from the table.                                  *
      *                                                                      *
      ***********************************************************************/

      *data = htbl->table[position];
      return 0;

   }

}

/*****************************************************************************
*                                                                            *
*  Return that the data was not found.                                       *
*                                                                            *
*****************************************************************************/

return -1;

}


#endif

(2)ex-1.c

/*****************************************************************************
*                                                                            *
*  ex-1.c                                                                    *
*  ======                                                                    *
*                                                                            *
*  Description: Illustrates using an open-addressed hash table (see Chapter  *
*               8).                                                          *
*                                                                            *
*****************************************************************************/

#include <stdio.h>

#include "ohtbl.h"

/*****************************************************************************
*                                                                            *
*  Define the size of the hash table.                                        *
*                                                                            *
*****************************************************************************/

#define            TBLSIZ               11

/*****************************************************************************
*                                                                            *
*  ------------------------------ match_char ------------------------------  *
*                                                                            *
*****************************************************************************/

static int match_char(const void *char1, const void *char2) {

/*****************************************************************************
*                                                                            *
*  Determine whether two characters match.                                   *
*                                                                            *
*****************************************************************************/

return (*(const char *)char1 == *(const char *)char2);

}

/*****************************************************************************
*                                                                            *
*  ------------------------------- h1_char --------------------------------  *
*                                                                            *
*****************************************************************************/

static int h1_char(const void *key) {

/*****************************************************************************
*                                                                            *
*  Define a simplistic auxilary hash function.                               *
*                                                                            *
*****************************************************************************/

return *(const char *)key % TBLSIZ;

}

/*****************************************************************************
*                                                                            *
*  ------------------------------- h2_char --------------------------------  *
*                                                                            *
*****************************************************************************/

static int h2_char(const void *key) {

/*****************************************************************************
*                                                                            *
*  Define a simplistic auxilary hash function.                               *
*                                                                            *
*****************************************************************************/

return 1 + (*(const char *)key % (TBLSIZ - 2));

}

/*****************************************************************************
*                                                                            *
*  ------------------------------ print_table -----------------------------  *
*                                                                            *
*****************************************************************************/

static void print_table(const OHTbl *htbl) {

int                i;

/*****************************************************************************
*                                                                            *
*  Display the open-addressed hash table.                                    *
*                                                                            *
*****************************************************************************/

fprintf(stdout, "Table size is %d\n", ohtbl_size(htbl));

for (i = 0; i < TBLSIZ; i++) {

   if (htbl->table[i] != NULL && htbl->table[i] != htbl->vacated) {

      fprintf(stdout, "Slot[%03d]=%c\n", i, *(char *)htbl->table[i]);

      }

   else {

      fprintf(stdout, "Slot[%03d]= \n", i);

   }

}

return;

}

/*****************************************************************************
*                                                                            *
*  --------------------------------- main ---------------------------------  *
*                                                                            *
*****************************************************************************/

int main(int argc, char **argv) {

OHTbl              htbl;

char               *data,
                   c;

int                retval,
                   i,
                   j;

/*****************************************************************************
*                                                                            *
*  Initialize the open-addressed hash table.                                 *
*                                                                            *
*****************************************************************************/

if (ohtbl_init(&htbl, TBLSIZ, h1_char, h2_char, match_char, free) != 0)
   return 1;

/*****************************************************************************
*                                                                            *
*  Perform some open-addressed hash table operations.                        *
*                                                                            *
*****************************************************************************/

for (i = 0; i < 5; i++) {

   if ((data = (char *)malloc(sizeof(char))) == NULL)
      return 1;

   /**************************************************************************
   *                                                                         *
   *  The following expression produces "random" data while avoiding dupli-  *
   *  cates.                                                                 *
   *                                                                         *
   **************************************************************************/

   *data = ((8 + (i * 9)) % 23) + 'A';

   fprintf(stdout, "Hashing %c:", *data);

   for (j = 0; j < TBLSIZ; j++)
      fprintf(stdout," %02d", (h1_char(data) + (j * h2_char(data))) % TBLSIZ);

   fprintf(stdout, "\n");

   if (ohtbl_insert(&htbl, data) != 0)
      return 1;

   print_table(&htbl);

}

for (i = 0; i < 5; i++) {

   if ((data = (char *)malloc(sizeof(char))) == NULL)
      return 1;

   /**************************************************************************
   *                                                                         *
   *  The following expression works similar to the one above but produces   *
   *  collisions.                                                            *
   *                                                                         *
   **************************************************************************/

   *data = ((8 + (i * 9)) % 13) + 'j';

   fprintf(stdout, "Hashing %c:", *data);

   for (j = 0; j < TBLSIZ; j++)
      fprintf(stdout," %02d", (h1_char(data) + (j * h2_char(data))) % TBLSIZ);

   fprintf(stdout, "\n");

   if (ohtbl_insert(&htbl, data) != 0)
      return 1;

   print_table(&htbl);

}

if ((data = (char *)malloc(sizeof(char))) == NULL)
   return 1;

*data = 'R';

if ((retval = ohtbl_insert(&htbl, data)) != 0)
   free(data);

fprintf(stdout, "Trying to insert R again...Value=%d (1=OK)\n", retval);

if ((data = (char *)malloc(sizeof(char))) == NULL)
   return 1;

*data = 'n';

if ((retval = ohtbl_insert(&htbl, data)) != 0)
   free(data);

fprintf(stdout, "Trying to insert n again...Value=%d (1=OK)\n", retval);

if ((data = (char *)malloc(sizeof(char))) == NULL)
   return 1;

*data = 'o';

if ((retval = ohtbl_insert(&htbl, data)) != 0)
   free(data);

fprintf(stdout, "Trying to insert o again...Value=%d (1=OK)\n", retval);

fprintf(stdout, "Removing R, n, and o\n");

c = 'R';
data = &c;

if (ohtbl_remove(&htbl, (void **)&data) == 0)
   free(data);

c = 'n';
data = &c;

if (ohtbl_remove(&htbl, (void **)&data) == 0)
   free(data);

c = 'o';
data = &c;

if (ohtbl_remove(&htbl, (void **)&data) == 0)
   free(data);

print_table(&htbl);

if ((data = (char *)malloc(sizeof(char))) == NULL)
   return 1;

*data = 'R';

if ((retval = ohtbl_insert(&htbl, data)) != 0)
   free(data);

fprintf(stdout, "Hashing %c:", *data);

for (j = 0; j < TBLSIZ; j++)
   fprintf(stdout, " %02d", (h1_char(data) + (j * h2_char(data))) % TBLSIZ);

fprintf(stdout, "\n");

fprintf(stdout, "Trying to insert R again...Value=%d (0=OK)\n", retval);

if ((data = (char *)malloc(sizeof(char))) == NULL)
   return 1;

*data = 'n';

if ((retval = ohtbl_insert(&htbl, data)) != 0)
   free(data);

fprintf(stdout, "Hashing %c:", *data);

for (j = 0; j < TBLSIZ; j++)
   fprintf(stdout, " %02d", (h1_char(data) + (j * h2_char(data))) % TBLSIZ);

fprintf(stdout, "\n");

fprintf(stdout, "Trying to insert n again...Value=%d (0=OK)\n", retval);

if ((data = (char *)malloc(sizeof(char))) == NULL)
   return 1;

*data = 'o';

if ((retval = ohtbl_insert(&htbl, data)) != 0)
   free(data);

fprintf(stdout, "Hashing %c:", *data);

for (j = 0; j < TBLSIZ; j++)
   fprintf(stdout, " %02d", (h1_char(data) + (j * h2_char(data))) % TBLSIZ);

fprintf(stdout, "\n");

fprintf(stdout, "Trying to insert o again...Value=%d (0=OK)\n", retval);

print_table(&htbl);

fprintf(stdout, "Inserting X\n");

if ((data = (char *)malloc(sizeof(char))) == NULL)
   return 1;

*data = 'X';

if (ohtbl_insert(&htbl, data) != 0)
   return 1;

print_table(&htbl);

if ((data = (char *)malloc(sizeof(char))) == NULL)
   return 1;

*data = 'Y';

if ((retval = ohtbl_insert(&htbl, data)) != 0)
   free(data);

fprintf(stdout, "Trying to insert into a full table...Value=%d (-1=OK)\n",
   retval);

c = 'o';
data = &c;

if (ohtbl_lookup(&htbl, (void **)&data) == 0)
   fprintf(stdout, "Found an occurrence of o\n");
else
   fprintf(stdout, "Did not find an occurrence of X\n");

c = 'Z';
data = &c;

if (ohtbl_lookup(&htbl, (void **)&data) == 0)
   fprintf(stdout, "Found an occurrence of Z\n");
else
   fprintf(stdout, "Did not find an occurrence of Z\n");

/*****************************************************************************
*                                                                            *
*  Destroy the open-addressed hash table.                                    *
*                                                                            *
*****************************************************************************/

fprintf(stdout, "Destroying the hash table\n");
ohtbl_destroy(&htbl);

return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
There are many books on data structures and algorithms, including some with useful libraries of C functions. Mastering Algorithms with C offers you a unique combination of theoretical background and working code. With robust solutions for everyday programming tasks, this book avoids the abstract style of most classic data structures and algorithms texts, but still provides all of the information you need to understand the purpose and use of common programming techniques. Implementations, as well as interesting, real-world examples of each data structure and algorithm, are included. Using both a programming style and a writing style that are exceptionally clean, Kyle Loudon shows you how to use such essential data structures as lists, stacks, queues, sets, trees, heaps, priority queues, and graphs. He explains how to use algorithms for sorting, searching, numerical analysis, data compression, data encryption, common graph problems, and computational geometry. And he describes the relative efficiency of all implementations. The compression and encryption chapters not only give you working code for reasonably efficient solutions, they offer explanations of concepts in an approachable manner for people who never have had the time or expertise to study them in depth. Anyone with a basic understanding of the C language can use this book. In order to provide maintainable and extendible code, an extra level of abstraction (such as pointers to functions) is used in examples where appropriate. Understanding that these techniques may be unfamiliar to some programmers, Loudon explains them clearly in the introductory chapters. Contents include: Pointers Recursion Analysis of algorithms Data structures (lists, stacks, queues, sets, hash tables, trees, heaps, priority queues, graphs) Sorting and searching Numerical methods Data compression Data encryption Graph algorithms Geometric algorithms
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值