有可能是全網最易理解的有關【堆排序】的博客

這次想寫一下堆排序,之前遇到過好多次有關堆排序的問題,無論是編程還是選擇題。但是對這個堆排序一直是稀裏糊塗,一個原因網上好多博客寫的爛,衆說紛紜,各執一詞,還有一個原因是自己沒有真正想要搞懂一個問題,真正搞透問題。

好了廢話不多說開始講解這次的主角堆排序

堆排序步驟

堆排序的步驟主要是三個:

  • 將序列構建成堆,然後整理這個堆,如果最終需要得到升序->大頂堆,降序->小頂堆
  • 將堆頂元素和末尾元素互換,將最大元素放到堆的最後
  • 然後調整這個堆,將除了最後一個元素之外的其他元素按照堆的順序進行整理,然後再將堆頂元素和最後一個元素(除了剛剛已經被放在最後一個的元素)進行互換位置。

這個地方有很多地方都是坑:
一個就是:
首先必須按照最後的排序要求構建大頂堆還是小頂堆!!!
首先必須按照最後的排序要求構建大頂堆還是小頂堆!!!
首先必須按照最後的排序要求構建大頂堆還是小頂堆!!!

第二個就是:
(這個步驟非常重要)構建大頂堆,小頂堆的方法:從最後一個非葉子節點(這個節點的位置非常有意思:如果節點數爲奇數:n/2-1; 如果節點數是偶數:n/2)開始調整,將這個節點和自己的兩個子節點進行比較,將這三個節點中最大或者最小的放在根節點處,從右向左,從下向上,依次整理過去。

第三個就是:
互換堆頂和末尾節點之後,末尾節點就不考慮了(排除在後續操作之外了)

複雜度

堆排序的平均時間複雜度、最好情況時間複雜度、最差情況時間複雜度都是O(nlog2n)O(nlog_2n)
空間複雜度:O(1)O(1)
堆排序是一種不穩定的排序。

C++實現代碼

//調用heap_sort,其中data爲待排序的數組,heapsize爲數組長度
void heapsort(int data[],int heapsize){
	//堆排序算法實現主體:先用build_max_heap將輸入數組構造成大頂堆
	//將data[0]和堆的最後一個元素交換
	//繼續進行調整
build_max_heap(data,heapsize);
for(int i=heapsize-1;i>0;i--){
	int t=data[0];
	data[0]=data[i];
	data[i]=t;
	max_heapify(data,0,i);
	}
}
void build_max_heap(int data[],int heapsize){
//建堆的過程,通過自底向上地調用max_heapify來將一個數組data[1...n]變成一個大頂堆
//只對除了葉子節點之外的節點進行調整
for(int i=heapsize/2-1;i>=0;i--)
	max_heapify(data,i,heapsize);
}
void max_heapify(int data[],int i,int heapsize){
	//以某個節點爲根節點的子樹進行調整,調整爲大頂堆
	int l=2*i+1;
	int r=2*i+2;
	int largest =i;
	if(l<heapsize && data[l]>data[i]){
	 largest =l;
	}
	if(r<heapsize && data[r]>data[largest]){
	largest =r;
	}
	if(largest!=r){
	int temp=data[largest];
	data[largest]=data[i];
	data[i]=temp;
	max_heapify(data,largest,heapsize);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章