堆排序分爲兩步:建初始堆和交換堆頂元素和末尾元素並重建堆( 排序) 時間複雜度爲O(n) + O(nlgn)即等於O(nlgn)
一、建堆:時間複雜度:O(n)
堆我們正好可以用一個數組來存儲,那麼它將有如下的關係:
i 表示第i個結點
parent = (i-1) / 2;
Lchild = 2*i + 1;
Rchild = 2*i + 2;
堆建立的時候有兩點很重要:
1、必須從最後一個子樹往上開始調整
2、每次調整都是從子樹的根節點開始向下調整
堆排的代碼如下:
//從某一個結點開始調整堆,可調整整個堆也可以調整部分堆,也就是說這個函數用於調整部分是滿足堆的特性,部分不滿足
void heapfiy(int *tree, int n, int i)//保證每一個子樹都是堆(即符合堆的要求) //i表示是第i個結點,n表示結點的個數
{
if(i > n) return ;
int Lchild = 2*i + 1; //下標
int Rchild = 2*i + 2;
int max = i; //要在每個子樹中先找到最大值,然後和根節點進行比較,max保存最大值結點的下標
if(Lchild < n && tree[Lchild] > tree[max])
{
max = Lchild;
}
if(Rchild < n && tree[Rchild] > tree[max])
{
max = Rchild;
}
if(max != i)
{
swap(tree[i],tree[max]);
heapfiy(tree,n,max);
}
}
void build_heap(int *tree, int n) //完全不符合堆的特性的堆的調整
{
int last_node = n - 1; //要從最後一個子樹的根開始調整
int parent = (last_node - 1) / 2; //每次調整都是從該子樹的根節點開始向下調整
//從這個結點開始全部做heapfiy(調整)
for(int i = parent; i>=0; i--)
{
heapfiy(tree,n,i);
}
}
排序的代碼如下:交換堆頂重建堆的時間複雜度:O(nlgn)
void heap_Sort(int *tree, int len)
{
build_heap(tree,len);
for(int i=len-1; i>=0; i--)
{
swap(tree[i],tree[0]);
heapfiy(tree,i,0); //把最後一個結點和根結點交換之後,就得出最大的結點了,所以就把它砍斷,n = i,因爲i每次都減1了
}
}