C语言实现哈希表HashTable及迅雷面试题哈希表桶结构代码

本文利用除留取余法+链地址法实现哈希表,并针对迅雷面试题写出相关代码。

一:哈希表

哈希表代码如下:

#ifndef _HASH_TABLE_H
#define _HASH_TABLE_H

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

#define ElemType int
#define N 7

typedef struct HashNode{
	ElemType m_data;
	struct HashNode *link;
} HashNode, *HashTable[N];

/*
void init_htable(HashTable* pht)     //自己的初始化方法
{
	for(int i=0; i<N; ++i){
		(*pht)[i] = (HashNode *)NULL;
	}
}
*/

void init_htable(HashTable pht)    //另一种初始化方法
{
	for(int i=0; i<N; ++i){
		pht[i] = NULL;
	}
}

int hash_maker(ElemType key)
{
	return key % N;
}

void insert_elem_front(HashTable pht, const ElemType val)
{
	int index = hash_maker(val);

	HashNode *new_node = (HashNode *)malloc(sizeof(HashNode));
	assert(new_node != NULL);
	new_node->m_data = val;

	new_node->link = pht[index];
	pht[index] = new_node;
}

void insert_elem_back(HashTable pht, const ElemType val)
{
	int index = hash_maker(val);

	HashNode *new_node = (HashNode *)malloc(sizeof(HashNode));
	assert(new_node != NULL);
	new_node->m_data = val;
	new_node->link = NULL;

	if(pht[index] == NULL){
		pht[index] = new_node;
	}
	else{
		HashNode *tmp = pht[index];
		while(tmp->link != NULL)
			tmp = tmp->link;
		tmp->link = new_node;
	}
}

HashNode* search_elem(HashTable pht, const ElemType target)
{
	int index = hash_maker(target);

	HashNode *tmp = pht[index];
	while(tmp != NULL && tmp->m_data != target) //while(tmp!=NULL, tmp->data!=target)->segemention fault,逗号会同时计算表达式
		tmp = tmp->link;
	return tmp;
}


bool remove_elem(HashTable pht, const ElemType target)
{
	HashNode* found = search_elem(pht, target);
	if(found == NULL)
		return false;

	int index = hash_maker(target);
	HashNode *tmp = pht[index];
	
	if(tmp == found){
		pht[index] = tmp->link;
	}
	else{
		while(tmp->link != found){
			tmp = tmp->link;
		}
		tmp->link = found->link;
	}
	free(found);
	return true;
}

void show_htable(HashTable pht)
{
	for(int i=0; i<N; ++i){
		printf("%d ", i);

		HashNode *tmp = pht[i];
		while(tmp != NULL){
			printf("%d->", tmp->m_data);
			tmp = tmp->link;
		}
		printf("NULL\n");
	}
}

void clear_htable(HashNode* tmp)
{
	while(tmp != NULL){
		HashNode *next_tmp = tmp->link;
		free(tmp);
		tmp = tmp->link;
	}
}

void destroy_htable(HashTable pht)
{
	for(int i=0; i<N; ++i){
		clear_htable(pht[i]);
	}
}

#endif

测试代码如下:

#include "Hash_Table.h"

int main()
{
	ElemType array[] = {3, 43, 765, 4312, 431, 
					132, 65, 8, 32, 654};
	HashTable ht;
	
	//init_htable(&ht);
	init_htable(ht);

	size_t len = sizeof(array) / sizeof(ElemType);
	for(int i=0; i<len; ++i)
		insert_elem_back(ht, array[i]);    //插入元素
	printf("*************************insert*****************************\n");
	show_htable(ht);

	printf("*************************search*****************************\n");
	printf("%p\n", search_elem(ht, 4312));    //查找元素

	printf("*************************remove*****************************\n");
	remove_elem(ht, 654);            //删除元素
	show_htable(ht);

	printf("*************************destroy*****************************\n");
	destroy_htable(ht);          //摧毁Hash表
	show_htable(ht);

	return 0;
}

测试结果如下:


二:迅雷面试题

面试题大概是这样的:

  现有一个用来存放整型的Hash表,Hash的存储单位成为桶,每个桶能存放3个整数,当一个桶要存放的数据超过3个时,则要将新的元素存放在溢出桶中,每个桶也能放三个元素,多个溢出桶用链表串联起来,此Hash表的基桶数目为素数P,Hash表的Hash函数对P取模。

下文是代码,P我自己习惯用N来表示。

#ifndef _HASH_TABLE_H
#define _HASH_TABLE_H

#define N 7
#define ElemType int
#define BUCKET_SIZE 3
#define NULL_DATA -1

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

typedef struct bucket_node{
	ElemType data[BUCKET_SIZE];
	struct bucket_node *next;
} bucket_node, HashTable[N];

void init_htable(HashTable pht)
{
	for(int i=0; i<N; ++i){
		for(int j=0; j<BUCKET_SIZE; ++j){
			pht[i].data[j] = NULL_DATA;
		}
		pht[i].next = NULL;
	}
}

int hash_maker(ElemType key)
{
	return key % N;
}

bool is_bucket_full(bucket_node *pbuck)
{
	if(pbuck->data[BUCKET_SIZE-1] != NULL_DATA)
		return true;
	else
		return false;
}

void insert_elem_final(bucket_node *pbuck, const ElemType val)
{
	for(int i=0; i<BUCKET_SIZE; ++i){
		if(pbuck->data[i] == NULL_DATA){
			pbuck->data[i] = val;
			break;
		}
	}
}

void insert_elem(HashTable pht, const ElemType val)
{
	int index = hash_maker(val);
	
	if(!is_bucket_full(&pht[index])){
		insert_elem_final(&pht[index], val);
	}
	else{
		bucket_node* pre_tmp = &pht[index];
		bucket_node* tmp = pre_tmp->next;
		
		while(tmp != NULL){
			if(!is_bucket_full(tmp)){
				insert_elem_final(tmp, val);
				return ;
			}
			pre_tmp = tmp;
			tmp = tmp->next;
		}
		
		bucket_node *new_node = (bucket_node *)malloc(sizeof(new_node));
		assert(new_node != NULL);
		
		new_node->data[0] = val;
		new_node->data[1] = new_node->data[2] = NULL_DATA;
		new_node->next = NULL;
		
		pre_tmp->next = new_node;
	}
	return ;
}

void show_htable(HashTable ht)
{
	for(int i=0; i<N; ++i){
		printf("%d: ", i);

		bucket_node *tmp = &ht[i];
		while(tmp != NULL){
			printf("{ ");
			for(int j=0; j<BUCKET_SIZE; j++)
				printf("%2d ", tmp->data[j]);
			tmp = tmp->next;
			printf("} ");
		}
		printf("\n");
	}
}

#endif

下面是测试代码:

#include "HashTable.h"

int main()
{
    ElemType array[] = {0,1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
					15, 16,17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 1, 1, 1,};
	//ElemType array[] = {6, 6, 6, 6};
	HashTable ht;

	init_htable(ht);
	
	int len = sizeof(array) / sizeof(ElemType);
	for(int i=0; i<len; ++i)
		insert_elem(ht, array[i]);

	show_htable(ht);

	return 0;
}

结果如下:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值