在这里我将会介绍堆的几个基本操作
1.堆的初始化
void HeapInit(Heap *heap,Compare cmp);
在这里我们可以简单粗暴一点,直接将有效值size设置为零,此外我还加了一个排序规则,Compare cmp用来控制大/小堆
2.堆的插入
void HeapInsert(Heap*heap,HeapType value);
在这里我们需要引入一个思路叫上浮式调整,因为堆可以看作一棵完全二叉树,所以我们将新插入的元素放置在最后一个叶子结点上,这样每次将叶子结点与其对应的父节点相比较,拿小堆距离,如果叶子结点比父节点小,那么交换两个结点的值,这样不停的比较交换,就像是气球一点点上浮一样。
3.查找根结点
int HeapRoot(Heap*heap,HeapType*value);
这个问题很简单,查找根结点我们只需要找到数组中第一个元素返回即可,这里我用int 为0还是1来判断返回是否成功,用HeapType*value将元素的地址获取出来
4.判断堆中元素是否为0
int HeapEmpty(Heap*heap);
这个我们可以直接用 return heap->size=0? 1:0;来做判断并返回值
void HeapErase(Heap*heap);删除堆顶元素
在这里我们就要引入另一种思路,叫下沉式调整,首先我们将堆顶元素与最后一个叶子结点中的元素进行交换,此时我们的删除就变成了删除最末尾元素,我们只需要将有效值size-1即可,但此时我们发现我们的堆不再满足堆的关系(大堆/小堆关系),这时候我们就需要进行堆的调整,我们采用下沉式调整。以小堆为例,我们将从根结点开始,先将它的两个子结点进行比较,选出其中较小的一个在与父节点进行比较。如父节点比子结点大,那么将父子结点进行交换,父节点比他小,则不变,这样以此类推,就像是石头在水中下沉一样
5.堆的销毁
void HeapDestroy(Heap*heap);
我们直接将堆的有效值size赋值为零即可完成
下面我们上代码:
1 #include"heap.h"
2 #include<stdio.h>
3 int Greater(HeapType a,HeapType b)
4 {
5 return a>b? 1:0;
6 }
7 int Less(HeapType a,HeapType b)
8 {
9 return a<b? 1:0;
10 }
11 void HeapInit(Heap*heap,Compare cmp)
12 {
13 if(heap==NULL)
14 {
15 return;
16 }
17 heap->size=0;
18 heap->cmp=cmp;
19 return;
20 }
21 void Swap(HeapType*a,HeapType*b)
22 {
23 HeapType tmp=*a;
24 *a=*b;
25 *b=tmp;
26 return;
27 }
28 void AdjustUp(HeapType data[],size_t size,Compare cmp,size_t index)
29 {
30 if(index>=size)
31 {
32 return;
33 }
34 size_t child=index;
35 size_t parent=(child-1)/2;
36 while(child>0)
37 {
38 if(cmp(data[child],data[parent]))
39 {
40 Swap(&data[child],&data[parent]);
41 }
42 else
43 {
44 break;
45 }
46 child=parent;
47 parent=(child-1)/2;
48 }
49 return;
50 }
51 void HeapInsert(Heap*heap,HeapType value)
52 {
53 if(heap==NULL)
54 {
55 return;
56 }
57 if(heap->size>=MAXSIZE)
58 {
59 return;
60 }
61 heap->data[heap->size++]=value;
62 AdjustUp(heap->data,heap->size,heap->cmp,heap->size-1);
63 }
64 void AdjustDown(HeapType data[],size_t size,Compare cmp,size_t index)
65 {
66 if(index>size)
67 {
68 return;
69 }
70 size_t parent=index;
71 size_t child=parent*2+1;
72 while(child<size)
73 {
74 if(child+1<size)
75 if(cmp(data[child+1],data[child]))
76 {
77 child=child+1;
78 }
79 if(cmp(data[child],data[parent]))
80 {
81 Swap(&data[child],&data[parent]);
82 }
83 else
84 {
85 break;
86 }
87 parent=child;
88 child=parent*2+1;
89 }
90 }
91
92 void HeapErase(Heap*heap)
93 {
94 if(heap==NULL)
95 {
96 return;
97 }
98 if(heap->size==0)
99 {
100 return;
101 }
102 Swap(&heap->data[0],&heap->data[heap->size-1]);
103 --heap->size;
104 AdjustDown(heap->data,heap->size,heap->cmp,0);
105 }
106 int HeapEmpty(Heap*heap)
107 {
108 if(heap==NULL)
109 {
110 return;
111 }
112 return heap->size=0? 1:0;
113 }
114 int HeapRoot(Heap*heap,HeapType* value)
115 {
116 if(heap==NULL)
117 {
118 return;
119 }
120 if(heap->size==0)
121 {
122 return;
123 }
124 *value=heap->data[0];
125 return 1;
126 }
127 void HeapDestroy(Heap*heap)
128 {
129 if(heap==NULL)
130 {
131 return;
132 }
133 heap->size=0;
134 return;
135 }
136 void HeapSort(HeapType array[],size_t size)
137 {
138 Heap heap;
139 HeapInit(&heap,Less);
140 size_t i=0;
141 for(i=0;i<size;i++)
142 {
143 HeapInsert(&heap,array[i]);
144 }
145 size_t output_index=0;
146 while(!HeapEmpty(&heap))
147 {
148 HeapType root=0;
149 HeapRoot(&heap,&root);
150 array[output_index++]=root;
151 HeapErase(&heap);
152 }
153 return;
154 }
以下为测试代码
157 void HeapPrintchar(Heap*heap,const char *msg)
158 {
159 printf("%s\n",msg);
160 size_t i=0;
161 for(i=0;i<heap->size;i++)
162 {
163 printf("[%lu]:%d ",i,heap->data[i]);
164 }
165 printf("\n");
166 }
167 void TestHeapInit()
168 {
169 Heap heap;
170 HeapInit(&heap,Less);
171 printf("size expected is 0 ,actual is %lu\n",heap.size);
172 printf("Compare expected is %p,actual is %p",Greater,heap.cmp);
173 }
174 void TestHeapInsert()
175 {
176 Heap heap;
177 HeapInit(&heap,Greater);
178 HeapInsert(&heap,10);
179 HeapInsert(&heap,8);
180 HeapInsert(&heap,9);
181 HeapInsert(&heap,1);
182 HeapInsert(&heap,12);
183 HeapPrintchar(&heap,"cha ru 6 ge yuan su");
184 }
185 void TestHeapErase()
186 {
187 Heap heap;
188 HeapInit(&heap,Greater);
189 HeapInsert(&heap,10);
190 HeapInsert(&heap,8);
191 HeapInsert(&heap,9);
192 HeapInsert(&heap,1);
193 HeapInsert(&heap,12);
194 HeapErase(&heap);
195 HeapPrintchar(&heap,"shan chu tou jie dian");
196 }
197 void TestHeapSort()
198 {
199 HeapType array[]={2,8,7,9,5,4,1};
200 HeapSort(array,sizeof(array)/sizeof(array[0]));
201 size_t i=0;
202 for(i=0;i<(sizeof(array)/sizeof(array[0]));i++)
203 {
204 printf("%d",array[i]);
205 }
206 printf("\n");
207 }
208 int main()
209 {
210 TestHeapInit();
211 printf("\n");
212 TestHeapInsert();
213 printf("\n");
214 TestHeapErase();
215 printf("\n");
216 TestHeapSort();
217 return 0;
218 }