堆排序:
利用最大堆/最小堆完成排序
用數組存儲,但邏輯結構爲 完全二叉樹
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);
}
測試結果: