C language to achieve hash table (chain method)

The author recently learned the hash table in the data structure and implemented it simply in C language.
Of course there are many references to the source code, this blog is designed to exchange ideas

Hash table principle

The structure is described as follows:

typedef struct element
{
	int key;
	int value;
	int hash;
}Element;

Element represents the type of each storage unit and is a custom structure.
value is the value stored under Element (you can change it to others).
key is the key value used to build the hash table (the only value that is not repeated)
hash is the value obtained by the hash function.

typedef struct Pnode
{
	Element *data;
	struct Pnode *next;
}Node;

Node is a node of a singly linked list.
Store
the pointer field next to the value of Element and the next node address

typedef struct hash_table
{
	int size;
	int length;
	struct Pnode *head;
}Hash_table;

Hash_table is a hash table structure.
Store the size of the hash table size (here related to the hash function, mine is REMAINDER = 11) and length (number of stored elements).
The head field stores the address of the array index 0 on the left side of the figure below.
Insert picture description here
Note: The way to resolve the conflict by the zipper method is to connect the conflicting element behind the node that conflicts with it, thereby forming a single linked list.

Part of the function description (involving the use of the malloc function and the operation of the singly linked list):
Initialization of the table header:

Hash_table* Creat_Table(int table_size)
{
	Hash_table *h = (Hash_table *)malloc(sizeof(Hash_table));
	h->size = REMAINDER;
	h->head = (Node *)malloc((h->size)*sizeof(Node));
	h->length = 0;
	int i = 0;
	for(i=0 ; i<h->size ; i++)
	{
		h->head[i].next = NULL;
	}
	return h;
}

Create a hash table and return the header pointer.
At the same time, create an array of length eleven for the head field under the table header, and assign the head address to head.
At the same time initialize the table, the size is set to REMAINDER 11, the length is set to zero, and the next field of each node under the head is assigned a null (to prevent errors due to compiler reasons).

Insert function:
In fact, it is more convenient to pass the address of the structure (I did not realize it when I was lazy ...)

void Insert(Hash_table *h , Element k)
{
	Node * p = lookup(h,k.key);
	if(!p)
	{
		Node *q = (Node *)malloc(sizeof(Node));
		q->data = (Element *)malloc(sizeof(Element));
		(q->data)->key = k.key;
		(q->data)->value = k.value;
		int position;
		position = (q->data)->hash  = hash(k.key);
		q->next = h->head[position].next;
		h->head[position].next = q;
		
		h->length += 1; 
		return ;
	}
	else
	{
		printf("The keys is exist !\n");
		return ;
	}
}

First find out whether the value passed in is already in the hash table (exit if it exists).
If it does not exist:
open up a new Element field and assign the structure to him (there is no pot to pass the address, resulting in a rough implementation, the reader can try a simpler method.)
And calculate the hash value corresponding to the key, and The node is assigned to the specified position (involving the operation of the singly linked list).
Note that whether it conflicts or not, the implementation method is unchanged (this is also one of the benefits of the zipper method, and it is easy to insert)

Find function:

Node *lookup(Hash_table *h , int key)
{
	int i;
	i = hash(key);
	Node * p = h->head[i].next;
	while(p && key != p->data->key)
	{
		p = p->next;
	}

	return p;
}

First calculate the hash value corresponding to the key value, and check the nodes of the singly linked list at the corresponding position one by one, and return their addresses.

The source code is as follows:

#include<stdio.h>
#include<stdlib.h>

#define REMAINDER 11	// 通常是质数

typedef struct element
{
	int key;		
	int value;
	int hash;
}Element;

typedef struct Pnode
{
	Element *data;
	struct Pnode *next;
}Node;

typedef struct hash_table
{
	int size;
	int length;
	struct Pnode *head;
}Hash_table;


int hash(int value)
{
	return value%REMAINDER;
}

Hash_table* Creat_Table(int table_size)
{
	Hash_table *h = (Hash_table *)malloc(sizeof(Hash_table));
	h->size = REMAINDER;
	h->head = (Node *)malloc((h->size)*sizeof(Node));
	h->length = 0;
	int i = 0;
	for(i=0 ; i<h->size ; i++)
	{
		h->head[i].next = NULL;
	}
	return h;
}

Node *lookup(Hash_table *h , int key)
{
	int i;
	i = hash(key);
	Node * p = h->head[i].next;
	while(p && key != p->data->key)
	{
		p = p->next;
	}

	return p;
}

void Insert(Hash_table *h , Element k)
{
	Node * p = lookup(h,k.key);
	if(!p)
	{
		Node *q = (Node *)malloc(sizeof(Node));
		q->data = (Element *)malloc(sizeof(Element));
		(q->data)->key = k.key;
		(q->data)->value = k.value;
		int position;
		position = (q->data)->hash  = hash(k.key);
		q->next = h->head[position].next;
		h->head[position].next = q;
		
		h->length += 1; 
		return ;
	}
	else
	{
		printf("The keys is exist !\n");
		return ;
	}
}

void Destroy_Table(Hash_table *h)
{
	int i;
	Node *p , *q;
	for(i=0 ; i<h->size ; i++)
	{
		p = h->head[i].next;
		while(p)
		{
			q=p->next;
			free(p);
			p=q;
		}
	}
	free(h->head);
	free(h);
}

void print_Table(Hash_table *h)
{
	int i = 0; 
	for (i = 0; i < h->size ; i++)
    {
        Node * p = h->head[i].next;
        while (p)
        {
            printf("[%d-%d] ",p->data->key, p->data->value);
            p = p->next;
        }
        printf("NULL\n");
    }
}

int main()
{
	Element a[]={{12,1},{2,2},{31,3},{45,4},{8,5}};
	
	int n = sizeof(a)/sizeof(Element);
	Hash_table *h = Creat_Table(n);
	int i = 0;
	for(i = 0 ; i<n ; i++)
	{
		Insert(h,a[i]);
	}
	print_Table(h);		// 打印哈希表 
	printf("%d\n\n", lookup(h,12)->data->key);	//查找key值为12的Element  
	printf("%d\n",h->length);	//打印哈希表的元素个数 
	Destroy_Table(h);	// 摧毁哈希表 
	return 0;
}

Source code screenshot:

Published 7 original articles · won 12 · views 775

Guess you like

Origin blog.csdn.net/M_H_T__/article/details/103208460