插入并堆排序到用数组构建的堆

Posted

技术标签:

【中文标题】插入并堆排序到用数组构建的堆【英文标题】:Insert and heapsort to heap built with an array 【发布时间】:2018-03-22 01:46:23 【问题描述】:

我正在尝试使用数组创建二进制堆。我已经成功地使用buildHeapheapify 建立了堆。我的问题是当我尝试将 insert 一个新元素放入数组时,以及当我尝试使用 heapSort 对其进行排序时。

这是我为 heapify 函数提供的内容:

void heap::Heapify(int arr[], int i)
    int largest = i;
    int L = LeftChild(i);
    int R = RightChild(i);
    if (L <= heapSize && arr[L] > arr[i])
        largest = L;
    else
        largest = i;
    

    if (R <= heapSize && arr[R] > arr[largest])
        largest = R;
    
    if(largest != i)
        int temp = arr[i];
        arr[i] = arr[largest];
        arr[largest] = temp;
        Heapify(arr, largest);
    

这是我的buildHeap 函数:

void heap::BuildHeap(int arr[])
    for(int i = (heapSize/2)-1; i >= 0; i--)
        Heapify(arr, i);
    

这两个功能有效,而以下功能无效,对于插入它没有将其插入正确的位置。

这里是insert 函数:

void heap::Insert(int arr[], int key)
    heapSize++;
    int i = heapSize - 1;

    while(i > 0 && arr[Parent(i)] <= key)
        arr[i] = arr[Parent(i)];
        i = Parent(i);
    

    arr[i] = key;

使用heapSort 函数,它在很大程度上对其进行排序,但会像这样打印它(第一行是排序之前的堆):

32 24 5 19 23 4 3 11 2 12 
5 2 4 3 23 19 32 11 24 12 

这是我的heapSort 函数:

void heap::HeapSort(int arr[])
    for(int i = heapSize - 1; i >= 0; i--)
        int temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;

        heapSize = heapSize - 1;
        Heapify(arr, 0);
    

任何帮助确定这两个功能如何无法正常工作的帮助将不胜感激。

【问题讨论】:

看起来像一个简单的调试任务。如果您尝试交换两个值,但交换后两者都相同并且另一个值丢失,那将是不好的。对于正确的minimal reproducible example,我希望将其复制粘贴到我的编译器中并得到与您相同的问题。 你真的应该回顾一下二叉堆背后的理论。序列 32 24 5 19 23 4 3 11 2 12 看起来不像是有效内容。堆排序不会对堆的内部数据进行就地排序,而是逐个提取最小值/最大值。 arr[i] = arr[Parent(i)]; 应该是std::swap(arr[i], arr[Parent(i)]) 【参考方案1】:

我认为问题在于这些行中的Off-by-One-Error

if (L <= heapSize && arr[L] > arr[i])

if (R <= heapSize && arr[R] > arr[largest])

它们都应该是&lt; 而不是&lt;=,因为最后一个元素在heapsSize-1 中。

其他细节

void heap::Heapify(int arr[], int i)
    int largest = i; // setting largest to i first time
    int L = LeftChild(i);
    int R = RightChild(i);
    if (L <= heapSize && arr[L] > arr[i]) // compare with arr[i] is not wrong but doesn't express the intent.
        largest = L;
    else
        largest = i; // setting largest to i second time
    

    if (R <= heapSize && arr[R] > arr[largest])
        largest = R;
    
    if(largest != i)
        int temp = arr[i];      // these 3 lines are the std::swap
        arr[i] = arr[largest];  // or you could roll your own function that does the same.
        arr[largest] = temp;    // better expressing the intent.
        Heapify(arr, largest);
    

改写为

void heap::Heapify(int arr[], int i)
    int largest = i;
    int L = LeftChild(i);
    int R = RightChild(i);

    if (L < heapSize && arr[L] > arr[largest]) 
        largest = L;
     

    if (R < heapSize && arr[R] > arr[largest]) 
        largest = R;
    

    if(largest != i)
        swap(arr[i], arr[largest]);
        Heapify(arr, largest);
    

【讨论】:

以上是关于插入并堆排序到用数组构建的堆的主要内容,如果未能解决你的问题,请参考以下文章

堆堆排序

八大排序-插入排序

数据结构与算法学习笔记(10) 排序

插入排序法

五十五深入插入排序和选择排序

插入排序法