还记得是大二的时候写过堆,没想到今天写的时候一气呵成
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PARENT_INDEX(i) (((i) - (!((i) & 1))) / 2)
#define LSON_INDEX(i) ((i) * 2 + 1)
#define RSON_INDEX(i) ((i) * 2 + 2)
#define SWAP(a, b) do{\
a = a ^ b;\
b = a ^ b;\
a = a ^ b;\
}while(0)
struct heap_t{
int * ptr_buf;
int size; /* 以4字节为单位 */
int capacity; /* 以4字节为单位 */
};
void heap_shift_up(struct heap_t * heap, int index)
{
if(heap->size > heap->capacity || index >= heap->size)
return;
while(index != 0)
{
if(heap->ptr_buf[index] > heap->ptr_buf[PARENT_INDEX(index)])
break;
/* 交换当前节点和父节点的值 */
SWAP(heap->ptr_buf[index], heap->ptr_buf[PARENT_INDEX(index)]);
index = PARENT_INDEX(index);
}
}
void heap_shift_down(struct heap_t * heap, int index)
{
int smaller_son_index;
if(heap->size > heap->capacity || index >= heap->size)
return;
while(LSON_INDEX(index) <= heap->size)
{
/* 找出左儿子和右儿子中较小的一个的索引 */
smaller_son_index = LSON_INDEX(index);
if(heap->ptr_buf[RSON_INDEX(index)] < heap->ptr_buf[LSON_INDEX(index)]
&& RSON_INDEX(index) <= heap->size)
smaller_son_index = RSON_INDEX(index);
/* 如果当前节点小于左右儿子,则成功 */
if(heap->ptr_buf[index] < heap->ptr_buf[smaller_son_index])
break;
/* 交换当前节点和较小的儿子的值 */
SWAP(heap->ptr_buf[smaller_son_index], heap->ptr_buf[index]);
index = smaller_son_index;
}
}
/* 初始化堆 */
void make_heap(struct heap_t * heap)
{
int i = 0;
if(heap->size > heap->capacity)
return;
for(i = heap->size - 1; i >= 0; i--)
heap_shift_down(heap, i);
}
void remove_from_heap(struct heap_t * heap, int index)
{
if(heap->size > heap->capacity || index >= heap->size)
return;
/* 将最后一个元素与需要移除的元素交换 */
SWAP(heap->ptr_buf[index], heap->ptr_buf[heap->size - 1]);
heap->size--;
/* 重新调整堆 */
heap_shift_up(heap, index);
heap_shift_down(heap, index);
}
/* 向堆中添加元素 */
bool add_to_heap(struct heap_t * heap, int val)
{
if(heap->size + 1 > heap->capacity)
return false;
heap->ptr_buf[heap->size] = val;
heap->size++;
heap_shift_up(heap, heap->size - 1);
}
int
main(int c, char **v) {
int i;
struct heap_t heap;
int arr[20] = {1, 20, 2, 30, 30, 4, 4, 100, 100, 100, 100, 5, 5, 6, 6};
heap.size = 15;
heap.capacity = 20;
heap.ptr_buf = arr;
make_heap(&heap);
remove_from_heap(&heap, 4);
add_to_heap(&heap, -1);
for(i = 0; i < heap.size; i++)
printf("%d\n", arr[i]);
printf("size: %d\n", heap.size);
return 0;
}
#ifdef __cplusplus
}
#endif