總結首先我們要知道什麼是堆?
若n個元素的序列滿足:
a_1\leq{}a_ \\ a_1\leq{}a_\end\right.
a_1\geq{}a_ \\ a_1\geq{}a_\end\right.
為小頂堆或者大頂堆。
若在輸出堆頂的最小值(最大值)後,對剩餘的n-1個元素的序列重新構建成乙個堆,則可得到n個元素的次小值(次大值)…如此反覆,便能得到乙個有序序列,此過程稱之為堆排序。
那麼現在就有兩個問題:
如何將乙個無序序列建成乙個堆?
如何在輸出堆頂元素後,將剩餘元素調整為乙個新堆?
我們先來思考上面的第二個問題:如何在輸出堆頂元素後,將剩餘元素調整為乙個新堆?,以大頂堆為例。
輸出堆頂元素後,以堆中的最後乙個元素替代之;
然後將根結點的值與其左、右子樹根結點的值進行比較,並與其中大者進行比較
重複上述過程,直到葉子節點。完成這些操作後,將得到乙個新的堆,稱這個從堆頂至葉子的調整過程為篩選
堆調整的**實現:
可以看出來,對乙個無序序列反覆篩選,就可以得到乙個堆,即乙個無序序列建堆的過程就是乙個反覆篩選的過程。//調整序列為大頂堆 篩選
void
heapadjust
(int* arr,int s,int m)
if(rc>arr[i]
) arr[s]
=arr[i]
; s=i;
} arr[s]
=rc;
//插入
}
可以這樣理解:
顯然,單節點的二叉樹是堆;在完全二叉樹中,所有以葉子節點為根的子樹是堆,這樣我們只需要依次將序號為n/2,n/2-1,…,1的節點為根的子樹均調整為堆即可。
即對n個無序元素建堆,篩選只需要從n/2個元素開始。
由以上分析可知:對乙個無序序列建堆,然後輸出根,重複該過程,就可以由乙個無序序列輸出乙個有序序列。實質上,堆排序是利用完全二叉樹中父節點與孩子節點之間的內在關係來排序的。
**如下:
堆排序完畢。用c語言寫的,其實在c++中,使用優先佇列(理解優先佇列和普通佇列的不同),也可以實現輸出最小的k個元素。//利用排序的方法,不用sort函式,傳進去的也不是vector陣列
int*
getleastnumbers
(int
* arr,
int arrsize,
int k,
int* returnsize)
//沉下去的是最大的
for(
int i=arrsize-
1;i>
0;i--
)*returnsize=k;
return arr;
}
c++**:
整個過程是由「尋找最小的k個數」引起的,最直觀的做法是先將序列進行從小到大的排序,然後輸出前k個即可。當然,這就涉及了很多種排序的方法,本文只介紹了堆排序,其餘方法後期在做比較。程式設計路上,砥礪前行~class
solution
for(int i=k;isize()
;i++)}
for(int i=
0;i)return vec;}}
;
最小的K個數
問題描述 給定的n個整數,計算其中最小的k個數。最直觀的解法莫過於將n個數按公升序排列後輸出前k個。但是就效率來看,這種方法並不是最理想的。一種改進方法是借助快速排序中對陣列的劃分,以第k個元素對陣列進行劃分,使得比第k個數字小的數字都在其左邊,比其大的數字都在它的右邊。void swap int ...
最小的K個數
從 陣列中出現次數超過一半的數字 得到啟發,同樣可以基於partition函式來解決。一 o n 演算法 void getleastnumbers int input,int n,int output,int k else for int i 0 i k i output i input i 二 o...
最小的K個數
輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,如果不讓使用sort的話,自己實現乙個,或者依次選取最小的 class solution public vectorgetleastnumbers solution vectori...