HASH表的建立及查找
生成50个在[200, 1000]之间互不相同的整数保存数组A中,以此数组元素作为关键字,设计实现以下操作的程序:
① 建立对应的HASH表并输出所建立的HASH表:HASH函数为h(k)=key% p(p为20以内的某个素数),采用链地址法解决冲突;
② 在所建立的HASH表中查找指定的关键字(输入要查找的整数),给出操作的结论及相应的操作次数;
③ 在所建立的HASH表中删除指定的关键字(输入要删除的整数),给出操作的结论及相应的操作次数;
④ 主函数通过调用函数实现以上操作。
⑴ 所定义的数据结构:
typedef struct MyHash {
int key;
int value;
struct MyHash* next;
}MyHash;
MyHash hash[17];
1
2
3
4
5
6
7
8
⑵ 主要操作算法思想或算法步骤:
#include<stdio.h>
#include<malloc.h>
typedef struct MyHash {
int key;
int value;
struct MyHash* next;
}MyHash;
MyHash hash[17];
//主要操作:
//初始化
void ini(MyHash hash[], int n) {
for (int i = 0; i < n; i++) {
hash[i].key = -1;
hash[i].value = -1;
hash[i].next = NULL;
}
}
//添加。返回1为成功,-1为失败(重复)
int addData(int key, int value) {
int t = key % 17;
if (hash[t].key == -1) {
hash[t].key = key;
hash[t].value = value;
return 1;
}
MyHash* p = (MyHash*)malloc(sizeof(MyHash));
*p = hash[t];
if (p->next == NULL) {
MyHash* h = (MyHash*)malloc(sizeof(MyHash));
h->key = key;
h->value = value;
h->next = NULL;
hash[t].next = h;
return 1;
}
while (p->next != NULL) {
if (p->next->key == key) {
return -1;
}
if (p->next->key ==-1) {
p->next->key = key;
p->next->value = value;
return 1;
}
p = p->next;
}
MyHash* h = malloc(sizeof(MyHash));
h->key = key;
h->value = value;
h->next = NULL;
p->next = h;
return 1;
}
//查找
int search(int key) {
int t = key % 17;
int n = 0;//查找次数
n++;
if (hash[t].key == key) {
printf("查找成功,查找次数为%d次\n", n);
return n;
}
MyHash* p = (MyHash*)malloc(sizeof(MyHash));
*p = hash[t];
n++;
if (p == NULL) {
printf("查找失败,查找次数为%d次\n", n);
return n;
}
while (p != NULL) {
n++;
if (p->key == key) {
printf("查找成功,查找次数为%d次\n", n);
return n;
}
p = p->next;
}
printf("查找失败,查找次数为%d次\n", n);
return n;
}
//删除
int delete(int key) {
int t = key % 17;
int n = 0;//操作次数
n++;
if (hash[t].key == key) {
hash[t].key = -1;
hash[t].value = -1;
n += 2;
printf("删除成功,操作次数为%d次\n", n);
return n;
}
MyHash* p = (MyHash*)malloc(sizeof(MyHash));
*p = hash[t];
n++;
if (p == NULL) {
printf("查找失败,不存在此数,操作次数为%d次\n", n);
return n;
}
while (p != NULL) {
n++;
if (p->key == key) {
hash[t].key = -1;
hash[t].value = -1;
n += 2;
printf("删除成功,操作次数为%d次\n", n);
return n;
}
p = p->next;
n++;
}
printf("查找失败,不存在此数,操作次数为%d次\n", n);
return n;
}
//步骤与测试
main() {
ini(&hash, 17);
int count = 50;
int i;
while (count > 0) {
i = rand();
if (i > 199 && i < 1001) {
if (addData(i, 0) > 0) {
count--;
}
}
}
printf("查找500(500为自定义的数)\n");
search(500);
printf("\n");
printf("查找%d(%d为生成的随机数)\n", i,i);
search(i);
printf("\n");
printf("删除%d\n", i);
delete(i);
}
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
排序
① 生成100个在[200, 1000]之间的整数保存数组A中,以此数组元素作为关键字,采用希尔排序算法按非递减方式进行排序,给出操作的结果及相应的操作次数;
③ 生成200个在[200, 10000]之间的整数保存数组A中,以此数组元素作为关键字,采用快速排序算法按非递减方式进行排序,给出操作的结果及相应的操作次数;
④ 生成500个在[200, 10000]之间的整数保存数组A中,以此数组元素作为关键字,采用堆排序算法按非递减方式进行排序,给出操作的结果及相应的操作次数;
⑤ 主函数通过调用函数实现以上操作。
⑴ 所定义的数据结构:
int A[100];
int count = 0;//计数器
1
2
⑵ 主要操作算法思想或算法步骤:
//主要操作:
//希尔排序
int shell_sort(int array[], int length) {
int i;
int j;
int k;
int step; //分组的步长
int temp; //哨兵
int count = 0;//计算操作数
for (step = length / 2; step > 0; step = step / 2) {
for (i = 0; i < step; i++, count++) {
for (j = i + step; j < length; j = j + step) { //单独一次的插入排序
if (array[j] < array[j - step]) {
temp = array[j]; //哨兵
k = j - step;
while (k >= 0 && array[k] > temp) {
array[k + step] = array[k];
k = k - step;
count += 4;
}
array[k + step] = temp;
count += 5;
}
}
}
}
return count;
}
//快速排序
int quickSort(int* arr, int low, int high) {
int c = 0;
c++;
if (low < high) {
int i = low;
int j = high;
int k = arr[low];
while (i < j) {
c+=5;
while (i < j && arr[j] >= k) { // 从右向左找第一个小于k的数
j--; c++;
}
if (i < j) {
arr[i++] = arr[j];
}
while (i < j && arr[i] < k) { // 从左向右找第一个大于等于k的数
i++; c++;
}
if (i < j) {
arr[j--] = arr[i];
}
}
arr[i] = k;
c += 6;
// 递归调用
c+=quickSort(arr, low, i - 1); // 排序k左边
c+=quickSort(arr, i + 1, high); // 排序k右边
}
return c;
}
//堆排序
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int percDown(int A[], int i, int N) {
int child;
int temp;
int c=0;
c+=2;
for (temp = A[i]; 2 * i + 1 < N; i = child) {
c+=2;
child = 2 * i + 1; //数组下标是从0开始的
c++;
c++;
if (child != N - 1 && A[child + 1] > A[child]) {
++child; //找到最大的儿子节点
c++;
}
c++;
if (temp < A[child]) {
A[i] = A[child];
c++;
}
else
break;
}
A[i] = temp;
c++;
return c;
}
int heapSort(int A[], int N) {
int i;
int c=0;//操作次数
c+=2;
for (i = N / 2; i >= 0; --i) {
c += 2;
c+=percDown(A, i, N); //构造堆
}
for (i = N - 1; i > 0; --i) {
c += 2;
swap(&A[0], &A[i]); //将最大元素(根)与数组末尾元素交换,从而删除最大元素,重新构造堆
c += 3;
c+=percDown(A, 0, i);
}
return c;
}
//测试函数
main() {
int A[100];
int count = 0;//计数器
while (count<100) {
int num = rand();
if (num >= 200 && num <= 1000) {
A[count] = num;
count++;
}
}
printf("未排序:\n");
for (int i = 0; i < 100; i++)
printf("%d ", A[i], i);
printf("\n\n");
int c=0;//操作次数
//c=shell_sort(A, 100);//希尔排序
//c=quickSort(A, 0, 99);//快速排序
c=heapSort(A, 100);//堆排序
printf("排序后:\n");
for (int i = 0; i < 100; i++)
printf("%d ", A[i]);
printf("\n\n操作次数:%d\n", c);
}