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;
}
}