簡體   English   中英

堆排序的目的是什么?

[英]What is the purpose of having heap sort?

當我們構建一個堆時,數組中的元素會按照特定的順序(升序或降序)排列,具體取決於它是最大堆還是最小堆。 那么在構建堆時,堆排序有什么用呢?它本身以排序的順序排列元素,時間復雜度更小?

    void build_heap (int Arr[ ])
        {
           for(int i = N/2-1 ; i >= 0; i-- )
           {
              down_heapify (Arr, i, N);
           }
        }
    void heap_sort(int Arr[], int N)
    {
        build_heap(Arr);
        
        for(int i = N-1; i >= 1; i--)
        {
            swap(Arr[i], Arr[0]);
            down_heapify(Arr, 0, i+1);
        }
    }

堆排序總結

堆排序是一種算法,可以概括為兩個步驟:

  • 將輸入數組轉換為堆;
  • 將堆轉換為排序數組。

堆本身不是排序數組。

讓我們看一個例子:

[9, 7, 3, 5, 4, 2, 0, 6, 8, 1]   # unsorted array

convert into heap
[9, 8, 3, 7, 4, 2, 0, 6, 5, 1]   # array representing a max-heap

sort
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]   # sorted array

如果你仔細觀察,你會注意到我的例子中的第二個數組,它代表一個堆,並沒有完全排序。 元素的順序看起來不像原始的未排序數組那樣隨機; 它們看起來幾乎是按降序排列的; 但它們沒有完全排序。 在數組中 3 在 7 之前,0 在 6 之前。

那么什么是堆?

什么是堆?

請注意,在上一節中,我區分了“堆”和“表示堆的數組”。 先說什么是堆,然后說什么是表示堆的數組。

最大堆是在節點上具有值的二叉樹,它滿足以下兩個屬性:

  • 子節點上的值總是低於其父節點上的值;
  • 這棵樹幾乎是完整的,即樹的所有分支都具有幾乎相同的長度,最長的分支和最短的分支之間的差異最多為 1; 此外,最長的分支必須在左側,最短的分支必須在右側。

在我給出的示例中,構建的堆是這樣的:

          9
      /      \
     8        3
   /   \     / \
  7     4   2   0
 / \   / \ / \ / \
6   5 1

您可以檢查此二叉樹是否滿足堆的兩個屬性:每個子節點的值都低於其父節點,並且所有分支的長度幾乎相同,每個分支始終有 4 或 3 個值,最長的分支位於左邊,最短的分支在右邊。

什么是表示堆的數組?

將二叉樹存儲到數組中通常很不方便,二叉樹通常使用指針來實現,有點像鏈表。 但是,堆是一種非常特殊的二叉樹,它的“幾乎完整”屬性對於將其實現為數組非常有用。

我們所要做的就是從左到右讀取每行的值。 在上面的堆中,我們有四行:

9
8 3
7 4 2 0
6 5 1

我們只需將這些值按順序存儲在一個數組中:

[9,  8, 3,  7, 4, 2, 0,  6, 5, 1]

請注意,這正是我文章開頭堆排序第一步之后的數組。

在這個數組表示中,我們可以使用位置來確定哪個節點是哪個節點的子節點:位置i的節點有兩個子節點,分別位於位置2*i+12*i+2

該數組不是排序數組。 但是它代表一個堆,我們可以很容易地使用它來生成一個排序數組,在n log(n)操作中,通過重復提取最大元素。

如果堆排序是用外部二叉樹實現的,那么我們可以使用最大堆或最小堆,並通過重復選擇最大元素或最小元素來對數組進行排序。 但是,如果您嘗試就地實現堆排序,將堆作為數組存儲在要排序的數組中,您會注意到使用最大堆比使用最小堆方便得多,在order 通過重復選擇最大元素並將其移動到數組的末尾來按升序對元素進行排序。

那么堆排序有什么用呢,在建堆的時候自己按排序的順序排列元素
您似乎混淆了Heap Sort算法heap數據結構的目的 讓我們以這種方式澄清:

heap是一種數據結構,它允許我們在不斷變化的集合中重復查找列表的最小值或最大值。 我們可以使用基於sink()的方法在O(n)從頭開始創建heap 然后每個操作都需要O(logn)復雜度。 但是, heap並沒有為您提供排序數組,它只是根據您的實現提供最大值或最小值。
另一方面, Heap Sort算法為您提供使用heap數據結構的排序數組/集合。 首先,它以O(n)時間復雜度構建一個heap 然后它從底部開始,將最大/最小一一返回到實際數組。 在每次迭代中,您必須heap heapify您的heap以正確獲得下一個最大值/最小值,這總共給出了O(n*logn)時間復雜度。

void heap_sort(int Arr[], int N)
{
    build_heap(Arr);   // O(n) time complexity
    
    for(int i = N-1; i >= 1; i--)  // n iteration
    {
        swap(Arr[i], Arr[0]);
        down_heapify(Arr, 0, i+1);   //O(logn) time complexity
    }
// in total O(n) + O(n*logn) = O(n*logn)
}

總之,構建堆本身並沒有為您提供排序數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM