堆排序<一> ---------簡單結構堆排序

堆排序:
利用最大堆/最小堆完成排序
用數組存儲,但邏輯結構爲 完全二叉樹

HeapElem arr[] = {45,23,56,34,12,45,67,78,90};
物理結構:

邏輯結構:

arr[end] = 90
start = (end-1)/2=3
tmp = 34
i = 3 (要調整的結點)
j= i*2+1 (左孩子結點)
對 3 7 8 進行判斷,已符合最小堆規則 則不調整 break
arr[i] = tmp;

–pos // 開始循環調整 2位置的 while(pos>=0)



普通結構堆排序

#include <stdio.h>
#include <assert.h>
typedef int HeapElem ;   // 定義堆排序時數據類型

template<class Type>
void Swap(Type &a,Type &b)    // 交換函數
{
    Type tmp = a;
    a=b;
    b=tmp;
}
void FileterDown(HeapElem *p,int start,int end)   // 向下調整
{
    int i = start;             // 調整的分支結點 起始位置
    int j = i*2 +1;             // 左孩子
    HeapElem tmp = p[i];        // 取出當前元素

    while(j<=end)                 // 在end之前
    {
        if(j < end && p[j]>p[j+1]) j+=1;         // 左右孩子內部判斷取最小==》最小堆
        if(tmp <= p[j]) break;
        p[i] = p[j]; 
        i = j;                          // 向下繼續調整
        j = i*2+1;
    }
    p[i] = tmp;                            
}
void MakeMinHeap(HeapElem *p ,int n)
{
    if(p == NULL || n <2)
    {
        return ;
    }
    int end = n-1 ;                         // 找出最後一個結點下標
    int pos = (end -1)/2;                   // pos爲end的雙親結點
    while(pos>=0)                            
    {
        FileterDown(p,pos,end);             //向下調整
        --pos;                              // 要調整的位置向上走
    }
}

void Heap_sort(HeapElem *p,int n)
{
    int pos = n-1;
    while(pos > 0)
    {
        Swap(p[0],p[pos]);                 // 用堆頂最小元素  與末尾元素交換
        FileterDown(p,0,--pos);            // 繼續調整剩餘其他元素         
    }
}

void PrintHeap(HeapElem *p ,int n)
{
    assert(p != NULL);
    for(int i = 0;i<n;++i)
    {
        printf("%d ",p[i]);           // 打印  從大到小  
    }
    printf("\n");
}
void main()
{
    HeapElem arr[] = {45,23,56,34,12,45,67,78,90};
    int n = sizeof(arr)/sizeof(arr[0]);

    MakeMinHeap(arr,n);
    Heap_sort(arr,n);
    PrintHeap(arr,n);
}

測試結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章