堆排序

  堆排序分爲兩步:建初始堆和交換堆頂元素和末尾元素並重建堆( 排序)  時間複雜度爲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了
	}
}

 

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