堆
说的堆,我们就知道有两种堆的方式
小堆(大堆)中:任意一个关键码均小于(大于)等于它的左右孩子的关键码,位于堆顶节点的关键码最小(最大),从根节点到每个节点的路径上手族元素组成的序列都是递增(递减)的
堆存储在下标为0开始的数组中,因此在堆中给定下标为i的节点时
如果i=0,节点i是根节点,没有双亲节点;否则节点i的双亲节点为(i-1)/2
如果2*i+1 <= n-1,则节点i的做孩子为节点2*i +1,否则节点i无左孩子
如果2*i +2 <= n-1,则节点i的右孩子为节点2*i +2,否则节点i无右孩子
heap.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#define HEAPMAXSIZE 1000
typedef char heaptype;
typedef int(*Compare)(heaptype a,heaptype b);
typedef struct heap{
heaptype data[HEAPMAXSIZE];
size_t size;
Compare cmp;
}heap;
void heapinit(heap *hp,Compare cmp);
void heapdestroy(heap *hp);
void heapinsert(heap *hp,heaptype value);
void heapcreat(heap *hp,heaptype arr[],size_t size);
int heapgettop(heap *hp,heaptype *root);
void heaperase(heap *hp);
void heapsort(heap *hp,heaptype arr[],size_t size);
堆的初始化与销毁
具体代码实现
void heapinit(heap *hp,Compare cmp)
{
if(hp == NULL)
{
return;
}
hp->cmp = cmp;
hp->size = 0;
return;
}
void heapdestroy(heap *hp)
{
if(hp == NULL)
{
return;
}
hp->cmp = NULL;
hp->size = 0;
return;
}
比较函数
void swap(heaptype *a,heaptype *b)
{
heaptype t = *a;
*a = *b;
*b = t;
}
堆的插入
在已经建成的最小或最大堆后面插入新元素,插入之后,当树中节点不满足堆的性质时,就需要对堆进行重新调整。
我们对这个数组进行尾插,然后我们进行上浮式比较,然后使它满足堆的性质
下面是代码具体实现
void heapinsert(heap *hp,heaptype value)
{
if(hp == NULL)
{
return;
}
if(hp->size >= HEAPMAXSIZE)
{
return;
}
hp->data[hp->size++] = value;
//adjustup(hp,hp->size -1);
size_t child = hp->size-1;
size_t parent = (child-1)/2;
while(child > 0)
{
if(hp->cmp(hp->data[child],hp->data[parent]))
{
swap(&hp->data[child],&hp->data[parent]);
child = parent;//上浮,将交换后的节点继续与它此时的根节点比较交换;
parent = (child-1)/2;
}
else
{
break;
}
}
return;
}
堆的删除
当我们要删除堆顶元素的时候,我们采取这样的思路
1.每次将堆中的最后一个元素代替堆顶元素
2.将堆中元素减少一个,也就是删除最后一个元素,意思就是将堆中有效size减一,但是它的size总体大小是不变的
3.此时堆结构可能被破坏,于是我们需要采用下沉式调整,将堆保持它的性质
void adjustdown(heap *hp)
{
size_t parent = 0;
size_t child = parent*2 +1;
while(child > 0 && child + 1 < hp->size && parent >= 0 && parent < hp->size)
{
if(!hp->cmp(hp->data[child],hp->data[child+1]))
{
child = child+1;
}
if(!hp->cmp(hp->data[parent],hp->data[child]))
{
swap(&hp->data[parent],&hp->data[child]);
parent = child;
child = parent*2 +1;
}
else
{
break;
}
}
return;
}
void heaperase(heap *hp)
{
if(hp == NULL)
{
return;
}
if(hp->size == 0)
{
return;
}
swap(&hp->data[0],&hp->data[hp->size-1]);
hp->size--;
adjustdown(hp);
}
根据一个数组创建一个堆
void heapcreat(heap *hp,heaptype arr[],size_t size)
{
if(hp == NULL || arr == NULL || size == 0)
{
return;
}
size_t i = 0;
for(;i<size;i++)
{
heapinsert(hp,arr[i]);
}
return;
}
取堆顶元素
int heapgettop(heap *hp,heaptype *root)
{
if(hp == NULL)
{
return 0;
}
if(hp->size == 0)
{
return 0;
}
*root = hp->data[0];
return 1;
}
堆的排序
给一个数组,用数组里面的元素创建一个堆,然后我们依次删除堆里面的元素,然后此时堆内这个数组就是排好顺序的数组,将这个数组依次赋值给,参数给的数组,就完成了堆的排序
void heapsort(heap *hp,heaptype arr[],size_t size)
{
if(hp == NULL)
{
return;
}
heapcreat(hp,arr,size);
size_t i = 0;
for(;i < size;i++)
{
heaperase(hp);
}
for(i = 0;i < size;i++)
{
arr[i] = hp->data[i];
}
}
下面是测试代码和测试结果
#define HEADER printf("\n=============%s=============\n",__FUNCTION__)
void testinsert()
{
HEADER;
heap hp;
heapinit(&hp,less);
heapinsert(&hp,'g');
heapinsert(&hp,'f');
heapinsert(&hp,'d');
heapinsert(&hp,'e');
heapinsert(&hp,'a');
heapinsert(&hp,'c');
heapinsert(&hp,'b');
print(&hp);
}
void testcreat()
{
HEADER;
heap hp;
heapinit(&hp,less);
char arr[10] = "abcdefg";
size_t size = strlen(arr);
heapcreat(&hp,arr,size);
print(&hp);
}
void testgettop()
{
HEADER;
heap hp;
heapinit(&hp,less);
heapinsert(&hp,'g');
heapinsert(&hp,'f');
heapinsert(&hp,'d');
heapinsert(&hp,'e');
heapinsert(&hp,'a');
heapinsert(&hp,'c');
heapinsert(&hp,'b');
print(&hp);
heaptype top;
int ret = heapgettop(&hp,&top);
printf("expected ret is 1,actul is %d\n",ret);
printf("expected top is a,actul is %c\n",top);
}
void testerase()
{
HEADER;
heap hp;
heapinit(&hp,less);
heapinsert(&hp,'g');
heapinsert(&hp,'f');
heapinsert(&hp,'d');
heapinsert(&hp,'e');
heapinsert(&hp,'a');
heapinsert(&hp,'c');
heapinsert(&hp,'b');
print(&hp);
heaperase(&hp);
print(&hp);
//heaptype top;
//int ret = heapgettop(&hp,&top);
//printf("expected ret is 1,actul is %d\n",ret);
//printf("expected top is b,actul is %c\n",top);
}
void testsort()
{
HEADER;
heap hp;
heapinit(&hp,less);
char arr[10] = "abcdefg";
size_t size = strlen(arr);
heapsort(&hp,arr,size);
printf("\n");
size_t i = 0;
for(;i < size;i++)
{
printf("%c",arr[i]);
}
printf("\n");
}
int main()
{
testinsert();
testcreat();
testgettop();
testerase();
testsort();
return 0;
}