1.首先,在这个测试中我使用的是用数组表示一个堆,并且每个堆的起始点是从数组下标为1的开始
大顶堆
#include <iostream> #include <algorithm> using namespace std; int b[100]; int c[100]; void shiftUp(int a[],int k) //将n个元素逐个插入到一个空堆中,时间复杂度 nlgN { b[k+1]=a[k]; k=k+1;//这里的b数组开始是从1开的是,能够正好对应左孩子是根节点的2倍,右孩子是根节点的2*k+1 while(k>1&&b[k]>b[k/2]){ swap(b[k],b[k/2]); k=k/2; } } void shiftDown(int k,int sum) { b[k]=b[sum];//这种 方法是不断的把叶子的值放到根节点上 sum--; while(2*k<=sum) //先判断是不是有孩子,有左孩子肯定说明不是独苗 { int j=2*k; // if(j+1<=sum&&b[j]<b[j+1]) j=j+1; //判断是不是有右孩子,判断哪个孩子的数值大,和那个交换 if(b[k]>b[j]) break; //如果父节点的值大,那么结束 swap(b[k],b[j]); k=j; } } void shiftDownArray(int k,int sum) //从非叶子节点开始时间复杂度是 O(n) { while(2*k<=sum) //先判断是不是有孩子,有左孩子肯定说明不是独苗 { int j=2*k; // if(j+1<=sum&&c[j]<c[j+1]) j=j+1; //判断是不是有右孩子,判断哪个孩子的数值大,和那个交换 if(c[k]>c[j]) break; //如果父节点的值大,那么结束 swap(c[k],c[j]); k=j; } } int main() { int a[]={2,3,1,5,8};//测试用例的一个简单数组 for(int i=0;i<5;i++) { shiftUp(a,i); //这里逐个的向堆中插入元素,进行选择最大的值 cout<<a[i]<<" "; } cout<<b[1]<<endl; for(int i=0;i<5;i++) { cout<<b[i+1]<<" ";//输出结果测试 } cout<<endl; int sum=5; while(sum>0){ cout<<b[1]<<"->"<<endl; shiftDown(1,sum);//这里是不断的取出堆的最大值,然后进行重新构建堆 sum--; } int m=5/2; //构建的堆的第一个非叶子节点的, for(int i=0;i<5;i++) { c[i+1]=a[i]; } //从下往上第一个非叶子节点(包括根节点),进行shiftDown操作 for(int i=m;i>=1;i--){ shiftDownArray(i,5);//检查节点是否比子节点大,如果不大,那么进行调试,转换 } cout<<c[1]<<endl; for(int i=1;i<6;i++) { cout<<c[i]<<" "; } }
2.一个数组表示堆,数组从下标0开始,顺便进行一次从小到大的排序
那么左孩子就是 2*i+1
右孩子就是 2*i+2
#include <iostream> #include <algorithm> using namespace std; void shiftDownArray(int a[],int k,int sum) //从非叶子节点开始时间复杂度是 O(n) { while(2*k+1<sum) //先判断是不是有孩子,有左孩子肯定说明不是独苗 { int j=2*k+1; // if(j+1<sum&&a[j]<a[j+1]) j=j+1; //判断是不是有右孩子,判断哪个孩子的数值大,和那个交换 if(a[k]>a[j]) break; //如果父节点的值大,那么结束 swap(a[k],a[j]); k=j; } } int main() { int a[]={2,3,1,5,8}; int n=5; for(int i=(n-1)/2;i>=0;i--) { shiftDownArray(a,i,n);//先构建一个大顶堆,这个是用第一个非叶子节点构建 } for(int i=0;i<n;i++){ cout<<a[i]<<" "; } cout<<endl; for(int i=n-1;i>0;i--){ //然后堆顶放到数组最后面 swap(a[0],a[i]); for(int j=0;j<n;j++){ cout<<a[j]<<" ###"; } cout<<endl; shiftDownArray(a,0,i); //再一次的进行重新构建大顶堆,但是数组的长度减1,这个是之间用最后一个顶替堆顶,从新构建堆 for(int j=0;j<n;j++){ cout<<a[j]<<" ***"; } cout<<endl; } }