首先我們要明確堆並非一種資料結構,所謂堆排序其實是對陣列進行排序。首先,我們可以將陣列看作乙個完全二叉樹,陣列第乙個元素a[0]即為二叉樹根節點,而後我們需要了解一些完全二叉樹的基礎概念:完全二叉樹最後乙個非葉子節點索引為:元素個數/2-1。記住這個以後我們就可以進行堆排序了,堆排序的思路比較簡單,如果我們想將輸入的資料由小到大排列並輸出,我們可以這樣做:(1)首先將待排序的陣列構建成乙個大頂堆,什麼是大頂堆?大頂堆即是一顆完全二叉樹,這顆二叉樹的根必須為所有元素中的最大值,並且這顆完全二叉樹中的所有父親節點都比起孩子節點大。那要怎麼構建大頂堆呢?構建大頂堆就要用到我們之前所說的二叉樹的最後乙個非葉子節點索引,我們要從最後乙個非葉子節點索引開始,將該節點與其孩子節點做比較,如果有孩子節點比它大,則將這個孩子節點與它(父節點)交換位置,重複這個比較、交換操作直到根節點。這樣乙個過程後我們得到的堆(完全二叉樹)不就是乙個大頂堆了嗎。得到大頂堆只是第一步操作,接下來我們將這個最大值即樹根的值與二叉樹的最後乙個節點交換位置,這樣最大的值就位於二叉樹末尾了(也可以說將最大的數放到陣列末尾了)。為什麼我們要將其放到末尾?因為我們想將陣列中元素由小到大排列輸出啊,那最大的數是不是應該最後乙個輸出,最大的數是不是應該放到陣列末尾?同理我們得到的次大的數也應該放到陣列倒數第二個位置、得到的第三大的數應該放到陣列倒數第三個位置..........,注意!確認了輸出位次的數就不能再動了,比如前面已經確認是最後乙個輸出的最大數!因此我們後續的所有操作都與其無關。回到正題,剛剛我們把最大的數與處於末尾的元素交換了位置,現在的堆還是大頂堆嗎?那就不敢保證了,因此我們還得繼續建立大頂堆,因為我們還要找到第二大的元素,此時就不用再從最後乙個非葉子節點的索引開始排序了,因為經過第一次的排序,這已經不再是一顆雜亂無章的二叉樹了,而是乙個除了剛剛交換上去的根節點外,所有父節點都比其孩子節點大的樹。我們現在就可以直接對根節點進行操作:其孩子節點是否有比它大的,有的話交換,交換後再看有無比它大的孩子節點,有的話再交換............大功告成,現在找到了第二大的元素,並且也處在了樹根的位置,接下來呢,與樹末尾的元素交換啊,注意!現在末尾的元素已經不再是之前換下來的最大的那個元素了!接下來重複對根的操作(與孩子節點比較、交換,最後與末尾元素交換位置)。
貼上**:
主函式:
構建大頂堆的函式:
交換樹根與樹末尾元素的函式:
輸入輸出:
帶你了解堆排序
堆排序在八大排序演算法中屬於選擇排序,她利用的是堆這種資料結構來構建的排序演算法,堆分為大頂堆 小頂堆,根節點的數值要麼是最大的,要麼是最小的,堆排序最主要的兩個操作是建堆和調整堆兩個操作。public static void downadjust int array,int parentindex...
詳解氣泡排序 秒懂
點關注不迷路,歡迎再訪!精簡部落格內容,盡量已專業術語來分享。努力做到對每一位認可自己的讀者負責。幫助別人的同時更是豐富自己的良機。氣泡排序演算法是所以排序演算法中最簡單 最基本的一種。氣泡排序演算法的思路就是交換排序,通過相鄰資料的交換來達到排序的目的。氣泡排序演算法通過多次比較和交換來實現排序,...
詳解選擇排序 秒懂
點關注不迷路,歡迎再訪!精簡部落格內容,盡量已專業術語來分享。努力做到對每一位認可自己的讀者負責。幫助別人的同時更是豐富自己的良機。選擇排序演算法也是比較簡單的排序演算法,其思路比較直觀。選擇排序演算法在每一步中選取最小值來重新排列,從而達到排序的目的。選擇排序演算法通過算選擇和交換來實現排序,其排...