#include using namespace std;//实现将元素x插入现有堆a[]//将元素x暂时放在a[length]位置,然后调用siftup,完成排序.关键问题在于数组a大小的变化是否需要重新建立数组b,还是用其他方法.//从现有堆a[]删除第i个元素//相当于将第i个元素值置为-1,调用siftdown,到最底层,然后删除.是这样吗?不是,会出现底层左边空出一个元素,不行,该方法舍弃//重新思考,由于最终要将第i个元素放置在第n个位置上删除,所以可以将a[n-1]与a[i-1]交换,然后跟上下节点比较,决定是否siftup还是siftdown//从现有堆a[]删除最大元素并返回max//同上,只是将删除第i个元素固定为删除第1个元素,然后返回第一个元素值//预处理template int Getlength(T &array){ return (sizeof(array)/sizeof(array[0]));}void Siftup1(int *a,int i){ if (i==1)return ; int j=i/2; while(a[j-1] < a[i-1]&&i > 1) { //交换 int temp=a[j-1]; a[j-1]=a[i-1]; a[i-1]=temp; i=j; j=i/2; }}void Siftdown1(int *a,int length,int i){ if (2*i > length)return; bool done=false; int j=2*i; do{ if (j+1<=length && a[j-1] a[i-1]) { int temp=a[j-1]; a[j-1]=a[i-1]; a[i-1]=temp; i=j; j=2*i; }else done=true; }while(j <= length && !done);}//堆的插入void insert(int *a ,int length,int x){//a表示数组首字母的指针,length表示数组的长度,x表示要插入的元素 *(a+length)=x;//不安全,改写后面的数字,可能会导致程序错误 Siftup1(a,length+1);}//删除堆的第i个元素void delete1(int *a,int length,int i){//a表示数组首字母的指针,length表示数组的长度,i表示要删除的元素位置 if (i==length)return ;//如果要删除的元素就是a[n-1],则直接删除,不用操作 //交换元素a[i-1]和a[n-1],由于最后一位不需要,所以可以直接赋值给a[i-1] a[i-1]=a[length-1]; //与上下节点比较,可以直接与上节点比较,若大于父节点,则siftup,否则siftdown. //等于情况下,即没有移动位置,也可以用siftup,siftdown,因为两函数都包含等于情况的处理 if (i==1||a[i-1] <= a[i/2-1])Siftdown1(a,length,i); else Siftup1(a,i); /*if (a[i-1] >= a[i/2-1])Siftup1(a,i);//a[i/2-1]表示父节点,出现问题,在于未判断是否存在父子节点 else Siftdown1(a,length,i);*/}//删除堆的最大值int deletemax(int *a,int length){//a表示数组首字母的指针,length表示数组的长度,返回的值是max int max=a[0]; delete1(a,length,1); return max;}int main(int argc, char const *argv[]){ int a[]={20,13,18,10,11,17,16,3,7,5,6,16}; int *p=a; int length=Getlength(a); delete1(a,length,4); //cout< <