#define LEFT(a) ((a)<<1)
#define RIGHT(a) (((a)<<1)+1)
#define PARENT(a) ((a)>>1)
using std::string;
template <typename T>
struct Heap
{
unsigned int heap_size;//有效数据个数
unsigned int length;//最大容量
T *array;
Heap(unsigned int length):heap_size(0),length(length),array(new T[length+1]){}//这里多申请了一个空间,因为第0个位置不使用
Heap &justAppend(T elem)
{
if(heap_size==length)
throw "too many elem";
array[++heap_size]=elem;
return *this;
}
//用于构建最大堆
void MAX_HEAPIFY(unsigned int i)
{
unsigned int left=LEFT(i);
unsigned int right=RIGHT(i);
unsigned int largest=i;
if(left<=heap_size && array[left]>array[largest])
largest=left;
if(right<=heap_size && array[right]>array[largest])
largest=right;
if(largest!=i)
{
T tmp=array[i];
array[i]=array[largest];
array[largest]=tmp;
MAX_HEAPIFY(largest);
}
}
//用于构建最小堆
void MIN_HEAPIFY(unsigned int i)
{
unsigned int left=LEFT(i);
unsigned int right=RIGHT(i);
unsigned int min=i;
if(left<=heap_size && array[left]<array[min])
min=left;
if(right<=heap_size && array[right]<array[min])
min=right;
if(min!=i)
{
T tmp=array[i];
array[i]=array[min];
array[min]=tmp;
MIN_HEAPIFY(min);
}
}
void MAX_ADD(T elem)
{
//向大根堆中添加一个元素,这里假设数组已经是一个大根堆了
if(heap_size==length)
{
printf("to many elem\n");
return;
}
++heap_size;//先在数组的最后面申请一个位置
unsigned int i;
for(i=heap_size;array[PARENT(i)]<elem;i=PARENT(i))
array[i]=array[PARENT(i)];//依次向上查找父节点,直到找到那个比elem小的父节点,如果没有这样的点,那么最后一个位置就是为elem准备的
array[i]=elem;
return;
}
void MAX_DELETE_ROOT()
{
//删除大根堆的根节点
if(heap_size==0)
{
printf("no elem\n");
return;
}
--heap_size;
if(heap_size==0)
return;//不需要调整堆
array[1]=array[heap_size+1];//将原来的堆中的最后一个elem放到堆的根,保证原来根节点的左右子树还是大根堆
MAX_HEAPIFY(1);//从堆的根开始调整,时间复杂度和堆的高度正相关,堆的高度为log2(n),因此时间复杂度为log2(n)
}
void MIN_DELETE_ROOT()
{
if(heap_size==0)
{
printf("no elem\n");
return;
}
--heap_size;
if(heap_size==0)
return;//不需要调整堆
array[1]=array[heap_size+1];//将原来的堆中的最后一个elem放到堆的根,保证原来根节点的左右子树还是大根堆
MIN_HEAPIFY(1);
}
void MAX_SORT()
{
//在此堆已经是大根堆的基础上排序
while(heap_size!=0)
{
printf("%d ",array[1]);//每次输出大根堆的根
MAX_DELETE_ROOT();//log2(n)的复杂度
}
printf("\n");
//总的时间复杂度为nlog2(n);因为删除了n个点,进行了n次调整,每次调整的时间复杂度是log2(n)
}
void MIN_SORT()
{
//在此堆已经是小根堆的基础上排序
while(heap_size!=0)
{
printf("%d ",array[1]);
MIN_DELETE_ROOT();
}
printf("\n");
}
void MIN_ADD(T elem)
{
//向小根堆中添加一个元素,这里假设此数组已经是一个小根堆了
if(heap_size==length)
{
printf("to many elem\n");
return;
}
++heap_size;//先在数组的最后面申请一个位置
unsigned int i;
for(i=heap_size;array[PARENT(i)]>elem;i=PARENT(i))
array[i]=array[PARENT(i)];//依次向上查找父节点,直到找到那个比elem大的父节点,如果没有这样的点,那么最后一个位置就是为elem准备的
array[i]=elem;
return;
}
void BUILD_MAX_HEAP()
{
//对非叶子节点从最底层向最高层调用MAX_HEAPIFY
//从[heap_size/2+1,heap_size]都是该堆的叶子节点,所以非叶子节点是从[1,heap_size/2]
for(unsigned int i=heap_size/2;i>=1;--i)
MAX_HEAPIFY(i);
}
void BUILD_MIN_HEAP()
{
for(unsigned int i=heap_size/2;i>=1;--i)
MIN_HEAPIFY(i);
}
void print()
{
for(unsigned int i=1;i<=heap_size;++i)
std::cout<<array[i]<<"\t";
std::cout<<std::endl;
}
~Heap()
{
if(!array)
{
delete [] array;
array=0;
}
}
};
int main()
{
Heap<int> heap(100);
heap.justAppend(4).justAppend(1).justAppend(3).justAppend(2).justAppend(16).
justAppend(9).justAppend(10).justAppend(14).justAppend(8).justAppend(7);
heap.print();
heap.BUILD_MAX_HEAP();
heap.MAX_SORT();
heap.justAppend(4).justAppend(1).justAppend(3).justAppend(2).justAppend(16).
justAppend(9).justAppend(10).justAppend(14).justAppend(8).justAppend(7);
heap.BUILD_MIN_HEAP();
heap.MIN_SORT();
return 0;
}