堆排序

堆排序的基本思想:如果把待排序的数据元素集合构成一个完全二叉树结构,则每次选择出一个最大(或最小)的数据元素只需比较完全二叉树的数值为高度的次数,即log2n次,时间复杂度就是O(nlog2n)

堆的两个性质
(1)最大堆的根节点是堆中值最大的数据元素,最小堆的根节点是堆中值最小的数据元素,称堆的根节点元素为堆顶元素。
(2)对于最大堆,从根节点到每个叶节点的路径上,数据元素组成的序列都是递减有序的;对于最小堆,从根节点到每个叶结点的路径上,数据元素组成的序列都是递增有序的。

实例
假设要排序一个数组
一:将数组看成完全二叉树,将其最大堆化(也可以最小堆)

二:堆排序算法基本思想
(1)把堆顶a[0]元素(最大元素)与最后一个元素交换
(2)最大堆元素个数少一
(3)若此时根节点不满足最大根定义,则调整根节点使他满足最大堆的定义

个人领悟
实现过程中最最重要的思路就是要把数组当成是一个二叉树来处理

自己代码
实现如下(个人代码实现还有一些漏洞,比如说,我是用-1表示的结点无效,但是堆排序的思想都实现了)

#include <iostream>
using namespace std;

void heapTrans(int a[], int size, int length)//传变成最大根堆
{
    int tmp;
    for (int i = size; i >= 0; --i)
    {//3 2 1 0
        int left = -1;
        int right = -1;
        if (2 * i + 1 < length)
        {
            left = a[2 * i + 1];
        }
        if (2 * i + 2 < length)
        {
            right = a[2 * i + 2];
        }

        if (right == -1 && left == -1)
        {
            continue;
        }
        else if (right == -1 && left != -1)
        {
            if (a[i] < left)
            {
                tmp = a[i];
                a[i] = a[2 * i + 1];
                a[2 * i + 1] = tmp;
            }
            continue;
        }
        else if(right != -1 && left == -1)
        {
            tmp = a[i];
            a[i] = a[2 * i + 2];
            a[2 * i + 2] = tmp;
            continue;
        }



        if (left > right)
        {
            if (a[i] < left)
            {
                tmp = a[i];
                a[i] = a[2 * i + 1];
                a[2 * i + 1] = tmp;
            }
        }
        else
        {
            if (a[i] < right)
            {
                tmp = a[i];
                a[i] = a[2 * i + 2];
                a[2 * i + 2] = tmp;
            }
        }

    }
}

void heapSort(int a[],int size, int length)//堆排序
{
    int tmp;
    tmp = a[0];
    a[0] = a[length - 1];
    a[length - 1] = tmp;
    length--;
    if (length == 0)
    {
        return;
    }
    heapTrans(a, (length - 1) / 2, length);
    heapSort(a, (length - 1) / 2, length);
}

int main()
{
    int size = 8;

    int a[8] = { 10,50,32,5,76,9,40,88 };
    for (int i = 0; i < 8; ++i)
    {
        cout << a[i] << " ";
    }
    cout << endl;
    heapTrans(a, 3, 8);
    for (int i = 0; i < 8; ++i)
    {
        cout << a[i] << " ";
    }
    cout << endl;

    heapSort(a, 3, 8);
    for (int i = 0; i < 8; ++i)
    {
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}

书上代码

#include <iostream>
using namespace std;

void CreatHeap(int a[], int n, int h)
{
    int i;
    int j;
    int flag;
    int temp;

    i = h;
    j = 2 * i + 1;//i为要创建的二叉树根结点下标
    temp = a[i];//j为i的左孩子结点的下标
    flag = 0;

    //沿左右孩子中值较大者重复向下筛选
    while (j < n&&flag != 1)
    {
        if (j < n - 1 && a[j] < a[j + 1])
        {
            j++;
        }

        if (temp > a[j])
        {
            flag = 1;//标记结束
        }
        else
        {
            a[i] = a[j];
            i = j;
            j = 2 * i + 1;
        }
    }
    a[i] = temp;
}

void InitCreatHeap(int a[], int n)
{
    int i;
    for (i = (n - 1) / 2; i >= 0; i--)
    {
        CreatHeap(a, n, i);
    }
}

void HeapSort(int a[], int n)
{
    int i;
    int temp;
    InitCreatHeap(a, n);
    for (i = n - 1; i > 0; --i)
    {
        temp = a[0];
        a[0] = a[i];
        a[i] = temp;

        CreatHeap(a, i, 0);
    }

}

int main()
{
    int size = 8;

    int a[8] = { 10,50,32,5,76,9,40,88 };
    HeapSort(a, 8);
    for (int i = 0; i < 8; ++i)
    {
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}

代码分析:
书上将实现了三个函数:
(1)化最大根堆
(2)初始化最大根堆
(3)进行堆排序

我的代码:
(1)化最大根堆
(2)排序
很明显的发现书上代码更加简洁,更加容易理解,比较的原因是要去学习书上规范代码的编写思路,让自己能以一个更加清晰的角度去看待问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值