1. 程式人生 > 實用技巧 >14.堆排序

14.堆排序

堆排序

從 13 裡面拿出來的,害,後面的陣列就自己編把,別和我重了

程式碼

#include <iostream>
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;
}