14.堆排序

堆排序

从 13 里面拿出来的,害,后面的数组就自己编把,别和我重了

代码

#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::ostream;
using std::string;
using std::swap;

struct Element
{
    int key;
    string data;

    // 重载比较运算符, 方便后面直接元素对比
    bool operator<(const Element &rhs) const { return key < rhs.key; }
    bool operator<=(const Element &rhs) const { return key <= rhs.key; }
    bool operator>(const Element &rhs) const { return key > rhs.key; }
    bool operator>=(const Element &rhs) const { return key >= rhs.key; }
};

// 重载 << 用于输出数组类型
template <size_t N>
ostream &operator<<(ostream &os, const Element (&array)[N])
{
    for (const Element &e : array)
        cout << e.data << "(" << e.key << ")  ";
    return os;
}

// 把以 root 为根的子树调整为大根堆(根>=左、右孩子)
// 数组从 1 号位置开始放, root 的左孩子是 2*root, 右孩子是 2*root + 1
// 这里的数组从 0 号位置开始放, root 的左孩子是 2*root+1, 右孩子是 2*root + 2
void adjust_heap(Element array[], int root, int length)
{
    Element old_root = array[root];                       // 暂存 root 节点的值
    for (int i = 2 * root + 1; i < length; i = 2 * i + 1) // i 指向 root 节点的左孩子
    {
        if (i + 1 < length && array[i] < array[i + 1]) // 如果右孩子存在, 且比左孩子大
            i++;                                       // 让 i 指向右孩子

        if (old_root >= array[i])
            break; // 如果原 root 结点的值 >= 左右孩子中的最大者, 不用调整了

        array[root] = array[i]; // 否则, 把它换到 root 结点的位置
        root = i;               // 换过之后, 以 i 为根的子树可能不再是大根堆, 需要继续调整
    }
    array[root] = old_root; // 调整到最后, root 指到了正确位置, 它的父节点比它大, 子节点比它小, 原来的根节点就放到这里
}

// 建立一个大根堆
void build_max_heap(Element array[], int length)
{
    int last_branch_node = length / 2;          // 最后一个分支结点应该是 结点数 / 2, 往后就是叶子结点了
    for (int i = last_branch_node; i >= 0; i--) // 从后往前, 调整所有分支结点
        adjust_heap(array, i, length);
}

// 堆排序
void heap_sort(Element array[], int length)
{
    build_max_heap(array, length); // 把数组转成大根堆

    for (int i = length - 1; i > 0; i--) // 从数组最后一个元素开始往前扫
    {
        swap(array[0], array[i]); // 把大根堆的根节点(最大值)换到后面
        adjust_heap(array, 0, i);
    }
}

int main(int argc, char const *argv[])
{
	Element array[] = {{23, "小红"}, {88, "小米"}, {6, "小黑"}, {54, "小白"}, {76, "小绿"}};
    int length = 5;
    cout << "原始数组: " << array << endl;
	heap_sort(array, length);
	cout << "排序结果: "  << array << endl;
	return 0;
}

posted @ 2020-12-04 15:39  zaxtyson  阅读(108)  评论(0编辑  收藏  举报