散列表的拉链法解决冲突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;
}

下面为简单的测试结果
散列表的拉链法解决冲突c语言实现_第1张图片
“个数”指的是链表中同义词的个数;里面的最后释放内存的部分可能存在一些小问题。

优化

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

  1. array+数组【每次插入新值后进行排序】
  2. array+二叉搜索树
  3. array+二叉平衡树
  4. array+红黑树
  5. array+skiplist(skiplist的插入、删除和查找性能可以媲美红黑树,而且相对来说实现也简单)
    其中第四种在java的JDK的TreeSet中有所使用,java的hashmap使用的array+链表array+红黑树两种方案的组合,数据少时使用链表,数据多时使用红黑树。后续会更新上述五种方案的代码。

你可能感兴趣的:(数据结构,c++,数据结构,链表)