散列表(hash table)

A hash table generalizes the simpler notion of an ordinary array. Directly addressing into an ordinary array makes effective use of our ability to examine an arbitrary position in an array in O(1) time.
散列表(hash table)是普通数组概念的推广。
冲突(collision)即多个关键字映射到数组的同一下标。
处理(较少)冲突的方法
1)精心的设计散列函数(hash function);
2)链接法(chainning):将散列到同一个槽中的所有元素都放到一个链表中;
     开发寻址法(open addressing):通过探查(probe),将所有元素都存放到散列表里。

散列表(hash table)_第1张图片散列表(hash table)_第2张图片

#ifdef MY_HASH

#ifndef _MY_HASH_TABLE_H
#define _MY_HASH_TABLE_H

/* singly linked list */
typedef struct hash_node {
	struct hash_node *next;
} HASH_NODE;

typedef struct hash_table {
	HASH_NODE *array;
	unsigned long size;
	unsigned long count;
	unsigned long key_offset;
} HASH_TABLE;


void hash_create(HASH_TABLE *hash_table, unsigned long size, unsigned long key_offset);

void hash_insert(HASH_TABLE *hash_table, HASH_NODE *node);

void hash_delete(HASH_TABLE *hash_table, HASH_NODE *node);

void hash_destroy(HASH_TABLE *hash_table);

HASH_NODE *hash_find_node_by_key(HASH_TABLE *hash_table, unsigned long key);

#endif

#endif
#define MY_HASH
#ifdef MY_HASH

#include 
#include 

#include "hash.h"

#define HASH_GET_NODE_KEY(hash_table, node)                                   \
    (*(((unsigned long *)(((unsigned char *)(node)) + (hash_table)->key_offset))))

#define HASH_GET_BUCKET_INDEX(hash_table, key)                                   \
    (key  % hash_table->size)

/*
参数:HASH_TABLE *hash_table, unsigned long size, unsigned long key_offset
返回值:void
作用:创建一个哈希表
*/
void hash_create(HASH_TABLE *hash_table, unsigned long size, unsigned long key_offset)
{
	int index = 0;

	if (hash_table == NULL) {
		return;
	}

	hash_table->array = (HASH_NODE *)malloc(sizeof(HASH_NODE) * size);
	if (hash_table->array == NULL) {
		printf("malloc error!\n");
		return;
	}

	hash_table->size = size;
	hash_table->count = 0;
	hash_table->key_offset = key_offset;

	for (; index < size; index++) {
		(hash_table->array + index)->next = NULL;
	}
}

/*
参数:HASH_TABLE *hash_table, HASH_NODE *node
返回值:void
作用:将节点node插入到哈希表
*/
void hash_insert(HASH_TABLE *hash_table, HASH_NODE *node)
{
	unsigned long key = 0;
	unsigned long index = 0;

	if (hash_table == NULL || node == NULL) {
		return;
	}

	key = HASH_GET_NODE_KEY(hash_table, node);
	index = HASH_GET_BUCKET_INDEX(hash_table, key);

	node->next = (hash_table->array + index)->next;
	(hash_table->array + index)->next = node;
	hash_table->count++;
}

/*
参数:HASH_TABLE *hash_table, HASH_NODE *node
返回值:void
作用:从哈希表中删除节点node
*/
void hash_delete(HASH_TABLE *hash_table, HASH_NODE *node)
{
	unsigned long key = 0;
	unsigned long index = 0;
	HASH_NODE *prev = NULL;
	HASH_NODE *iter = NULL;

	if (hash_table == NULL || node == NULL) {
		return;
	}

	key = HASH_GET_NODE_KEY(hash_table, node);
	index = HASH_GET_BUCKET_INDEX(hash_table, key);

	prev = hash_table->array + index;
	iter = (hash_table->array + index)->next;
	while (iter != NULL) {
		if (iter == node) {
			prev->next = node->next;
			node->next = NULL;
			break;
		}

		prev = iter;
		iter = iter->next;
	}

	hash_table->count--;
}

/*
参数:HASH_TABLE *hash_table
返回值:void
作用:释放哈希表(不完善)
*/
void hash_destroy(HASH_TABLE *hash_table)
{
	if (hash_table == NULL) {
		return;
	}

	free(hash_table->array);
	hash_table->array = NULL;
}

/*
参数:HASH_TABLE *hash_table, unsigned long key
返回值:HASH_NODE *
作用:通过key来查找节点
*/
HASH_NODE *hash_find_node_by_key(HASH_TABLE *hash_table, unsigned long key)
{
	unsigned long index = 0;
	HASH_NODE *node = NULL;

	if (hash_table == NULL) {
		return NULL;
	}

	index = HASH_GET_BUCKET_INDEX(hash_table, key);

	node = (hash_table->array + index)->next;
	while (node != NULL) {
		if (key == HASH_GET_NODE_KEY(hash_table, node)) {
			return node;
		}

		node = node->next;
	}

	return NULL;
}

#endif
#pragma once

#ifndef _MY_HASH2_TABLE_H
#define _MY_HASH2_TABLE_H

/* singly linked list */
typedef struct hash_node {
	struct hash_node *next;
	struct hash_node *prev;
} HASH_NODE;

typedef struct hash_table {
	HASH_NODE *array;
	unsigned long size;
	unsigned long count;
	unsigned long key_offset;
} HASH_TABLE;


void hash_create(HASH_TABLE *hash_table, unsigned long size, unsigned long key_offset);

void hash_insert(HASH_TABLE *hash_table, HASH_NODE *node);

