next up previous contents
Next: Heap/Priority Queue: ADT Up: Hash Tables: ADT Previous: Open (Pointer) Hashing: ohash   Contents

Closed (Array) Hashing [109]

% gcc -o chash chash.c                                 > tcc chash.c
% chash
> h
h(elp; q(uit; c(reate size; i(nsert x; D(elete x; d(isplay r(ehash Q(uadratic

Data File with Test Cases: chash.dat

i 89 i 18 i 49 i 58 i 69 d
D 89 d
c 10 Q d
i 89 i 18 i 49 i 58 i 69 d
r d



Closed Hashing: Linear Probing [110]

Linear Probing: if collision, then search for empty spot incrementally:

pos = hash(key,H_SIZE);
while (table[pos] != EMPTY_DATA) { /* collision */
  pos = (++pos % H_SIZE);
}
position  empty  i 89  i 18  i 49  i 58  i 69  D 89
---------------------------------------------------
       0     -1    -1    -1    49    49    49    49
       1     -1    -1    -1    -1    58    58    58
       2     -1    -1    -1    -1    -1    69    69
       3     -1    -1    -1    -1    -1    -1    -1
       4     -1    -1    -1    -1    -1    -1    -1
       5     -1    -1    -1    -1    -1    -1    -1
       6     -1    -1    -1    -1    -1    -1    -1
       7     -1    -1    -1    -1    -1    -1    -1
       8     -1    -1    18    18    18    18    18
       9     -1    89    89    89    89    89    -2

Find: hash, start scanning for key or EMPTY_DATA

Delete: mark it as DEL_DATA (-2) so other keys can still be found

(How does this change the code above?)



Closed Hashing: Quadratic Probing [111]

Problem with Linear Probing: makes long sequential clusters

Quadratic Probing, if collision:

try next cell away ($1^2$)

then 4 cells away ($2^2$)

then 9 cells away ($3^2$)

$f(i)=i^2$

Linear Probing: $f(i)=i$

position  empty  i 89  i 18  i 49  i 58  i 69
---------------------------------------------
       0     -1    -1    -1    49    49    49
       1     -1    -1    -1    -1    -1    -1
       2     -1    -1    -1    -1    58    58
       3     -1    -1    -1    -1    -1    69
       4     -1    -1    -1    -1    -1    -1
       5     -1    -1    -1    -1    -1    -1
       6     -1    -1    -1    -1    -1    -1
       7     -1    -1    -1    -1    -1    -1
       8     -1    -1    18    18    18    18
       9     -1    89    89    89    89    89



Closed Hashing: Rehashing [112]

Important: keep $\lambda <= 0.5$

If table fills up or clusters slow down performance: rehash.

Make a new table with ``doubled'' H_SIZE.

Insert old keys into new table.

Note: in general, H_SIZE should be prime.

position  entry    position  entry
----------------------------------
       0     -1          10     69
       1     -1          11     -1
       2     -1          12     -1
       3     -1          13     -1
       4     -1          14     -1
       5     -1          15     -1
       6     -1          16     -1
       7     -1          17     -1
       8     -1          18     58
       9     49          19     18



Closed Hashing: chash.c [113]

#define EMPTY_DATA -1
#define DEL_DATA -2
#define NOT_FOUND -1
#define LINEAR_PROBING 0
#define QUADRATIC_PROBING 1
int probing = LINEAR_PROBING;

typedef int element_type;
typedef int INDEX;

struct hash_entry {
  element_type element;
};

typedef INDEX position;
typedef struct hash_entry cell;

struct hash_tbl {
  unsigned int table_size;
  cell *the_cells;
};

typedef struct hash_tbl *HASH_TABLE;


Open Hashing: chash.c [114]
HASH_TABLE create_hash_table(unsigned int table_size) {
  HASH_TABLE H;
  int i;
   
  H = (HASH_TABLE) malloc(sizeof(struct hash_tbl));
  if (H == NULL)
    printf("Out of space!\n");
  else {
    H->table_size = table_size;
    H->the_cells = (cell *) malloc(sizeof(cell)*H->table_size);
    if (H->the_cells == NULL)
      printf("Out of space!\n");
    else {
      for (i=0; i<H->table_size; i++) 
        H->the_cells[i].element = EMPTY_DATA;
    }
  }
  return(H);
}


Open Hashing: chash.c [115]
position find(element_type key, HASH_TABLE H) {
  position i, current_pos;
  i = 0;
  current_pos = hash(key, H->table_size);
  while ((H->the_cells[current_pos].element != EMPTY_DATA) && 
         (H->the_cells[current_pos].element != key)) {  
    if (probing == LINEAR_PROBING)
      current_pos = (++current_pos % H->table_size);
    else { /* QUADRATIC PROBING */
      current_pos += 2*(++i) - 1;
      if (current_pos >= H->table_size) 
        current_pos -= H->table_size;
    }
  }
  return(current_pos);
} 
position insert(element_type key, HASH_TABLE H) {
  position pos;
  pos = find(key,H);
   if ((H->the_cells[pos].element == EMPTY_DATA) ||
       (H->the_cells[pos].element == DEL_DATA))
     H->the_cells[pos].element = key; 
  else pos = NOT_FOUND;
  return(pos);
}


Open Hashing: chash.c [116]
position delete(element_type key, HASH_TABLE H) {
  position pos;
  
  pos = find(key,H);
  if (H->the_cells[pos].element == key) 
    H->the_cells[pos].element = DEL_DATA; 
  else
    pos = NOT_FOUND;
  return(pos);
}

HASH_TABLE rehash(HASH_TABLE H) {
  unsigned int i, old_size;
  cell *old_cells;
  
  old_cells = H->the_cells;
  old_size = H->table_size;
  H = create_hash_table(2*old_size);
  for (i=0; i<old_size; i++)
    if ((old_cells[i].element != EMPTY_DATA) && 
       (old_cells[i].element != DEL_DATA))
      insert(old_cells[i].element,H);
  free(old_cells);                         /* Memory Leak ? */
  return(H);
}


next up previous contents
Next: Heap/Priority Queue: ADT Up: Hash Tables: ADT Previous: Open (Pointer) Hashing: ohash   Contents
Ted Billard 2001-10-25