散列表的拉链法解决冲突c语言实现

#define N 12
//首先定义相关的结构体
typedef struct HNode {
	int key;
	struct HNode *next;
}Hnode;
/*
	创建哈希表
		heahLink哈希表,里面存储的为指针变量
		key关键字列表
		n关键字数目
*/
void createHB(Hnode *heahLink[], int key[], int n) {
	for (int i = 0; i < n; i++) {
		Hnode *head = (Hnode *)malloc(sizeof(Hnode));
		if (!head) {
			printf("error\n");
			return;
		}
		head->key = 0;
		head->next = NULL;
		heahLink[i] = head;
	}
	//插入操作
	for (int i = 0; i < n; i++) {
		Hnode *p, *H,*s;
		int j = key[i] % 11;
		H = p = heahLink[j];
		while (p->next != NULL) {
			p = p->next;
		}
		s = (Hnode *)malloc(sizeof(Hnode));
		s->key = key[i];
		s->next = NULL;
		p->next = s;
		H->key++;
	}
}
/**
	删除某个关键字
		heahLink为哈希表
		key为要删除的关键字
*/
void deleteNode(Hnode *heahLink[], int key) {
	Hnode *h, *p,*q;
	h = q = heahLink[key % 11];
	p = q->next;
	while (p->next != NULL && p->key !=key) {
		q = p;
		p = p->next;
	}
	if (!p->next) {
		printf("the key does't exist!!\n");
	}
	else {
		q->next = p->next;
		h->key--;
		free(p);
	}
}

/*
	释放内存空间
*/
void FreeNode(Hnode *heahLink[],int n) {
	Hnode *h, *p;
	for (int i = 0; i < n; i++) {
		h = p = heahLink[i];
		while (p->next != NULL) {
			p = p->next;
			free(h);
			h = p;
		}
		free(h);
	}
}
void print(Hnode *heahLink[],int n) {
	Hnode *p;
	printf("下标 个数\n");//%-d左对齐 %d右对齐
	for (int i = 0; i < n; i++) {
		p = heahLink[i];
		printf("  %-2d  ", i);//%-d左对齐 %d右对齐
		while (p->next != NULL) {
			printf("%-2d  ", p->key);
			p = p->next;
		}
		printf("%-2d \n", p->key);
	}
}
//测试程序
int main() {
	int key[] = { 13,28,72,5,16,8,7,9,34,24,18,25 };
	Hnode *heahLink[N];
	createHB(heahLink, key, N);
	printf("..before deleting..\n");
	print(heahLink, N);
	deleteNode(heahLink, key[1]);//删除key[1],即28
	printf("..after deleting..\n");
	print(heahLink, N);
	FreeNode(heahLink, N);
	getchar();
	return 0;
}

下面为简单的测试结果
在这里插入图片描述
“个数”指的是链表中同义词的个数;里面的最后释放内存的部分可能存在一些小问题。

优化

上面的写法采用的是array+链表的形式来实现的,在进行查找过程中,链表的查找效率是整个hash的瓶颈,所以优化的话,需要从替换链表存储数据值的地方进行(因为array允许随机访问),所以待实现的优化方案有以下可选:

  1. array+数组【每次插入新值后进行排序】
  2. array+二叉搜索树
  3. array+二叉平衡树
  4. array+红黑树
  5. array+skiplist(skiplist的插入、删除和查找性能可以媲美红黑树,而且相对来说实现也简单)
    其中第四种在java的JDK的TreeSet中有所使用,java的hashmap使用的array+链表array+红黑树两种方案的组合,数据少时使用链表,数据多时使用红黑树。后续会更新上述五种方案的代码。
  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用线性探测处理冲突散列表的 C 代码示例: ```c #include <stdio.h> #include <stdlib.h> #define SIZE 10 struct node { int key; int value; }; struct hash_table { struct node *data[SIZE]; }; int hash_function(int key) { return key % SIZE; } int rehash(int old_hash) { return (old_hash + 1) % SIZE; } void put(struct hash_table *table, int key, int value) { int hash_value = hash_function(key); struct node *node = (struct node *) malloc(sizeof(struct node)); node->key = key; node->value = value; while (table->data[hash_value] != NULL && table->data[hash_value]->key != key) { hash_value = rehash(hash_value); } table->data[hash_value] = node; } int get(struct hash_table *table, int key) { int start_hash = hash_function(key); int hash_value = start_hash; int value = -1; while (table->data[hash_value] != NULL) { if (table->data[hash_value]->key == key) { value = table->data[hash_value]->value; break; } hash_value = rehash(hash_value); if (hash_value == start_hash) { break; } } return value; } int main() { struct hash_table table; for (int i = 0; i < SIZE; i++) { table.data[i] = NULL; } put(&table, 1, 10); put(&table, 2, 20); put(&table, 3, 30); printf("%d\n", get(&table, 1)); printf("%d\n", get(&table, 2)); printf("%d\n", get(&table, 3)); printf("%d\n", get(&table, 4)); return 0; } ``` 这个散列表使用取余计算哈希值,并且使用线性探测解决冲突。在 `put` 函数,如果发生冲突,就不断向后查找下一个空位置,直到找到一个空位置或者查找完整个散列表。在 `get` 函数,先计算出哈希值,然后依次向后查找,直到找到目标元素或者查找完整个散列表。注意,我们在每次 `put` 操作时都需要动态分配一个新的节点,以便保存键值对信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值