堆排序中每次堆调整后的次序

堆排序(heap sort)是对简单选择排序的一种改进,改进的着眼点是:如何减少记录的比较次数。简单选择排序在一趟排序中仅选出最小记录,没有把一趟的比较结果保存下来,因而记录的比较次数较多。堆排序在选出最小记录的同时,也找出较小记录,减少了选择的比较次数,从而提高整个排序的效率。堆排序算法的基本思想如下:
首先将待排序序列构造成一个大根堆,即选出了堆中所有记录的最大者,将它从堆中移走,并将剩余的记录再调整成堆,这样又找出了次小的记录,以此类推,直到堆中只有一个记录。
现在希望算出从小到大堆排序的过程中,每次进行堆调整后(包括构造初始堆),打印输出堆的次序。
在这里插入图片描述
【输入形式】
第一行一个整数N, 第二行有N个整数,无序。0<N <= 100
【输出形式】
输出共 N 行。第i行对应第i次堆调整后N-i+1个整数的次序。
【样例输入】
5
2 3 1 5 4
【样例输出】
5 4 1 3 2
4 3 1 2
3 2 1
2 1
1

分析:
堆排序 利用完全二叉树的性质 构建一个大根堆(小根堆)把最大的(最小的)放到根节点 然后把根节点与最后一个结点交换数值
本质上就是利用重复构建大根堆(小根堆)的方法,找到最大(最小)的值 然后利用和最后一个结点交换的方式进行排序

构建堆的函数

void adjust(int arr[],int n,int i)
{
    int left=i*2+1;//下标为i的左孩子
    int right=i*2+2;//下标为i的右孩子
    int maxi = i;
    if(left<n&&arr[left]>arr[maxi])
        maxi=left;
    if(right<n&&arr[right]>arr[maxi])
        maxi=right;
    if(maxi!=i)//当下标为i 的结点不是它和它孩子节点中最大数时
    {
        swap(arr[maxi],arr[i]);
        adjust(arr,n,maxi);
    }
}

排序输出堆的函数

void heapSort(int arr[],int n)
{
    for(int i=n/2-1;i>=0;i--)//从第一个非叶子结点开始
    {
        adjust(arr,n,i);//初始建堆
    }
    for(int i =0;i<n;i++)
    {
        cout<<arr[i]<<" ";
    }
    cout<<endl;
    for(int i=n-1,j=n-1;i>=1;i--,j--)//经过初始建堆后 还需n-1次建堆
    //每次最大的在树的根节点上
    {
        swap(arr[0],arr[i]);//把根节点和最后一个结点交换
        adjust(arr,i,0);//继续进行排堆 从下标为0的结点开始 对剩下的i个进行堆排序
        for(int i=0;i<j;i++)
        {
            cout<<arr[i]<<" ";//输出堆排序后每次堆调整后的次序
        }
        cout<<endl;
    }
}

主函数

int main()
{
    int n;
    cin>>n;
    int arr[n];
    for(int i=0;i<n;i++)
    {
        cin>>arr[i];
    }
    heapSort(arr,n);
}

在下是一名小白 如果有不恰当的地方 欢迎指正

发布了31 篇原创文章 · 获赞 8 · 访问量 2155

猜你喜欢

转载自blog.csdn.net/weixin_44034024/article/details/105242476