堆的概念
最小堆:任一结点的关键码均小于等于它的左右孩子的关键码,位于堆顶结点的关键码最
小
最大堆:任一结点的关键码均大于等于它的左右孩子的关键码,位于堆顶结点的关键码
最大
堆存储在下标为0开始计数的数组中,因此在堆中给定小标为i的结点时:
1、如果i=0,结点i是根节点,没有双亲节点;否则结点i的双亲结点为结点(i-1)/2
2、如果2*i+1>n-1,则结点i无左孩子,否则结点i的左孩子为结点2*i+1
3、如果2*i+2>n-1,则结点i无右孩子,否则结点i的右孩子为结点2*i+2
堆排序的结点表示
typedef struct
{
ElemType *data;
int maxsize;
int cursize;
}Heap;
堆的创建(最小堆)
//从结点(ArraySize-1)/2开始调整,将每一棵子树都调整成一棵最小堆结构
void Make_Heap(Heap *hp)
{
assert(hp != NULL);
int end = hp->cursize -1;
int pos = (end-1)/2;
while(pos >= 0)
{
FilterDown(hp->data,pos,end);
--pos;
}
}
//检测以i为结点的子树是否满足最小堆,若满足不调整,否则,调整。
void FilterDown(ElemType *ar,int start,int end)
{
int i = start; // root;
int j = i*2+1; // leftchild;
ElemType tmp = ar[i];
while(j <= end)
{
if(j < end && ar[j] >= ar[j+1]) j+=1;
if(tmp <= ar[j]) break;
ar[i] = ar[j];
i = j;
j = i*2+1;
}
ar[i] = tmp;
}
堆的单个元素插入
堆的插入每次都在已经建成的而最小堆的后面插入,但插入之后,有可能破坏了对的
结构,这时就需要对堆进行重新调整
void Insert_Heap(Heap *hp,ElemType *ar,int n)
{
assert(hp != NULL && ar != NULL && n>0 );
for(int i = 0;i<n;++i)
{
hp->data[i] = ar[i];
}
hp->cursize = n;
Make_Heap(hp);
}
堆的数组插入
void Insert_Heap(Heap *hp,ElemType *ar,int n)
{
assert(hp != NULL && ar != NULL && n>0 );
for(int i = 0;i<n;++i)
{
hp->data[i] = ar[i];
}
hp->cursize = n;
Make_Heap(hp);
}
堆的取栈顶
ElemType Pop_Heap(Heap *hp)
{
assert(hp != NULL);
int tmp = hp->data[0];
Swap(hp->data[0],hp->data[hp->cursize-1]);
hp->cursize -= 1;
FilterDown(hp->data,0,hp->cursize-1);
return tmp;
}
算法实现和程序代码:
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#include<stdlib.h>
#include"Heap.h"
#define MINHEAP
template<class Type>
void Swap(Type &a,Type &b)
{
Type tmp = a;
a = b;
b = tmp;
}
void FilterDown(ElemType *ar,int start,int end)
{
int i = start; // root;
int j = i*2+1; // leftchild;
ElemType tmp = ar[i];
while(j <= end)
{
if(j < end && ar[j] >= ar[j+1]) j+=1;
if(tmp <= ar[j]) break;
ar[i] = ar[j];
i = j;
j = i*2+1;
}
ar[i] = tmp;
}
void FilerUp(ElemType *ar,int start)
{
int j = start, i = (j-1)/2;
ElemType tmp = ar[j];
while(j > 0)
{
#ifdef MINHEAP
if(ar[i] <= tmp)
#else
if(ar[i] >= tmp)
#endif
break;
ar[j] = ar[i];
j = i;
i = (j-1)/2;
}
ar[j] = tmp;
}
bool Init_Heap(Heap *hp)
{
assert(hp!= NULL);
hp->cursize = 0;
hp->maxsize = HEAPSIZE;
hp->data = (ElemType*)malloc(sizeof(ElemType)*hp->maxsize);
if(hp->data == NULL) exit(1); // return false;
return true;
}
void Destroy_Heap(Heap *hp)
{
assert(hp != NULL);
free(hp->data);
hp->data = NULL;
hp->maxsize = 0;
hp->cursize = 0;
}
void Clear_Heap(Heap *hp)
{
assert(hp != NULL);
hp->cursize = 0;
}
bool Empty_Heap(Heap *hp)
{
assert(hp != NULL);
return hp->cursize == 0;
}
bool Full_Heap(Heap *hp)
{
assert(hp != NULL);
return hp->cursize == hp->maxsize;
}
int Size_Heap(Heap *hp)
{
assert(hp != NULL);
return hp->cursize;
}
// Empty_Heap();
ElemType Pop_Heap(Heap *hp)
{
assert(hp != NULL);
int tmp = hp->data[0];
Swap(hp->data[0],hp->data[hp->cursize-1]);
hp->cursize -= 1;
FilterDown(hp->data,0,hp->cursize-1);
return tmp;
}
void Make_Heap(Heap *hp)
{
assert(hp != NULL);
int end = hp->cursize -1;
int pos = (end-1)/2;
while(pos >= 0)
{
FilterDown(hp->data,pos,end);
--pos;
}
}
void Insert_Heap(Heap *hp,ElemType *ar,int n)
{
assert(hp != NULL && ar != NULL && n>0 );
for(int i = 0;i<n;++i)
{
hp->data[i] = ar[i];
}
hp->cursize = n;
Make_Heap(hp);
}
void Push_Heap(Heap *hp,ElemType x)
{
assert(hp != NULL);
if(Full_Heap(hp))
{
// Inc_Heap(ph);
}
hp->data[hp->cursize] = x;
hp->cursize +=1;
FilerUp(hp->data,hp->cursize - 1);
}