Hash table is a comprehensive application of arrays, linked lists, and mathematical algorithms. It is of great value both in theory and practice. If you don't talk much about it, paste your own implementations for reference. If there are any errors, please point out. Another task that needs to be done is to design a detailed and rigorous test for the linked list and hash table used in implementation.
The hash table contains four files: Common. H, linklist. C, hashtable. C, and Main. C. Put them in the same folder and compile and run them as follows:
$ Gcc-wall *. C-o main
$ Main
Or a simple MAKEFILE file:
Objs = hashtable. O main. O linklist. o
Mhash: $ (objs)
[Tab] CC-O mhash $ (objs)
Hashsearch. O: hashtable. c Common. h
[Tab] CC-C hashtable. c
Main. O: Main. c Common. h
[Tab] CC-C main. c
Linklist. O: linklist. c Common. h
[Tab] CC-C linklist. c
. Phony: clean
Clean:
[Tab]-RM $ (objs) mhash
$ Make
$ Mhash
The specific implementation of each file is as follows:
Common. h
/** Common. H * description and definition of hash searches and linked list structures. ** Hash Lookup method: * use the hash function of the string hash function and the link address method conflict solution **/Enum {OK = 1, error = 0, true = 1, false = 0, failure = 1, len_of_table = 13, record_num = 95}; typedef struct {/* record type */char * key; int value;} record; typedef struct node * llnptr; typedef struct node {/* linked list node type */record data; llnptr next;} llnode; typedef int status;/* function declaration of a single-chain table, follow the description */status initlist (llnptr * List) in instructor Yan Weimin's "Data Structure C language version";/* create a single-chain table for the lead node */INT isempty (llnptr list ); /* judge whether a single-chain table is empty */INT listlength (llnptr list);/* return the length of the linked list, that is, the number of records (excluding the header node) */status getrecord (llnptr list, int I, record * E);/* return the node at position I in the linked list, and save it in E */status listinsert (llnptr list, int I, record E);/* Insert record e to position I in the list of linked lists */status listdelete (llnptr list, int I, record * E ); /* Delete the record at position I in the list of linked lists and use e to return */status listtraverse (llnptr list, void (* visit) (record * E )); /* use the visit traversal list */status listprint (llnptr list);/* print the content of the linked list */void printrecord (record * E ); /* print the record content */INT equal (record * E1, record * E2 ); /* determine the equality of records * // * return the pointer of the record whose values meet the Compare relationship with E in the list of linked lists. If no value exists, null */record * plocaterecord (llnptr list, record E, INT (* compare) (record * E1, record * E2);/* function declaration for hash search */INT Hash (char * Key ); /* calculate the hash value of the keyword */status inittable (llnptr hashtable []);/* initialize the hash table hashtable */status hashinsert (llnptr hashtable [], Record E ); /* insert records into the hashtable */record * hashsearch (llnptr hashtable [], Record E);/* search by record Keyword: If yes, a pointer to the record is returned, otherwise, null */status hashtraverse (llnptr hashtable []) is returned./* traverse the hash table */
Linklist. c
/* Linklist. C * // * single-chain table implementation of the leading node. the header node stores the table length information */# include <stdio. h> # include <stdlib. h> # include <string. h> # include "Common. H "status initlist (llnptr * List) {llnptr head = (llnptr) malloc (sizeof (llnode); If (! Head) {fprintf (stderr, "error: fail to allocate memory! \ N "); Return Error;} head-> data. value = 0;/* The Value Field of the header node stores the table length */head-> data. key = NULL;/* The key field of the header node is not used */head-> next = NULL; * List = head; Return OK;} int isempty (llnptr List) {return list-> data. value = 0;} int listlength (llnptr list) {return list-> data. value;} status getrecord (llnptr list, int I, record * E) {/* obtains the I element in the table list, use E to return */llnptr P = List-> next;/* P to point to the first record node */If (isempty (list )){ Fprintf (stderr, "error: List empty! \ N "); Return Error;} if (I <1 | I> listlength (list) {fprintf (stderr," error: Position parameter % d out of range! \ N ", I); Return Error;} while (-- I) P = p-> next; /* P points to the I-th element */* E = p-> data; Return OK;} record * plocaterecord (llnptr list, Record E, INT (* compare) (record * E1, record * E2) {/* returns the record pointer that matches the Compare relationship with the given element e in the table list */llnptr P = List-> next; while (p) {If (compare (& P-> data, & E) Return & P-> data; P = p-> next;} return NULL ;} status listinsert (llnptr list, int I, Record E) {/* Insert record e to position I in table list */ Llnptr S, P = List; Int J = 0;/* j as counter */if (I <1 | I> listlength (list) + 1) {fprintf (stderr, "Error: Position parameter % d out of range! \ N ", I); Return Error;} while (P & J <i-1) {P = p-> next; j ++;} s = (llnptr) malloc (sizeof (llnode); If (! S) {fprintf (stderr, "error: fail to allocate memory! \ N "); Return Error;} s-> DATA = E; s-> next = p-> next; P-> next = s; List-> data. value ++; Return OK;} status listdelete (llnptr list, int I, record * E) {/* delete records at position I in the table list, use E to return */llnptr p1 = List; llnptr P2; Int J = 0;/* j as the counter */If (isempty (list) {printf ("error: list empty! \ N "); Return Error;} if (I <1 | I> listlength (list) {printf (" error: Invalid index! \ N "); Return Error;} while (P1-> next & J <i-1) {/* P1 points to the I-1 element */P1 = p1-> next; j ++;} P2 = p1-> next;/* P2 points to the I-th element */* E = P2-> data; P1-> next = P2-> next; free (P2); List-> data. value --; Return OK;} status listtraverse (llnptr list, void (* visit) (record * E )) {/* use the visit function to traverse the elements in the table list that have only one */llnptr P = List-> next; If (isempty (list) {printf ("list empty! \ N "); Return Error;} while (p) {visit (& P-> data); P = p-> next;} Return OK ;} status listprint (llnptr list) {return listtraverse (list, printrecord);} void printrecord (record * E) {printf ("(% s, % d) \ n ", e-> key, e-> value);} int equal (record * E1, record * E2) {return strcmp (E1-> key, E2-> key) = 0 ;}
Hashtable. c
// Hashtable. C // Implementation of hash functions # include <stdio. h> # include "Common. H "int Hash (char * Key) {char * P = key; int hash = 17; while (* P) {hash = hash * 37 + (* P ); P ++;} printf ("Key = % s \ thash = % d, hash % d = % d \ n", key, hash, len_of_table, hash % len_of_table); Return hash % len_of_table;} status inittable (llnptr table []) {int I; for (I = 0; I <len_of_table; I ++) {If (! Initlist (& table [I]) {Return Error ;}} Return OK;} status hashinsert (llnptr table [], Record E) {int t_index = hash (E. key); If (plocaterecord (Table [t_index], E, equal) {/* this record already exists in the hash table */printf ("record exists, nothing to do. "); Return OK;} int ins_pos = listlength (Table [t_index]) + 1; if (! Listinsert (Table [t_index], ins_pos, E) {return error;} Return OK;} record * hashsearch (llnptr table [], Record E) {int t_index = hash (E. key); return plocaterecord (Table [t_index], E, equal);} status hashtraverse (llnptr table []) {int I; printf ("the hash table: \ n "); for (I = 0; I <len_of_table; I ++) {printf (" list [% d]: \ n ", I ); listprint (Table [I]); printf ("\ n");} Return OK ;}
Main. c
# Include <stdio. h> # include <stdlib. h> # include <string. h> # include "Common. H "char * tostring (int I); int main () {printf (" program start up... \ n ");/* The table length is a hash table of len_of_table. Each element is a single-chain table pointer */llnptr hashtable [len_of_table]; record RDS [record_num]; record * PE; record * QE; int I; If (! Inittable (hashtable) {fprintf (stderr, "error: fail to initialize the hashtable! \ N "); exit (failure);} printf (" initialize the hashtable successfully! \ N "); hashtraverse (hashtable); for (I = 0; I <record_num; I ++) {RDS [I]. key = tostring (I); RDS [I]. value = I; printf ("record: (% S % d) \ n", RDS [I]. key, RDS [I]. value); printf ("prepare to insert... "); If (! Hashinsert (hashtable, RDS [I]) {printf ("failed to insert record! ") ;}} Hashtraverse (hashtable); Pe = (record *) malloc (sizeof (record); pe-> key =" 11111 "; Qe = hashsearch (hashtable, * PE); If (QE! = NULL) {printrecord (QE);} else {printf ("record not found. \ n ") ;}pe-> key =" 11112 "; Qe = hashsearch (hashtable, * PE); If (QE! = NULL) {printrecord (QE);} else {printf ("record not found. \ n ") ;}return 0 ;}char * tostring (int I) {char * P = (char *) malloc (5 * sizeof (char) + 1 ); char * q; If (! P) {fprintf (stderr, "error, fail to allocate memory. "); exit (failure);} q = P; while (q <p + 5) {* q = I +''; q ++ ;} * q = '\ 0'; return P ;}