常見程式演算:: Heap 排序- 改良的選擇排序 - OpenHome.cc

文章推薦指數: 80 %
投票人數:10人

由於使用陣列來儲存堆積樹,每次將最後一個節點與樹根交換的動作,就是將最小值放至後端的陣列,最後陣列就會變為已排序的狀態。

程式實作. C Java Python OPENHOME.CC 常見程式演算 |老掉牙 河內塔 費氏數列 巴斯卡三角形 三色旗 老鼠走迷宮 騎士走棋盤 八皇后 八銀幣 康威生命遊戲 字串比對 背包問題 雙色、三色河內塔 得分排行 |「數」 最大訪客數 Eratosthenes篩選求質數 完全數 阿姆斯壯數 大數運算 指定位數的圓周率 |隨機 蒙地卡羅法求PI 洗牌 Craps賭博遊戲 約瑟夫問題 |組構 排列 格雷碼 子集 k組合 因數分解 加法因子 |排序 選擇、插入、氣泡排序 Heap排序-改良的選擇排序 Shell排序-改良的插入排序 Shaker排序-改良的氣泡排序 快速排序(一) 快速排序(二) 合併排序 基數排序 |搜尋 線性搜尋 二分搜尋 插補搜尋 費氏搜尋 |矩陣 稀疏矩陣 多維矩陣降維 上/下三角、對稱矩陣 奇數魔方陣 4N魔方陣 2(2N+1)魔方陣 |運算 中序式轉後序式 後序式運算 Quine GitHub Twitter Facebook LinkedIn 2DDesigns 3DDesigns Tags BuiltwithbyHugo HOME> 常見程式演算> 排序> Heap排序-改良的選擇排序 解法思路 程式實作 sort C Java Python Scala Ruby JavaScript Haskell Heap排序-改良的選擇排序 December8,2021 選擇排序的概念簡單,以降冪為例,每次從未排序部份選最小值,插入已排序部份的後端,時間主要花費於在整個未排序部份尋找最小值,如果能讓搜尋最小值的方式加快,選擇排序法的速率也就可以加快。

Heap排序會先建立堆積樹(Heaptree),父子節點間的值具有順序關係,可以加快值的搜尋,可算是改良的選擇排序法。

解法思路 堆積樹是個二元樹,父節點最多有兩個子節點,父節點若小於子節點,稱為最小堆積(Minheap),父節點若大於子節點,稱為最大堆積(Maxheap),同一層的節點不考慮大小關係,例如是個最小堆積樹: 若使用陣列來儲存堆積樹的元素,為了計算方便,使用的起始索引是1而不是0,索引1是樹根位置,如果左子節點儲存在陣列中的索引為s,則其父節點的索引為s/2,而右子節點為s+1,就如上圖所示,將上圖的堆積樹轉換為陣列後如下: 若要建立堆積樹,以最小堆積為例,加至堆積樹的元素會先放置在最後一個節點位置,然後檢查父節點是否小於子節點,將小的元素不斷與父節點交換,直到滿足堆積樹的條件為止,例如在上圖的堆積加入一個元素12,則堆積樹的調整方式如下所示: 建立好最小堆積樹後,樹根一定是最小值,將最小值取出,然後調整樹為最小堆積樹,不斷重複這兩個步驟,就可以達到排序的效果。

最小值取出方式是將樹根與最後一個節點交換,然後切下最後一個節點;調整堆積樹的方式,是找出父節點兩子節點中較小的一個進行交換,如下所示: 調整完畢後,樹根節點又是最小值了,於是可以重覆這個步驟,再取出最小值,並調整樹為堆積樹,如下所示: 由於使用陣列來儲存堆積樹,每次將最後一個節點與樹根交換的動作,就是將最小值放至後端的陣列,最後陣列就會變為已排序的狀態。

