C++ 实现最大堆排序与最大优先队列

我一向赞同一个理念: 用代码实现简单逻辑是不需要注释的, 因此我也就不写注释了, 直接上代码:

#include <iostream>
#include <deque>
#include <limits>

inline int Parent (const int i)
{
    return std::move( i % 2
        ? (i - 1) / 2
        : (i - 2) / 2);
}

inline int Left (const int i)
{
    return std::move(2 * i + 1);
}

inline int Right (const int i)
{
    return std::move(2 * i + 2);
}

void MaxHeapify (std::deque<int> &ideq, int node)
{
    int largest = node;
    int limit = ideq.size ();

    auto SmallerThan = [&] (int child){ return (child < limit) && (ideq[largest] < ideq[child]); };

    int leftNode = Left (node);
    if (SmallerThan (leftNode)) {
        largest = leftNode;
    }

    int rightNode = Right (node);
    if (SmallerThan (rightNode)) {
        largest = rightNode;
    }

    if (largest != node) {
        std::swap (ideq[largest], ideq[node]);
        MaxHeapify (ideq, largest);
    }
}

std::deque<int>  BuildMaxHeap (std::deque<int> &ideq)
{
    std::deque<int> heap (ideq);
    for (int i = ideq.size () / 2 - 1; i > -1; --i) {
        MaxHeapify (heap, i);
    }
    return std::move (heap);
}

void HeapSort (std::deque<int> &ideq)
{
    auto heap = BuildMaxHeap (std::move(ideq));
    for (int i = ideq.size () - 1; i > -1; --i) {
        ideq[i] = std::move (heap[0]);
        heap.pop_front ();
        MaxHeapify (heap, 0);
    }
}

int HeapMaximum (std::deque<int> &heap)
{
    const int topValue = heap[0];
    return std::move(topValue);
}

int HeapExtractMax (std::deque<int> &heap)
{
    if (heap.empty()) {
        std::cerr << "heap overfow!\n";
    }
    int max = std::move(heap[0]);
    heap.pop_front ();
    MaxHeapify (heap, 0);
    return std::move (max);
}

void
HeapIncreaseKey (std::deque<int> &heap, int &&node, int &&key)
{
    if (key < heap[node]) {
        std::cerr << "This key is smaller than current key!\n";
    }
    heap[node] = key;
    int parentNode = 0;
    while (( node > 0) && (parentNode = Parent(node), heap[parentNode] < key)){
        std::swap (heap[parentNode], heap[node]);
        node = parentNode;
    }
}

void MaxHeapInsert (std::deque<int> &heap, int key)
{

    heap.push_back (std::move(std::numeric_limits<int>::min()));
    HeapIncreaseKey (heap, heap.size() - 1, std::move(key));
}

void Print (const std::deque<int> &ideq)
{
    for (const auto &elem : ideq) {
        std::cout << elem << " ";
    }
}

int main ()
{
    std::ios::sync_with_stdio (false);
    std::deque<int> ideq{ 5, 13, 2, 25, 7, 17, 20, 9, 4};
    auto maxHeap = BuildMaxHeap (ideq);
    HeapIncreaseKey (maxHeap, 0, 30);
    HeapIncreaseKey (maxHeap, maxHeap.size() - 1, 40);
    MaxHeapInsert (maxHeap, 35);
    Print (maxHeap);
    std::cout << std::endl;
    return 0;
}

当然还有许多需要改进的地方, 还希望看官多提意见哈~

泛型的话还需要把 Less<_Ty>(_Ty lhs, _Ty rhs) 抽象出来, 甚至还有 Left<_Ty>(_Ty index), Right<_Ty>(_Ty index) 和 Parent<_Ty>(_Ty) 也要抽象出来. 只是这个博客的目的还是复习这个算法, 所以不作过多讨论.

当然要只是纯粹练习算法, 还是 python 更爽一些......

而且我不会说 STL 有个 priority_queue<type> 的......

时间: 2024-10-31 03:07:48

C++ 实现最大堆排序与最大优先队列的相关文章

第六章 堆排序 6.5 优先队列

