【问题标题】:heap sort - which heap (min/max) to use for ascending and descending order sort?堆排序 - 哪个堆(最小/最大)用于升序和降序排序?
【发布时间】:2016-10-02 17:41:17
【问题描述】:

我注意到一件非常奇怪的事情。

通过lecture 之后,我在 C++ 中实现了一些堆排序代码。

代码如下。

    template<typename T> void min_heapify(std::vector<T> &vec, int i, int size)
    {
        int left  = (2*i); //left child of a zero-indexed heap (array)
        int right = (2*i)+1; //right child.
        int min;

        min = ( (left<size) && (vec[left] < vec[i]) ) ? left : i;
        min = ( (right<size) && (vec[right] < vec[min]) ) ? right : min;

        if (min!= i)
        {
            swapper(vec[i],vec[min]);
            min_heapify(vec, min, size);
        }
    }
    template<typename T> void build_min_heap(std::vector<T> &vec, int size)
    {
        int i = size/2;
        while(i--)
        {
            min_heapify(vec, i, size);

        }
    }
    template<typename T> void heap_sort(std::vector<T> &vec, int size)
    {
        // build min heap
        build_min_heap(vec, size);
        // then extract min repeatedly.
        while(size>0)
        {
            size--;
            swapper(vec[0],vec[size]);
            min_heapify(vec,0,size);
        }
    }

   int main()
   {
        vector<int> v{14,-1,1000, -999, 3,2,5,10};
        heap_sort(v, v.size());

        return 0;
   }

奇怪的是,这对我来说很有意义 - 建立一个最小堆 - 提取 min(或在构建最小堆后在根处执行 min-heapify) 应该导致升序。 但是,在执行此代码并打印出结果向量后, 我明白了:

1000 14 10 5 3 2 -1 -999 

在试图弄明白发生了什么的时候,我改变了

min = ( (left<size) && (vec[left] < vec[i]) ) ? left : i;
min = ( (right<size) && (vec[right] < vec[min]) ) ? right : min;

min = ( (left<size) && (vec[left] > vec[i]) ) ? left : i;
min = ( (right<size) && (vec[right] > vec[min]) ) ? right : min;

实际上最终选择了父节点和子节点中较大的(或最大值),结果向量是:

-999 -1 2 3 5 10 14 1000 

是我做错了什么还是我对堆/堆排序的理解不清楚?我在这里错过了什么?

【问题讨论】:

  • 您对堆排序中堆使用情况的理解可能不太有效:这些值通常是从最后选择的。

标签: c++ algorithm sorting heap heapsort


【解决方案1】:

是的,swapper(vec[0],vec[size]); 是提取。 您正在将第一个元素提取到向量的最后一个元素中。因此得到相反的结果。

堆最小元素是vec[0]。将其交换到最后一个位置将在该向量中创建一个从最大到最小的排序。

如果你实现类似的东西

result.push_back(heap.pop_min());

你会得到你期望的顺序。

【讨论】:

  • “你应该通过...提取(推入结果向量)” -- 你是吗?如果您想要的是就地排序,这听起来像是不必要的工作。相反,您应该改变对堆排序应该如何工作的期望,如果您希望结果反转,则使用反向比较。
  • @BenjaminLindley 感谢您的评论。我会修改的。
  • @BenjaminLindley 嗨,这是否意味着我应该使用 max-heapify 来就地进行升序排序?
  • @CaptainGiraffe 啊!当然。如果我只是在不取出它的情况下进行交换,那么它们(最小元素)就位于数组中。谢谢。
  • @Raaj:是的,我想是的。例如,如果您使用标准库函数make_heap 后跟sort_heap,您会得到同样的结果。 make_heap 默认创建一个最大堆,sort_heap 将按升序对该堆进行排序。
猜你喜欢
  • 2020-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 2011-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多