数据结构之排序算法(一)-堆排序
生活随笔
收集整理的這篇文章主要介紹了
数据结构之排序算法(一)-堆排序
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
繼上篇文章講到堆的實現之后http://blog.csdn.net/tuke_tuke/article/details/50357939,下面可以使用堆來實現堆排序。
在堆的基礎上實現堆排序的思路很簡單:(這里使用最小堆,當然最大堆也可以)
? ?最小堆MinHeap就是最小的數在堆的根元素的位置。首先把一組數建堆,然后再不斷的移除堆的根元素,由于每次移除的根元素都是現有堆的最小元素,故可得到所有元素的從小到大的順序。
MinHeap.java
package heapsort;import java.util.ArrayList;public class MinHeap <E extends Comparable>{ private ArrayList<E> list=new ArrayList<E>();//用數組實現堆public MinHeap(){}public MinHeap(E[] objects){for(int i=0;i<objects.length;i++){add(objects[i]);}} public void add(E newObject){//添加一個元素list.add(newObject);int currentIndex=list.size()-1;while(currentIndex>0){int parentIndex=(currentIndex-1)/2;//找到該結點的父結點if(list.get(currentIndex).compareTo(list.get(parentIndex))<0){//如果當前結點的值小于父結點就交換位置E temp=list.get(currentIndex);list.set(currentIndex, list.get(parentIndex));list.set(parentIndex, temp); }elsebreak;currentIndex=parentIndex;} }public E remove(){//刪除并返回根結點if(list.size()==0) return null;E removeObject=list.get(0);list.set(0, list.get(list.size()-1));//把最后一個結點放在根結點的位置list.remove(list.size()-1);int currentIndex=0;while(currentIndex<list.size()){int leftChildIndex=2*currentIndex+1;int rightChildIndex=2*currentIndex+2;//左右孩子結點的坐標if(leftChildIndex>=list.size())break;//比較左右孩子的值,使maxIndex指向值小的結點int minIndex=leftChildIndex;if(rightChildIndex<list.size()){if(list.get(minIndex).compareTo(list.get(rightChildIndex))>0){minIndex=rightChildIndex;}}//如果當前結點的值大于其左右孩子中的大的值,就交換兩個結點if(list.get(currentIndex).compareTo(list.get(minIndex))>0){E temp=list.get(minIndex);list.set(minIndex, list.get(currentIndex));list.set(currentIndex, temp);currentIndex=minIndex;}elsebreak;}return removeObject; }public int getSize(){return list.size();} } HeapSort.java
package heapsort;import java.awt.List;public class HeapSort {public static<E extends Comparable> void heapSort(E[] list){MinHeap<E> heap=new MinHeap<E>();//最小堆類//先把數組添加到堆中,建堆for(int i=0;i<list.length;i++){heap.add(list[i]);}//然后在一次刪除根結點,根結點總是最值/*for(int i=list.length-1;i>=0;i--){//利用最大堆排序list[i]=heap.remove(); }*/for(int i=0;i<=list.length-1;i++){//利用最小堆排序,不斷的移除堆的根元素list[i]=heap.remove(); //每次都會調整堆 }}public static void main(String[] args) {// TODO Auto-generated method stubInteger[] list={22,43,11,24,27,21,54,35,23};System.out.println("堆排序前的數組是:");for(int i=0;i<list.length;i++){System.out.print(list[i]+" ");}heapSort(list);//堆排序System.out.println();System.out.println("堆排序后的數組是:");for(int i=0;i<list.length;i++){System.out.print(list[i]+" ");}}}
算法分析:
? ?運行時間主要是消耗在初始構建堆和在重建堆時的反復篩選上。
在構建堆的過程中,因為我們是完全二叉樹從最下層最右邊的非終端結點開始構建,將它與其孩子進行比較和若有必要的互換,對于每個非終端結點來說,其實最多進行兩次比較和互換操作,因此整個構建堆的時間復雜度為O(n)。
在正式排序時,第i次取堆頂記錄重建堆需要用O(logi)的時間(完全二叉樹的某個結點到根結點的距離為log2i+1),并且需要取n-1次堆頂記錄,因此,重建堆的時間復雜度為O(nlogn)。
總體來說,堆排序的時間復雜度為O(nlogn)。由于堆排序對原始記錄的排序狀態并不敏感,因此它無論是最好、最壞和平均時間復雜度均為O(nlogn)
總結
以上是生活随笔為你收集整理的数据结构之排序算法(一)-堆排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构-二叉树和二叉查找树
- 下一篇: 数据结构值排序算法(三)-快速排序