java數(shù)據(jù)結(jié)構(gòu)排序算法之樹形選擇排序詳解
本文實(shí)例講述了java數(shù)據(jù)結(jié)構(gòu)排序算法之樹形選擇排序。分享給大家供大家參考,具體如下:
這里我們就來說說選擇類排序之一的排序:樹形選擇排序
在簡(jiǎn)單選擇排序中,每次的比較都沒有用到上次比較的結(jié)果,所以比較操作的時(shí)間復(fù)雜度是O(N^2),想要降低比較的次數(shù),則需要把比較過程中的大小關(guān)系保存下來。樹形選擇排序是對(duì)簡(jiǎn)單選擇排序的改進(jìn)。
樹形選擇排序:又稱錦標(biāo)賽排序(Tournament Sort),是一種按照錦標(biāo)賽的思想進(jìn)行選擇排序的方法。首先對(duì)n個(gè)記錄的關(guān)鍵字進(jìn)行兩兩比較,然后在n/2個(gè)較小者之間再進(jìn)行兩兩比較,如此重復(fù),直至選出最小的記錄為止。
算法實(shí)現(xiàn)代碼如下:
package exp_sort; public class TreeSelectSort { public static int[] TreeSelectionSort(int[] mData) { int TreeLong = mData.length * 4; int MinValue = -10000; int[] tree = new int[TreeLong]; // 樹的大小 int baseSize; int i; int n = mData.length; int max; int maxIndex; int treeSize; baseSize = 1; while (baseSize < n) { baseSize *= 2; } treeSize = baseSize * 2 - 1; for (i = 0; i < n; i++) { tree[treeSize - i] = mData[i]; } for (; i < baseSize; i++) { tree[treeSize - i] = MinValue; } // 構(gòu)造一棵樹 for (i = treeSize; i > 1; i -= 2) { tree[i / 2] = (tree[i] > tree[i - 1] ? tree[i] : tree[i - 1]); } n -= 1; while (n != -1) { max = tree[1]; mData[n--] = max; maxIndex = treeSize; while (tree[maxIndex] != max) { maxIndex--; } tree[maxIndex] = MinValue; while (maxIndex > 1) { if (maxIndex % 2 == 0) { tree[maxIndex / 2] = (tree[maxIndex] > tree[maxIndex + 1] ? tree[maxIndex] : tree[maxIndex + 1]); } else { tree[maxIndex / 2] = (tree[maxIndex] > tree[maxIndex - 1] ? tree[maxIndex] : tree[maxIndex - 1]); } maxIndex /= 2; } } return mData; } public static void main(String[] args) { // TODO Auto-generated method stub int array[] = { 38, 62, 35, 77, 55, 14, 35, 98 }; TreeSelectionSort(array); for (int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); } System.out.println("\n"); } }
算法分析:
在樹形選擇排序中,除了最小的關(guān)鍵字,被選出的最小關(guān)鍵字都是走了一條由葉子結(jié)點(diǎn)到跟節(jié)點(diǎn)的比較過程,由于含有n個(gè)葉子結(jié)點(diǎn)的完全二叉樹的深度log2n+1,因此在樹形選擇排序中,每選出一個(gè)較小關(guān)鍵字需要進(jìn)行l(wèi)og2n次比較,所以其時(shí)間復(fù)雜度是O(nlog2n),移動(dòng)記錄次數(shù)不超過比較次數(shù),故總的算法時(shí)間復(fù)雜度為O(nlog2n),與簡(jiǎn)單選擇排序算法相比,降低了比較次數(shù)的數(shù)量級(jí),增加了n-1個(gè)額外的存儲(chǔ)空間存放中間比較結(jié)果。
補(bǔ)充:
這里再來介紹對(duì)樹形選擇排序的改進(jìn)算法,即堆排序算法。
堆排序彌補(bǔ)了樹形選擇排序算法占用空間多的缺憾。采用堆排序時(shí),只需要一個(gè)記錄大小的輔助空間。
算法思想是:
把待排序記錄的關(guān)鍵字存放在數(shù)組r[1...n]中,將r看成是一棵完全二叉樹的順序表示,每個(gè)結(jié)點(diǎn)表示一個(gè)記錄,第一個(gè)記錄r[1]作為二叉樹的根,以下每個(gè)記錄r[2...n]依次逐層從左到右順序排列,任意結(jié)點(diǎn)r[i]的左孩子是r[2*i],右孩子是r[2*i+1];雙親是r[[i/2]]。
堆定義:各結(jié)點(diǎn)的關(guān)鍵字值滿足下列條件:
r[i].key >= r[2i].key 且 r[i].key >= r[2i+1].key (i=1,2,……[i/2])
滿足上面條件的完全二叉樹稱為大根堆;相反,如果這顆完全二叉樹中任意結(jié)點(diǎn)的關(guān)鍵字小于或者等于其左孩子和右孩子的關(guān)鍵字,對(duì)應(yīng)的堆叫做小根堆。
堆排序的過程主要需要解決兩個(gè)問題:第一個(gè)是,按照堆定義建初堆;第二個(gè)是,去掉最大元后重建堆,得到次大元。
堆排序即是利用堆的特性對(duì)記錄序列進(jìn)行排序,過程如下:
1、對(duì)給定序列建堆;
2、輸出堆頂;(首元素與尾元素交換)
3、對(duì)剩余元素重建堆;(篩選首元素)
4、重復(fù)2,3,直至所有元素輸出。
注意:“篩選”須從第[n/2]個(gè)結(jié)點(diǎn)開始,逐層向上倒退,直到根結(jié)點(diǎn)。
算法分析:
1. 對(duì)深度為 k 的堆,“篩選”所需進(jìn)行的關(guān)鍵字比較的次數(shù)至多為2(k-1);
2. n 個(gè)關(guān)鍵字的堆深度為 [log2n]+1, 初建堆所需進(jìn)行的關(guān)鍵字比較的次數(shù)至多為:n* [log2n];
3. 重建堆 n-1 次,所需進(jìn)行的關(guān)鍵字比較的次數(shù)不超過:(n-1)*2 [log2n ];
因此,堆排序在最壞情況下,其時(shí)間復(fù)雜度為O(nlog2n),這是堆排序的最大優(yōu)點(diǎn)。
更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
Java語(yǔ)法基礎(chǔ)之選擇結(jié)構(gòu)的if語(yǔ)句、switch語(yǔ)句詳解
這篇文章主要為大詳細(xì)介紹了Java語(yǔ)法基礎(chǔ)之選擇結(jié)構(gòu)的if語(yǔ)句、switch語(yǔ)句,感興趣的小伙伴們可以參考一下2016-09-09基于params、@PathVariabl和@RequestParam的用法與區(qū)別說明
這篇文章主要介紹了方法參數(shù)相關(guān)屬性params、@PathVariabl和@RequestParam用法與區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08徹底搞明白Spring中的自動(dòng)裝配和Autowired注解的使用
這篇文章主要介紹了徹底搞明白Spring中的自動(dòng)裝配和Autowired注解的使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03前端如何傳遞Array、Map類型數(shù)據(jù)到Java后端
這篇文章主要給大家介紹了關(guān)于前端如何傳遞Array、Map類型數(shù)據(jù)到Java后端的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01SpringBoot+Vue靜態(tài)資源刷新后無法訪問的問題解決方案
這篇文章主要介紹了SpringBoot+Vue靜態(tài)資源刷新后無法訪問的問題解決方案,文中通過代碼示例和圖文講解的非常詳細(xì),對(duì)大家解決問題有一定的幫助,需要的朋友可以參考下2024-05-05IDEA安裝lombok插件設(shè)置Enable Annotation Processing后編譯依然報(bào)錯(cuò)解決方法
這篇文章主要介紹了IDEA安裝lombok插件設(shè)置Enable Annotation Processing后編譯依然報(bào)錯(cuò)解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04SpringMvc返回modelandview返回的頁(yè)面無法跳轉(zhuǎn)問題及解決
這篇文章主要介紹了SpringMvc返回modelandview返回的頁(yè)面無法跳轉(zhuǎn)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05springboot如何重定向攜帶數(shù)據(jù) RedirectAttributes
這篇文章主要介紹了springboot如何重定向攜帶數(shù)據(jù) RedirectAttributes,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09