程式實作 C Java Python Scala Ruby JavaScript Haskell #include #include #defineLEN10 #defineOFFSET1 #defineSWAP(x,y){intt;t=x;x=y;y=t;} voidheapSort(int*,intlen,int(*)(int,int)); voidheapTree(int*,int,int(*)(int,int)); voidselectFromHeap(int*,int,int(*)(int,int)); voidbubbleLeaf(int*,int,int(*)(int,int)); intisBubbleable(int*,int,int,int(*)(int,int)); voidbubbleRoot(int*,int,int(*)(int,int)); intidxFromChilds(int*,int,int,int(*)(int,int)); intisRightLeafSuitable(int*,int,int,int(*)(int,int)); voidprint(int*,intlen); intascending(int,int); intdescending(int,int); intmain(void){ intnum[LEN]={10,9,1,2,5,3,8,7,12,11}; heapSort(num,LEN,descending); print(num,LEN); heapSort(num,LEN,ascending); print(num,LEN); system("PAUSE"); return0; } voidheapSort(int*num,intlen,int(*compar)(int,int)){ heapTree(num,len,compar); selectFromHeap(num,len,compar); } voidheapTree(int*num,intlen,int(*compar)(int,int)){ inti,end; for(i=1,end=len+1;iOFFSET;end--){ SWAP(num[1-OFFSET],num[end-OFFSET]); bubbleRoot(num,end,comp); } } voidbubbleLeaf(int*num,inteleIdx,int(*compar)(int,int)){ intchildIdx,parentIdx; for(childIdx=eleIdx,parentIdx=eleIdx/2; isBubbleable(num,childIdx,parentIdx,compar); childIdx=parentIdx,parentIdx=childIdx/2){ SWAP(num[parentIdx-OFFSET],num[childIdx-OFFSET]); } } intisBubbleable(int*num,intchildIdx, intparentIdx,int(*compar)(int,int)){ returnchildIdx>OFFSET&& compar(num[parentIdx-OFFSET],num[childIdx-OFFSET])<0; } voidbubbleRoot(int*num,intend,int(*comp)(int,int)){ intparentIdx,childIdx; for(parentIdx=0+OFFSET, childIdx=idxFromChilds(num,parentIdx,end,comp); childIdx0; parentIdx=childIdx, childIdx=idxFromChilds(num,parentIdx,end,comp)){ SWAP(num[parentIdx-OFFSET],num[childIdx-OFFSET]); } } intidxFromChilds(int*num,intparentIdx,intend,int(*comp)(int,int)){ intchildIdx=parentIdx*2; returnisRightLeafSuitable(num,childIdx,end,comp)? childIdx+1:childIdx; } intisRightLeafSuitable(int*num,intchildIdx, intend,int(*comp)(int,int)){ returnchildIdx0; } voidprint(int*arr,intlen){ inti; for(i=0;i> intascending(Tt1,Tt2){returnt1.compareTo(t2);} publicstatic> intdescending(Tt1,Tt2){return-ascending(t1,t2);} publicstatic> voidheapSort(Listlist){heapSort(list,Sort::ascending);} privatestaticfinalintOFFSET=1; publicstaticvoidheapSort( Listlist,Comparatorc){ heapTree(list,c); selectFromHeap(list,c); } privatestaticvoidheapTree(Listlist,Comparatorc){ for(inti=1,end=list.size()+1;ivoidselectFromHeap(Listlist, Comparatorc){ for(intend=list.size();end>OFFSET;end--){ swap(list,1-OFFSET,end-OFFSET); bubbleRoot(list,end,c); } } privatestaticvoidbubbleLeaf(Listlist, inteleIdx,Comparatorc){ for(intchildIdx=eleIdx,parentIdx=eleIdx/2; isBubbleable(list,childIdx,parentIdx,c); childIdx=parentIdx,parentIdx=childIdx/2){ swap(list,parentIdx-OFFSET,childIdx-OFFSET); } } privatestaticbooleanisBubbleable(Listlist,intchildIdx, intparentIdx,Comparatorc){ returnchildIdx>OFFSET&&c.compare( list.get(parentIdx-OFFSET),list.get(childIdx-OFFSET))<0; } privatestaticvoidbubbleRoot(Listlist, intend,Comparatorc){ for(intparentIdx=0+OFFSET, childIdx=idxFromChilds(list,parentIdx,end,c); childIdx0; parentIdx=childIdx, childIdx=idxFromChilds(list,parentIdx,end,c)){ swap(list,parentIdx-OFFSET,childIdx-OFFSET); } } privatestaticintidxFromChilds(Listlist, intparentIdx,intend,Comparatorc){ intchildIdx=parentIdx*2; returnisRightLeafSuitable(list,childIdx,end,c)? childIdx+1:childIdx; } privatestaticbooleanisRightLeafSuitable(Listlist, intchildIdx,intend,Comparatorc){ returnchildIdx0; } publicstaticvoidmain(String[]args){ Listlist= newArrayList<>(Arrays.asList(10,9,1,2,5,3,8,7,12,11)); heapSort(list); out.println(list); heapSort(list,Sort::descending); out.println(list); } } defascending(a,b):returna-b defdescending(a,b):return-ascending(a,b) __OFFSET=1 defheapSort(xs,comp=ascending): ifnotxs: return[] else: heapped=heapTree([],xs,comp) returnselectFromHeap(heapped,[],comp) defheapTree(heapped,xs,comp): ifnotxs: returnheapped else: returnheapTree(bubbleLeaf(heapped,xs[0],comp),xs[1:],comp) defbubbleLeaf(heapped,child,comp): ifnotheapped: return[child] else: parentIdx=(len(heapped)+1)//2 ifcomp(heapped[parentIdx-__OFFSET],child)<0: heappedChilds=(heapped[parentIdx-__OFFSET+1:]+ [heapped[parentIdx-__OFFSET]]) heappedParents=heapped[0:parentIdx-__OFFSET] returnbubbleLeaf(heappedParents,child,comp)+heappedChilds else: returnheapped+[child] defselectFromHeap(heapped,sorted,comp): iflen(heapped)==1: returnheapped+sorted else: rootSorted=[heapped[0]]+sorted unheapped=[heapped[-1]]+heapped[1:-1] leftHeapped=bubbleRoot(unheapped,1,0,comp) returnselectFromHeap(leftHeapped,rootSorted,comp) defbubbleRoot(unheapped,parentIdx,heappedLen,comp): childLIdx=(parentIdx*2)-heappedLen iflen(unheapped)==1orchildLIdx>len(unheapped): returnunheapped else: childIdx=idxFromChilds(childLIdx,unheapped,comp) ifcomp(unheapped[childIdx-__OFFSET],unheapped[0])>0: heapped=([unheapped[childIdx-__OFFSET]]+ unheapped[1:childIdx-__OFFSET]) rightUnheapped=([unheapped[0]]+ unheapped[childIdx+1-__OFFSET:]) returnheapped+bubbleRoot(rightUnheapped, heappedLen+childIdx, heappedLen+childIdx-1,comp) else: returnunheapped defidxFromChilds(childLIdx,unheapped,comp): return(childLIdx+1ifchildLIdx0 elsechildLIdx) list=[10,9,1,2,5,3,8,7,12,11] print(heapSort(list)) print(heapSort(list,descending)) objectSort{ privatevalOFFSET=1 defheap[T](xs:List[T],compare:(T,T)=>Boolean):List[T]={ if(xs.isEmpty)Nil else{ valheapped=heapTree(Nil,xs,compare) selectFromHeap(heapped,Nil,compare) } } privatedefheapTree[T](heapped:List[T],xs:List[T], compare:(T,T)=>Boolean):List[T]={ if(xs.isEmpty)heapped else{ heapTree(bubbleLeaf(heapped,xs(0),compare),xs.tail,compare) } } privatedefbubbleLeaf[T](heapped:List[T],child:T, compare:(T,T)=>Boolean):List[T]={ if(heapped.isEmpty)List(child) else{ valparentIdx=(heapped.size+1)/2 if(compare(child,heapped(parentIdx-OFFSET))){ valheappedChilds= heapped.slice(parentIdx-OFFSET+1,heapped.size) ++List(heapped(parentIdx-OFFSET)) valheappedParents=heapped.slice(0,parentIdx-OFFSET) bubbleLeaf(heappedParents,child,compare)++heappedChilds } elseheapped++List(child) } } privatedefselectFromHeap[T](heapped:List[T],sorted:List[T], compare:(T,T)=>Boolean):List[T]={ if(heapped.size==1)heapped++sorted else{ valrootSorted=heapped.head::sorted valunheapped=heapped.last:: heapped.slice(1,heapped.size-1) valleftHeapped=bubbleRoot(unheapped,1,0,compare) selectFromHeap(leftHeapped,rootSorted,compare) } } privatedefbubbleRoot[T](unheapped:List[T],parentIdx:Int, heappedLen:Int,compare:(T,T)=>Boolean):List[T]={ valchildLIdx=(parentIdx*2)-heappedLen if(unheapped.size==1||childLIdx>unheapped.size)unheapped else{ valchildIdx=idxFromChilds(childLIdx,unheapped,compare) if(compare(unheapped(childIdx-OFFSET),unheapped.head)){ valheapped=unheapped(childIdx-OFFSET):: unheapped.slice(1,childIdx-OFFSET) valrightUnheapped=unheapped.head:: unheapped.slice(childIdx+1-OFFSET,unheapped.size) heapped++bubbleRoot(rightUnheapped,heappedLen+childIdx, heappedLen+childIdx-1,compare) } elseunheapped } } privatedefidxFromChilds[T](childLIdx:Int, unheapped:List[T],compare:(T,T)=>Boolean)={ if(childLIdx_)) println(Sort.heap[Int](list,_<_ classsort>(a,b){a-b} @@descending=->(a,b){-@@ascending.call(a,b)} defself.ascending;@@ascendingend defself.descending;@@descendingend OFFSET=1 defself.heap(xs,comp) ifxs.empty? [] else heapped=heapTree([],xs,comp) selectFromHeap(heapped,[],comp) end end defself.heapTree(heapped,xs,comp) ifxs.empty? heapped else heapTree(bubbleLeaf(heapped,xs[0],comp),xs[1..-1],comp) end end private_class_method:heapTree defself.bubbleLeaf(heapped,child,comp) ifheapped.empty? [child] else parentIdx=(heapped.size+1)/2 ifcomp.call(heapped[parentIdx-OFFSET],child)<0 heappedChilds=(heapped[parentIdx-OFFSET+1..-1]+ [heapped[parentIdx-OFFSET]]) heappedParents=heapped[0...parentIdx-OFFSET] bubbleLeaf(heappedParents,child,comp)+heappedChilds else heapped+[child] end end end private_class_method:bubbleLeaf defself.selectFromHeap(heapped,sorted,comp) ifheapped.size==1 heapped+sorted else rootSorted=[heapped[0]]+sorted unheapped=[heapped.last]+heapped[1...-1] leftHeapped=bubbleRoot(unheapped,1,0,comp) selectFromHeap(leftHeapped,rootSorted,comp) end end private_class_method:selectFromHeap defself.bubbleRoot(unheapped,parentIdx,heappedLen,comp) childLIdx=(parentIdx*2)-heappedLen ifunheapped.size==1orchildLIdx>unheapped.size unheapped else childIdx=idxFromChilds(childLIdx,unheapped,comp) ifcomp.call(unheapped[childIdx-OFFSET],unheapped[0])>0 heapped=([unheapped[childIdx-OFFSET]]+ unheapped[1...childIdx-OFFSET]) rightUnheapped=([unheapped[0]]+ unheapped[childIdx+1-OFFSET..-1]) heapped+bubbleRoot(rightUnheapped, heappedLen+childIdx, heappedLen+childIdx-1,comp) else unheapped end end end private_class_method:bubbleRoot defself.idxFromChilds(childLIdx,unheapped,comp) (childLIdx0)? childLIdx+1:childLIdx end private_class_method:idxFromChilds end list=[10,9,1,2,5,3,8,7,12,11] print(Sort.heap(list,Sort.ascending).to_s+"\n") print(Sort.heap(list,Sort.descending).to_s+"\n") functionascending(a,b){returna-b;} functiondescending(a,b){return-ascending(a,b);} varheapSort=function(){ functionswap(list,i,j){ varele=list[i]; list[i]=list[j]; list[j]=ele; } varOFFSET=1; functionsort(list,c){ heapTree(list,c); selectFromHeap(list,c); } functionheapTree(list,c){ for(vari=1,end=list.length+1;iOFFSET;end--){ swap(list,1-OFFSET,end-OFFSET); bubbleRoot(list,end,c); } } functionbubbleLeaf(list,eleIdx,c){ for(varchildIdx=eleIdx,parentIdx=parseInt(eleIdx/2); isBubbleable(list,childIdx,parentIdx,c); childIdx=parentIdx,parentIdx=parseInt(childIdx/2)){ swap(list,parentIdx-OFFSET,childIdx-OFFSET); } } functionisBubbleable(list,childIdx,parentIdx,c){ returnchildIdx>OFFSET&&c( list[parentIdx-OFFSET],list[childIdx-OFFSET])<0; } functionbubbleRoot(list,end,c){ for(varparentIdx=0+OFFSET, childIdx=idxFromChilds(list,parentIdx,end,c); childIdx0; parentIdx=childIdx, childIdx=idxFromChilds(list,parentIdx,end,c)){ swap(list,parentIdx-OFFSET,childIdx-OFFSET); } } functionidxFromChilds(list,parentIdx,end,c){ varchildIdx=parentIdx*2; returnisRightLeafSuitable(list,childIdx,end,c)? childIdx+1:childIdx; } functionisRightLeafSuitable(list,childIdx,end,c){ returnchildIdx0; } returnsort; }(); varlist=[10,9,1,2,5,3,8,7,12,11]; heapSort(list,ascending); print(list); heapSort(list,descending); print(list); ascendingab=a-b descendingab=-ascendingab slicefromtoxs=take(to-from)(dropfromxs) tailFromfromxs=slicefrom(lengthxs)xs initUntiluntilxs=slice0untilxs offset=1 heapSortxscomp= ifxs==[]then[] else letheapped=heapTree[]xscomp inselectFromHeapheapped[]comp heapTreeheappedxscomp= ifxs==[] thenheapped elseheapTree(bubbleLeafheapped(headxs)comp)(tailxs)comp bubbleLeafheappedchildcomp= ifheapped==[]then[child] else letparentIdx=(lengthheapped+1)`div`2 in if(comp(heapped!!(parentIdx-offset))child)<0then letheappedChilds= (tailFrom(parentIdx-offset+1)heapped)++ [heapped!!(parentIdx-offset)] heappedParents=initUntil(parentIdx-offset)heapped in(bubbleLeafheappedParentschildcomp)++heappedChilds else heapped++[child] selectFromHeapheappedsortedcomp= if(lengthheapped==1)thenheapped++sorted else letrootSorted=(headheapped):sorted unheapped=(lastheapped):(init$tailheapped) leftHeapped=bubbleRootunheapped10comp inselectFromHeapleftHeappedrootSortedcomp bubbleRootunheappedparentIdxheappedLencomp= if(lengthunheapped==1)||(childLIdx>lengthunheapped) thenunheapped else letchildIdx=idxFromChildschildLIdxunheappedcomp in ifcomp(unheapped!!(childIdx-offset))(headunheapped)>0 then letheapped=(unheapped!!(childIdx-offset)): (slice1(childIdx-offset)unheapped) rightUnheapped= (headunheapped): (tailFrom(childIdx+1-offset)unheapped) inheapped++ (bubbleRootrightUnheapped(heappedLen+childIdx) (heappedLen+childIdx-1)comp) elseunheapped wherechildLIdx=(parentIdx*2)-heappedLen idxFromChildschildLIdxunheappedcomp= ifchildLIdx0 thenchildLIdx+1 elsechildLIdx main=sequence[print$heapSortlistascending, print$heapSortlistdescending] wherelist=[10,9,1,2,5,3,8,7,12,11]



請為這篇文章評分?