void hash_delete(HASH_TABLE *hash_table, HASH_NODE *node);

void hash_destroy(HASH_TABLE *hash_table);

HASH_NODE *hash_find_node_by_key(HASH_TABLE *hash_table, unsigned long key);

#endif

#include 
#include 

#include "hash2.h"

#define HASH_GET_NODE_KEY(hash_table, node)                                   \
    (*(((unsigned long *)(((unsigned char *)(node)) + (hash_table)->key_offset))))

#define HASH_GET_BUCKET_INDEX(hash_table, key)                                   \
    (key  % hash_table->size)

/*
参数:HASH_TABLE *hash_table, unsigned long size, unsigned long key_offset
返回值:void
作用:创建一个哈希表
*/
void hash_create(HASH_TABLE *hash_table, unsigned long size, unsigned long key_offset)
{
	int index = 0;

	if (hash_table == NULL) {
		return;
	}

	hash_table->array = (HASH_NODE *)malloc(sizeof(HASH_NODE) * size);
	if (hash_table->array == NULL) {
		printf("malloc error!\n");
		return;
	}

	hash_table->size = size;
	hash_table->count = 0;
	hash_table->key_offset = key_offset;

	for (; index < size; index++) {
		(hash_table->array + index)->next = NULL;
	}
}

/*
参数:HASH_TABLE *hash_table, HASH_NODE *node
返回值:void
作用:将节点node插入到哈希表
*/
void hash_insert(HASH_TABLE *hash_table, HASH_NODE *node)
{
	unsigned long key = 0;
	unsigned long index = 0;

	if (hash_table == NULL || node == NULL) {
		return;
	}

	key = HASH_GET_NODE_KEY(hash_table, node);
	index = HASH_GET_BUCKET_INDEX(hash_table, key);

	node->prev = NULL;
	node->next = (hash_table->array + index)->next;	
	(hash_table->array + index)->next = node;
	if (node->next != NULL) { // not empty
		node->next->prev = node;
	}

	hash_table->count++;
}

/*
参数:HASH_TABLE *hash_table, HASH_NODE *node
返回值:void
作用:从哈希表中删除节点node
*/
void hash_delete(HASH_TABLE *hash_table, HASH_NODE *node)
{
	unsigned long key = 0;
	unsigned long index = 0;

	if (hash_table == NULL || node == NULL) {
		return;
	}

	if (node->prev != NULL) {
		node->prev->next = node->next;
	} else { // first node
		key = HASH_GET_NODE_KEY(hash_table, node);
		index = HASH_GET_BUCKET_INDEX(hash_table, key);
		(hash_table->array + index)->next = node->next;
	}

	if (node->next != NULL) { // not last one
		node->next->prev = node->prev;
	}

	node->prev = NULL;
	node->next = NULL;

	hash_table->count--;
}

/*
参数:HASH_TABLE *hash_table
返回值:void
作用:释放哈希表(不完善)
*/
void hash_destroy(HASH_TABLE *hash_table)
{
	if (hash_table == NULL) {
		return;
	}

	free(hash_table->array);
	hash_table->array = NULL;
}

/*
参数:HASH_TABLE *hash_table, unsigned long key
返回值:HASH_NODE *
作用:通过key来查找节点
*/
HASH_NODE *hash_find_node_by_key(HASH_TABLE *hash_table, unsigned long key)
{
	unsigned long index = 0;
	HASH_NODE *node = NULL;

	if (hash_table == NULL) {
		return NULL;
	}

	index = HASH_GET_BUCKET_INDEX(hash_table, key);

	node = (hash_table->array + index)->next;
	while (node != NULL) {
		if (key == HASH_GET_NODE_KEY(hash_table, node)) {
			return node;
		}

		node = node->next;
	}

	return NULL;
}

#include 
#include 
#include 

#include "hash2.h"

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

typedef struct life {
	HASH_NODE node;
	int work;
	int study;
	int play;
} LIFT;

void hash_print(HASH_TABLE *hash_table)
{
	unsigned long index = 0;
	HASH_NODE *iter = NULL;
	LIFT *life = NULL;

	for (; index < hash_table->size; index++) {
		iter = hash_table->array[index].next;
		while (iter != NULL) {
			life = (LIFT *)iter;
			printf("%2d: work: %d, strudy: %d, play: %d\n",
				index, life->work, life->study, life->play);
			iter = iter->next;
		}
	}

	printf("\n");
}

int main()
{
	int i = 0;
	int arr[] = { 123, 4, 3, 34, 35, 7, 8, 9, 5, 4, 2, 1 };
	int len = sizeof(arr) / sizeof(arr[0]);
	HASH_TABLE real_life;
	LIFT *my_life = NULL;

	hash_create(&real_life, len, offsetof(LIFT, work));
	for (i = 0; i < len; i++) {
		my_life = (struct life *)malloc(sizeof(struct life));
		if (my_life == NULL) {
			printf("malloc error!\n");
			return 1;
		}

		my_life->node.prev = NULL;
		my_life->node.next = NULL;
		my_life->work = arr[i];
		my_life->study = arr[i] + 1;
		my_life->play = arr[i] + 2;
		
		hash_insert(&real_life, &(my_life->node));
	}

	hash_print(&real_life);

	for (i = 0; i < len; i++) {
		my_life = hash_find_node_by_key(&real_life, arr[i]);
		hash_delete(&real_life, &(my_life->node));
		free(my_life);
		my_life = NULL;

		hash_print(&real_life);
	}

	hash_destroy(&real_life);

	getchar();

	return 0;
}

 

你可能感兴趣的:(算法,C语言基础)