package chap06_Heap_Sort; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Arrays; import org.junit.Test; /** * 优先队列,二叉堆数组实现,数组的size最好大一些,至少比里面的堆大一些,来实现堆的扩展(插入元素) * * @author xiaojintao * */ public class PriorityQueue {

算法导论学习之堆+堆排序+堆构成优先队列

注:堆分为最大堆和最小堆两种,下面我们讨论的堆都是指的最大堆,最小堆的性质与其是类似的. 堆数据结构是一种数组对象,可以被视为一棵完全二叉树(这棵二叉树除最后一层外,其余每层都是填满的):我们用一个数组来存储一个堆,表示堆的数组有两个属性:length[A]表示的是数组中的元素个数,headsize[A]表示堆中元素个数(也就是说数组中的元素不一定都是堆中的元素). 下面不加证明的给出一些堆的性质: 对于任何一个节点,其父节点为i/2(i>1):左儿子:2*i,右儿子:2*i+1; 对于最大堆每

三、堆排序(Heapsort),优先队列可以用于O(N log N)

三.堆排序(Heapsort) 优先队列可以用于O(N log N) 存储空间增加一倍 排序类别 排序方法 时间复杂度 时间复 杂度 空间复杂度 稳定性 复杂性 平均情况 最坏情况 最好情况 选择排序 堆排序 O(nlog2n) O(nlog2n) O(nlog2n) O(1) 不稳定 较复杂 堆排序:堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序.首先简单了解下堆结构. 堆:堆是具有以下性质的完全二叉树

算法导论——最大堆,以及堆排序算法

本段代码实现了建堆,维护最大堆的性质,堆排序函数,优先队列的相关函数(插入,找最大值,提取出最大值,增加关键值,增加元素),以及相关的测试 1 #include <iostream> 2 #include <memory> 3 #include <iomanip> 4 #define LEFT(i) (2 * i) 5 #define RIGHT(i) (2*i + 1) 6 #define PARENT(i) (i >> 1) 7 8 using name

算法问题分类---Top-K问题与多路归并排序

Pro1:寻找前K大数 方法1:K小根堆  后面的值若大于当前根,则替换之,并调整堆 大部分人都推荐的做法是用堆,小根堆.下面具体解释下: 如果K = 1,那么什么都不需要做,直接遍历一遍,时间复杂度O(N). 下面讨论K 比较大的情况,比如1万. 建立一个小根堆,则根是当前最小的第K个数.然后读入N-K个数,每次读入一个数就与当前的根进行比较,如果大于当前根,则替换之,并调整堆.如果小,则读入下一个. 时间复杂度O(N*logK). 方法2:利用快排分区思想: 本题还有一个时间复杂度比较好的做

如何给100亿个数字排序

转自:http://netsmell.com/post/how-sort-10-billion-data.html?ref=myread 海量数据处理/外部归并排序 - 分治.cppp // 对 2 亿个数字进行排序, 约 10 G 的文件, 每个数字 int 能表示   3 // 算法流程   4 // 将 10 G 的文件散列到 300 个文件中, 每个文件大约 35 MB   5 // 对 35 MB 的小文件内部排序, 或者分发到多台计算机中, 并行处理 MapReduce   6 //

排序(二)

(一) 堆排序:由于优先队列可以花费O(NlogN)时间的排序,基于该想法的排序称之为堆排序.建立N个元素的二叉堆,基本上花费的时间为O(N),再执行N次删除操作.按照顺序呢,最小的元素先离开该堆.通过将这些元素记录到第二个数组然后在将数组拷贝回来,就可得到N个元素的排序.由于每个Delete操作花费时间. 该算法的主要问题在于它使用了一个附加的数组,因此,存储需求增加了一倍,注意,将第二个数组拷贝回第一个数组的额外时间消耗只是O(N),这不可能显著影响运行时间问题,这只是一个空间问题. 避免使

最大/最小de K个数/第K个数

题目 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 思路 堆排序 收获 用优先队列实现最大最小堆 注意下列代码中优先队列的创建声明,需要自定义比较函数 代码 class Solution { public int findKthLargest(int[] nums, int k) { PriorityQueue<Integer> h = new PriorityQueue<>((n1,n2)->n

利用堆实现堆排序&amp;优先队列

数据结构之(二叉)堆 一文末尾提到"利用堆可以实现:堆排序.优先队列".本文代码实现之. 1.堆排序 假设要将无序数组按非递减(递增)排序,则应使用大(小)顶堆.这里涉及到大堆排序涉及到三种操作:(1).MaxHeapify操作(自顶向下即SiftDown操作):(2).BuildMaxHeap操作(线性时间内将无序数组构造成一个最大堆):(3)将堆顶元素和堆的最后一个元素交换,并将堆元素大小减去1,对堆顶元素调用MaxHeapify操作重新调整为大顶堆,重复直到数组有序.下面是详细的