小根堆的调整

本文介绍了小根堆的数据结构及其操作,包括创建、插入、删除和调整算法。通过siftDown和siftUp函数实现堆的维护,提供了一个完整的最小堆实现示例。
 

#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);
}*/
 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值