#include "stdio.h"
#include "stack.h"
#define maxHeapSize 20 //小根堆中最多允许元素
///---------------堆的类型跟操作的定义-----------------------------------
//小根堆的数据结构类型定义
typedef int DataType;
typedef struct MinNode{
DataType key[maxHeapSize]; //定义一个数据域数组型
int currentSize; //当前元素个数
}MinHeap;
//小根堆自上向下筛选算法
void siftDown(MinHeap *minHeap,int i,int m){
//从结点hight开始到m为止,自上向下比较,如果子女的值小于父结点
//则关键字小的向上浮,继续向下层比较,这样将一个集合局部调整为小
//根堆,主要用于创建
DataType tmp=minHeap->key[i];
int j;
for(j=2*i+1;j<=m;j=j*2+1){
if(minHeap->key[j]>minHeap->key[j+1]&&j<m)//比较hight层的左右孩子
j++; //让j指向小的孩子
if(tmp<=minHeap->key[j]) break;
else{ //若父亲结点大于孩子结点
minHeap->key[i]=minHeap->key[j]; //则该孩子向上移,hight
i=j;} //向下移
}
minHeap->key[i]=tmp;
}
void siftUp(MinHeap *minHeap,int start){
//从start开始到结点0为止,自下向上比较,如果子女的值小于父结点的值则
//相互交换,这样将集合重新调整为小根堆,主要用于插入
DataType tmp=minHeap->key[start];
int j=start;int i=(j-1)/2;
while(j>0){ //沿父结点路径向上直达根
if(tmp>=minHeap->key[i])break;
else{ //若父亲结点大于孩子结点
minHeap->key[j]=minHeap->key[i]; //则父结点下移,
j=i;i=(i-1)/2;} //继续跟上一层的父结点比较
}
minHeap->key[j]=tmp;
}
void CreatHeap(MinHeap *minHeap,DataType key[],int n){
//创建一个小根堆,
int i;int hight; //找最初调整位置,最后分支结点
for(i=0;i<n;i++) minHeap->key[i]=key[i];
minHeap->currentSize=n;
hight=(minHeap->currentSize-2)/2;
while(hight>=0){
siftDown(minHeap,hight,minHeap->currentSize-1);
hight--;
}
}
int InsertHeap(MinHeap *minHeap,DataType data){
//插入元素
if(minHeap->currentSize>=maxHeapSize)
return 0; //堆满不能插入
minHeap->key[minHeap->currentSize]=data;
siftUp(minHeap,minHeap->currentSize);
minHeap->currentSize++;
return 1;
}
int RemoveHeap(MinHeap *minHeap,DataType *data){
//删除堆顶元素
if(minHeap->currentSize==0)
return 0; //堆空不能删除
*data=minHeap->key[0];
minHeap->key[0]=minHeap->key[minHeap->currentSize-1];//用最后一个元素填补堆顶
minHeap->currentSize--;
siftDown(minHeap,0,minHeap->currentSize-1); //从堆顶开始调整
return 1;
}
void InitMinHeap(MinHeap *minHeap){
//初始化即空堆
minHeap->currentSize=0;
}
void InOrderHeap(MinHeap minheap){
//中序非递归遍历小堆
int i;
SqStack s;
InitStack(&s);
i=0;
do
{
while(i<=minheap.currentSize-1){ //若根节点不为空则进栈
PushStack(&s,i); //i指向左孩子直到为空
i=2*i+1;}
if(!IsEmpty(s)){
GetStack(s,&i);
PopStack(&s); //出栈,打印该结点
printf("%5d",minheap.key[i]);
i=2*i+2; //访问右孩子结点
}
}while((i<=minheap.currentSize-1)||!IsEmpty(s)); //若p不为空或栈不为空则继续循环
}
//-----------------------------堆的定义结束-------------------------
/*main(){
MinHeap minheap;int i;int x=11;
int a[8]={53,17,78,9,45,65,87,23};
InitMinHeap(&minheap);
CreatHeap(&minheap,a,8);
printf("\n中序非递归遍历小根堆:\n");
InOrderHeap(minheap);
printf("\n层次遍历小根堆:\n");
for( i=0;i<8;i++)
printf("%5d",minheap.key[i]);
printf("\n%5d\n",minheap.currentSize);
}*/
本文介绍了小根堆的数据结构及其操作,包括创建、插入、删除和调整算法。通过siftDown和siftUp函数实现堆的维护,提供了一个完整的最小堆实现示例。

752

被折叠的 条评论
为什么被折叠?



