学习笔记(一) 排序算法--堆排序

- 前言

    虽然挺简单的,但还是决定记录一下,方便自己以后复习吧...

- 思路

1.待排序n个元素,看成一个完全二叉树,从倒数第一个具有子树的节点(n/2-1)开始,从右到左从下到上,保证每个子树的父节点都比左右子树的值大,一路交换上去最后保证根节点是最大值,将根节点与最后一个元素n交换;这样就得到了最后一个元素为该数组的最大值;
2.除去最后一个元素,将(n-1)个元素重复上述操作,直到元素个数为1个

结合图片理解:

a、假设无序序列如下图所示。
这里写图片描述
b、从倒数第一个有子树的节点开始(n/2-1)=1,即节点6,比较[6,5,9],9与6交换。
这里写图片描述
c、下一个节点4,比较[4,9,8],9与4交换
这里写图片描述
这样第一次堆调整就完成了,得到的根节点一定是该序列的最大值,将根节点与最后一个节点调换,那么就把最大值放到了数列最后面,再对前面0到n-1的数列进行上述的堆调整,即(下标0到3),直到待调整元素剩下一个时就完成了从小到大的排序
这里写图片描述

-代码实现

void adjustHeap(int arr[], int i, int len)
{
    int temp = arr[i];          //先记录当前父节点
    int k = 2 * i + 1;          //待交换位置为左子节点
    if (k + 1 < len)            //如果有右子节点
    {
        if (arr[k] < arr[k + 1])//如果右子节点大于左子节点
        {
            k++;                //待交换位置变为右子节点
        }
    }
    if (arr[k] > arr[i])        //如果子节点比父节点大,交换 
    {
        arr[i] = arr[k];
        arr[k] = temp;
    }
}

void heapsort(int arr[], int len)
{
    for (int j_len = len; j_len > 0; j_len--)//进行堆调整的元素长度
    {
        for (int i = j_len / 2 - 1; i >= 0; i--)//从倒数第一个有孩子的节点开始
        {
            adjustHeap(arr, i, j_len);
        }
        //完成调整,将根节点(最大值)与参加调整的最后一个元素进行交换
        int temp = arr[0];
        arr[0] = arr[j_len - 1];
        arr[j_len - 1] = temp;
    }

}

//测试代码
int main()
{
    int arr[] = {2,6,7,1,9};
    heapsort(arr,5);
    for(int i = 0;i<5;i++)
        cout<<arr[i]<<" ";
    return 0;
}

输出结果为:1 2 6 7 9
平均时间复杂度为nlog(n)

猜你喜欢

转载自blog.csdn.net/weixin_41212181/article/details/81335629