算法學習----各種排序算法的實現和對比2


算法學習----各種排序算法的實現和對比2


1 簡單排序算法

簡單排序算法主要有:冒泡排序法、選擇排序法、插入排序法。詳細內容見:算法學習----各種排序算法的實現和對比1

2  中級的排序算法:歸併排序

這裏所謂的中級排序算法是指在算法的時間複雜度上比較優秀的算法,那就是基於遞歸思想的的歸併排序。歸併排序在速度上比簡單排序快的多,時間複雜度爲O(N*logN),但空間上需要一個大小等於原來數組的工作空間。
      歸併算法的中心是歸併兩個已經有序的數組。歸併兩個有序數組A和B,就生第三個數組C。
歸併排序思想的核心是把一個數組劃分成兩半,排序每一半,然後用歸併方法把數組的兩半歸併成一個有序的數組。主要還要用到遞歸來完成。
算法的執行過程如圖所示:


程序實現如下:
package intdata.InsertionSort;

public class Meger {
	
	static int[] a = {2,1,5,34,12,9,64,123,32,432,13};
	static int[] workSpace = new int[11];
	
	public static void main(String[] args){
		regMegerSort(a,0,10);
		
		
		for(int i = 0;i< a.length; i++){
			System.out.println(a[i]);
		}
		
	}
	
	private static void meger(int[] workSpace,int lower,int mid,int upper) {
		
		int j=0;
		int lowerBound = lower;
		int mider = mid -1;
		int n = upper-lower+1;
		
		while(lower <= mider && mid <= upper){
			if(a[lower]<a[mid]) {
				workSpace[j++]=a[lower++];
			}
			else {
				workSpace[j++]=a[mid++];
			}
			
			while(lower <= mid){
				workSpace[j++] = a[lower++];
			}
			
			while(mid <= upper){
				workSpace[j++] = a[mid++];
			}
			
			for(j=0;j<n;j++){
				a[lowerBound+j] = workSpace[j];
			}
			
		}	
		
	}
	
	private static void regMegerSort(int[] workSpace, int lowerBound,int upperBound){
		
		if(lowerBound == upperBound) 
			return;
		else {
			int mid = (lowerBound + upperBound)/2;
			regMegerSort(workSpace,lowerBound,mid);
			
			regMegerSort(workSpace,mid+1,upperBound);
			
			meger(workSpace, lowerBound,mid+1, upperBound);
		}
	}
}
程序還是比較簡單,易於實現的。

小結一下:
1 歸井兩個有序數組意思是創建第三個數組,這個數組按順序存儲從這兩個有序數組中取到的所有數據項。
2 在歸併排序中,一個大數組的單個數據項的子數組歸井爲兩個數據項的子數組,然後兩個數據項的子數組歸併爲4 個數據項的子數組,
如此下去直到所有的數組數據項有序。
3 歸井排序需要O(N*logN) 時間。
4 歸併排序需要一個大小等於原來數組的工作空間。



3 高級排序


這裏主要的兩個高級的排序算法:希爾排序和快速排序。最後還有基數排序,雖然不常用但很有趣的排序算法。
這兩種排序算法都比簡單排序算法快得多:希爾排序大約需要O(N* (logN)2)時間,快速排序需要O(N*logN)時間。這兩種排序算法都和歸併排序不同,不需要大量的輔助存儲空間。希爾排序幾乎和歸併排序一樣容易實現,而快速排序是所有通用排序算法中最快的一種排序算法。

希爾排序:

  1. 希爾排序是基於插入排序,但是增加了一個新的特性,大大地提高了插入排序的執行效率。
  2. 希爾排序對於多達幾千個數據項的,中等大小規模的數組排序表現良好。
  3. 希爾排序不像快速排序和其他時間複雜度爲O(N*logN)的排序算法那麼快,因此對非常大的文件排序,它不是最優選擇。
  4. 但是,希爾排序比選擇排序和插入排序這種時間複雜度爲O(N2 ) 的排序算法還是要快得多,並且它非常容易實現。
  5. 希爾排序算法的代碼既短又簡單。

這裏值得說的是:希爾排序在最壞情況下的執行效率和在平均情況下的執行效率相比沒有差很多。(和快速排序相比,除非採取了預防措施,否則快速排序在最壞情況下的執行效率會非常差。〉一些專家,提倡差不多任何排序工作在開始時都可以使用希爾排序算法,若在實際中證明它不夠快,再改換成諸如快速排序這樣更高級的排序算法。



希爾排序是基於插入排序的,但插入排序的複製次數太多了。
下面先看看簡單插入排序的代碼:
<span style="font-size:18px;">public static void insertionSort(int[] a){ //a 爲數字對象的一個引用。引用=地址
		int i,j,key,n=a.length; //i爲數組下標;j爲循環次數,與i有聯繫;key爲容器。
		for(j=1;j<n;j++){
			key=a[j];//將新的數據(牌)給容器
			i=j-1;//i爲手中原有的牌數,a[i]爲手中原有的(牌)
			while(i>=0 && a[i] > key ){//從小到大
				a[i+1]=a[i]; //將原數往後放一位
				i--; //循環,直到減爲0。			
			}
			a[i+1]=key;//把新的數據插入正確的標號。	
		}
	}</span>
插入排序的思想是將新的要插入的值和原來數組中的值一個一個做比較,然後在一個一個複製移動,直到插入合適的位置。最壞的情況下,要從頭到尾都複製移動一次。時間複製度要O(N*N),最好的情況下,就是數組基本有序的情況下,只需要移動2個左右的數就可以排行序,這時的時間複雜度爲O(N)。這就是爲什麼說,插入排序對基本有序的數組排序,效率很高的原因。
那麼假設,如果能以某種方式不必一個一個地移動所有中間的數據項(也就是每次移動間隔多個值),就能把較小的數據快速的移動到左邊。,那麼這個算法的效率就大大的提高了。
基於此,希爾排序採用了N增量排序的方式進行。希爾排序通過加入插入排序中元素之間的間隔,並在這些有間隔的元素中進行插入排序,從而使數據項能大跨度地移動。當這些數據項排過一趟序後,希爾排序算法減小數據項的間隔再進行排序,依此進行下去。進行這些排序時數據項之間的間隔被稱爲增量,並且習慣上用字母h 來表示。

看下圖是一個完整的以4爲增量的排序過程:




這樣是不是已經基本有序了。剩下就看插入算法的了。
直接看下面希爾排序算法的代碼:

<span style="font-size:18px;">package intdata.InsertionSort;

public class SheelSortApp {
	
	public static void main(String[] args){
		long[] a = {5,1,9,3,46,90,19,100,11,65};

		shellSort(a);
		
		for(int i = 0; i<a.length; i++){
			System.out.print(a[i]+"  ");
		}
	}

	private static void shellSort(long[] a) {
		int inner,outer;
		long temp;
		
		int h=1;
		while(h<a.length /3)
			h = 3*h+1;
		
		while(h>0){
			
			for(outer = h;outer < a.length; outer++){
				temp = a[outer];
				inner = outer;
				
				while(inner > h-1 && a[inner -h] > temp){
					a[inner] = a[inner-h];
					inner -= h;
				}
				a[inner] = temp;
			}//end for
			
			h = (h-1)/3;
		}//end while
	}//end shellSort
} //end class
</span>

程序結果:1  3  5  9  11  19  46  65  90  100  
這就是傳說中的希爾排序算法,是不是也很簡單。注意看程序中的變量h,他就是增量排序中的增量,它的取值不唯一。這裏的取值是算法書中推薦的值的取法。


快速排序:

  • 1. 快速排序是基於劃分思想的。
  • 2.快速排序算法是對自身的遞歸調用。
  • 3.要理解快速排序算法必須先理解劃分算法。

由於快速排序是基於劃分思想的,那先來看看劃分思想。
劃分數據就是把數據分爲兩組,使所有關鍵字大於特定值的數據項在一組,使所有關鍵字小於特定值的數據項在另組。這個特殊值就是叫樞紐或中樞。它和希爾排序中的增量h一樣,其值的選取對算法的運行效率有影響。

1  劃分算法:

劃分算法由兩個指針開始工作,兩個指針分別指向數組的兩頭。(這裏使用"指針"這個詞是指示數組數據項的,而不是C++ 中所說的指針。)在左邊的指針: leftPtr 向右移動,而在右邊的指針: rightPtr 向左移動。


算法思想:當leftPtr 遇到比樞紐小的數據項時,它繼續右移,因爲這個數據項的位置已經處在數組的正確一邊了。
但是,當遇到比樞紐大的數據項時,它就停下來。類似的,當rightPtr 遇到大於樞紐的數據項時,它繼續左移,
但是當發現比樞紐小的數據項時,它也停下來。當第一個循環在發現比樞紐大的數據項時退出:第二個循環在發現比樞紐小的數據項時退出。當這兩個循環都退出之後, leftPtr 和rightPtr 都指着在數組的錯誤一方位置上的數據項,所以交換這兩個數據項。交換之後,兩個指針繼續移動,繼續以上操作。當兩個指針最終相遇時,結束劃分,完成劃分了。
下面看看程序代碼;
package intdata.InsertionSort;

public class ArrayPartitiom {
	private long[] theArray;
	private int nElems;

	
	public ArrayPartitiom(int max){
		theArray = new long[max];
		nElems = 0;
	}
	
	public void insert(long value){
		theArray[nElems++] = value;
	}
	
	public int patitionIt(int left, int right,long pivot){
		int leftPtr = left - 1; //左指針,在左邊數據的的前一位
		int rightPtr = right + 1; //右指針,在右邊數據的的後一位
		while(true){
			while(leftPtr < right && theArray[++leftPtr] < pivot); //find bigger item
			while(rightPtr > left && theArray[--rightPtr] > pivot); //find smaller item
			if(leftPtr >= rightPtr)
				break;
			else 
				swap(leftPtr,rightPtr);
		} //end while
		return leftPtr;
	} //end patitionIt method

	private void swap(int leftPtr, int rightPtr) {
		long temp;
		temp = theArray[leftPtr];
		theArray[leftPtr] = theArray[rightPtr];
		theArray[rightPtr] = temp;
		
	} //end swap method
	
	public void display(){
		for(int i =0;i< nElems; i++){
			System.out.print(theArray[i]+" ");
		}
		System.out.println();
	}// end display method
	
	public int size(){
		return nElems;
	}//end size method

}
下面是劃分算法的測試程序:
package intdata.InsertionSort;

public class PartitionApp {

    
	public static void main(String[] args) {
		int maxSize = 16;
		ArrayPartitiom arr = new ArrayPartitiom(maxSize);
		
		for(int i = 0;i < maxSize; i++){
			long n = (int) (java.lang.Math.random()*199);
			arr.insert(n);
		}
		
		arr.display();
		
		long pivot = 99;
		int size = arr.size();
		
		System.out.println("pivot = "+pivot);
		
		int partDex = arr.patitionIt(0, size-1, pivot);
		
		System.out.println("patitoin is at index "+partDex);
		
		arr.display();
		
	} //end main method

}
程序的運行結果如下:
102 185 59 142 8 49 150 39 119 1 179 97 16 60 48 151 
pivot = 99  (這個是中樞)
patitoin is at index 9
48 60 59 16 8 49 97 39 1 119 179 150 142 185 102 151 

快速排序算法:

毫無疑問,快速排序是最流行的排序算法,因爲有充足的理由,在大多數情況下,快速排序都是最快的,執行時間爲O(N*logN) 級。(這只是對內部排序或者說隨機存儲器內的排序而言,對於在磁盤文件中的數據進行的排序,其他的排序算法可能更好。)
必須注意的是:
快速排序算法本質上通過把一個數組劃分爲兩個子數組,然後遞歸地調用自身爲每一個子數組進行快速排序來實現的。但是,對這個基本的設計還需要進行一些加工。算法還必須要選擇樞紐以及對小的劃分區域進行排序。


快速排序算法有三個基本的步驟:
  • 1.把數組或者子數組劃分成左邊(較小的關鍵字)的一組和右邊(較大的關鍵字)的一組。
  • 2. 調用自身對左邊的一組進行排序。
  • 3. 再次調用自身對右邊的一組進行排序。
經過一次劃分之後,所有在左邊子數組的數據項都小於在右邊子數組的數據。只要對左邊子數組和右邊子數組分別進行排序,整個數組就是有序的了。通過遞歸的調用排序算法自身就可以對子數組進行排序了。

看下面的程序:
package intdata.InsertionSort;

public class QuickSort1 {
	
	private static long[] theArray = new long[16];
	
	public static void main(String[] args) {
		
		
		for(int i = 0;i < theArray.length; i++){
			theArray[i] = (int) (java.lang.Math.random()*99);
		}
		
		display();
		recQuickSort(0,theArray.length-1);//theArray.length-1 是最後一個數
		display();
	}

	private static void display() {
		for(int i =0;i< theArray.length; i++){
			System.out.print(theArray[i]+" ");
		}
		System.out.println();
	}//end display method
	
	private static void recQuickSort(int left,int right){
		if(right-left <= 0)
			return;
		else{
			long pivot = theArray[right];
			int partition = partition(left,right,pivot);
			
			recQuickSort(left, partition-1);
			recQuickSort(partition+1, right);
			
		} //end else
	}//  end recQuickSort
	
	private static int partition(int left, int right,long pivot){
		int leftPtr = left - 1; //左指針,在左邊數據的的前一位
		int rightPtr = right; //右指針,右邊數據
		while(true){
			
			while(theArray[++leftPtr] < pivot); //find bigger item
			while(rightPtr > 0 && theArray[--rightPtr] > pivot); //find smaller item
			
			if(leftPtr >= rightPtr)
				break;
			else 
				swap(leftPtr,rightPtr);
		} //end while
		swap(leftPtr,right);
		return leftPtr;
	} //end patitionIt method

	private static void swap(int leftPtr, int rightPtr) {
		long temp;
		temp = theArray[leftPtr];
		theArray[leftPtr] = theArray[rightPtr];
		theArray[rightPtr] = temp;
		
	} //end swap method

}

程序結果:
55 69 94 38 48 36 62 76 97 16 37 23 82 61 26 92 
16 23 26 36 37 38 48 55 61 62 69 76 82 92 94 97 

2 選擇樞紐:
劃分方法應該使用什麼樣的樞紐呢?以下是一些相關的思想:
  1. • 應該選擇具體的一個數據項的關鍵字的值作爲樞紐:稱這個數據項爲pivot ( 樞紐) 。
  2. • 可以選擇任意一個數據項作爲樞紐。爲了簡便,我們假設總是選擇待劃分的子數組最右端的數據項作爲樞紐。
  3. • 劃分完成之後,如果樞紐被插入到左右子數組之間的分界處,那麼樞紐就落在排序之後的最終位置上了。
下圖是交換樞紐的位置示意圖:

但是上面的樞紐選擇方案,在已經有序的數據進行排序時,時間複雜多會變成O(N*N),爲了解決這個問題,提出了另一種樞紐選擇方案:三項數據取中
如下圖所示:

看如下代碼:

package intdata.InsertionSort;

public class QuickSort2 {

	/**
	 * 三項數據取中
	 * 解決了對已經有序的數組快速排序需要O(N*N)的問題
	 */
	private static long[] theArray = new long[16];
	
	public static void main(String[] args) {
		
		for(int i = 0;i < theArray.length; i++){
			theArray[i] = (int) (java.lang.Math.random()*99);
		}
		
		display();
		recQuickSort(0,theArray.length-1);//theArray.length-1 是最後一個數
		display();
	}
	
	private static void display() {
		for(int i =0;i< theArray.length; i++){
			System.out.print(theArray[i]+" ");
		}
		System.out.println();
	}//end display method
	
	private static void recQuickSort(int left,int right){
		
		int size = right-left+1;
		
		if(size <= 3){ //處理小劃問題,cutoff = 3
			manualSort(left,right); //簡單的人工排序
		}
		else{
			long median = medianOf3(left,right);//取三項數據的中間值爲劃分樞紐
			
			int partition = partition(left,right,median);
			
			recQuickSort(left, partition-1);
			recQuickSort(partition+1, right);
			
		} //end else
	}//  end recQuickSort
	
	private static long medianOf3(int left, int right) {
		
		int center = (left+right)/2;
		if(theArray[left] > theArray[center])
			swap(left,center);
		
		if(theArray[left] > theArray[right])
			swap(left,right);
		
		if(theArray[center] > theArray[right])
			swap(center,right); //三項數據排序取中完成
		
		swap(center,right-1); //put pivot on right;
		return theArray[right-1]; //return median value
		
	}//end medianOf3 method

	private static void manualSort(int left, int right) {
		int size = right-left+1;
		if(size <= 1) 
			return;
		if(size == 2){ //2 sort left and right
			if(theArray[left] > theArray[right])
				swap(left,right);
			return;
		}
		else { //sort is 3   //right = right -1;
			if(theArray[left] > theArray[right -1])
				swap(left,right-1);
			
			if(theArray[left] > theArray[right])
				swap(left,right);
			
			if(theArray[right -1] > theArray[right])
				swap(right-1,right); 
		}
		
	}//end manual method

	private static int partition(int left, int right,long pivot){
		int leftPtr = left; //左指針,左邊數據
		int rightPtr = right -1; //右指針,右邊數的後一位
		while(true){
			
			while(theArray[++leftPtr] < pivot); //find bigger item
			while(theArray[--rightPtr] > pivot); //find smaller item
			
			if(leftPtr >= rightPtr)
				break;
			else 
				swap(leftPtr,rightPtr);
		} //end while
		swap(leftPtr,right-1); //restore pivot
		return leftPtr;        //return pivot location
	} //end patitionIt method

	private static void swap(int leftPtr, int rightPtr) {
		long temp;
		temp = theArray[leftPtr];
		theArray[leftPtr] = theArray[rightPtr];
		theArray[rightPtr] = temp;
		
	} //end swap method

}
程序結果:
95 28 55 3 0 23 85 57 39 32 36 58 23 61 88 88 
0 3 23 23 28 32 36 39 55 57 58 61 85 88 88 95 


3 處理小劃分:

如果使用三數據項取中劃分方法,則必須要遵循快速排序算法不能執行三個或者少於三個數據
項的劃分的規則。在這種情況下,數字3 被稱爲切割點(cutoff)。

處理小劃分的另一個選擇是使用插入排序。當使用插入排序的時候,不用限制以3 爲切割點
(cutoff) 。可以把界限定爲10 、20 或者其他任何數。試驗不同切割點的值以找到最好的執行效率。

看下面的程序:
package intdata.InsertionSort;

public class QuickSort3 {

	/**
	 * 對於小劃分的小於10項的數據,用插入算法排序
	 */
	private static long[] theArray = new long[16];
	
	public static void main(String[] args) {
		
		for(int i = 0;i < theArray.length; i++){
			theArray[i] = (int) (java.lang.Math.random()*99);
		}
		
		display();
		recQuickSort(0,theArray.length-1);//theArray.length-1 是最後一個數
		display();
	}
	
	private static void display() {
		for(int i =0;i< theArray.length; i++){
			System.out.print(theArray[i]+" ");
		}
		System.out.println();
	}//end display method
	
	private static void recQuickSort(int left,int right){
		
		int size = right-left+1;
		
		if(size < 10){ //處理小劃問題,cutoff = 10
			insertionSort(left,right); //插入算法
		}
		
		else{
			long median = medianOf3(left,right);//取三項數據的中間值爲劃分樞紐
			
			int partition = partition(left,right,median);
			
			recQuickSort(left, partition-1);
			recQuickSort(partition+1, right);
			
		} //end else
	}//  end recQuickSort
	
	private static void insertionSort(int left, int right) {
		int inner,outer;
		long temp;
		for(outer = left+1;outer <= right;outer++){
			temp = theArray[outer];
			inner = outer;
			
			while(inner > left && theArray[inner-1] >= temp){
				theArray[inner] = theArray[inner -1];
				--inner; //inner--;
			}
			
			theArray[inner] = temp;
		}
			
			
	}

	private static long medianOf3(int left, int right) {
		
		int center = (left+right)/2;
		if(theArray[left] > theArray[center])
			swap(left,center);
		
		if(theArray[left] > theArray[right])
			swap(left,right);
		
		if(theArray[center] > theArray[right])
			swap(center,right); //三項數據排序取中完成
		
		swap(center,right-1); //put pivot on right;
		return theArray[right-1]; //return median value
		
	}//end medianOf3 method

	private static void manualSort(int left, int right) {
		int size = right-left+1;
		if(size <= 1) 
			return;
		if(size == 2){ //2 sort left and right
			if(theArray[left] > theArray[right])
				swap(left,right);
			return;
		}
		else { //sort is 3   //right = right -1;
			if(theArray[left] > theArray[right -1])
				swap(left,right-1);
			
			if(theArray[left] > theArray[right])
				swap(left,right);
			
			if(theArray[right -1] > theArray[right])
				swap(right-1,right); 
		}
		
	}//end manual method

	private static int partition(int left, int right,long pivot){
		int leftPtr = left; //左指針,左邊數據
		int rightPtr = right -1; //右指針,右邊數的後一位
		while(true){
			
			while(theArray[++leftPtr] < pivot); //find bigger item
			while(theArray[--rightPtr] > pivot); //find smaller item
			
			if(leftPtr >= rightPtr)
				break;
			else 
				swap(leftPtr,rightPtr);
		} //end while
		swap(leftPtr,right-1); //restore pivot
		return leftPtr;        //return pivot location
	} //end patitionIt method

	private static void swap(int leftPtr, int rightPtr) {
		long temp;
		temp = theArray[leftPtr];
		theArray[leftPtr] = theArray[rightPtr];
		theArray[rightPtr] = temp;
		
	} //end swap method

}
程序結果:
81 15 62 41 44 90 51 53 45 65 87 98 69 52 48 12 
12 15 41 44 45 48 51 52 53 62 65 69 81 87 90 98 


基數排序:

基數排序算法

這裏的基數排序都是普通的以10 爲基數的運算,因爲這樣更易於講解。
但是,以2 爲基數實現的基數排序也是非常高效的,這可以利用計算機高速的位運算。這裏只考察基數排序,而不考察與基數排序相似但更復雜一些的基數交換排序。基數這個詞的意思是一個數字系統的基。10 是十進制系統的基數, 2 是二進制系統的基數。

算法思路:

排序包括分別檢測關鍵字的每一個數字,檢測從個位(最低有效位)開始。

1.根據數據項個位上的值,把所有的數據項分爲10 組。
2. 然後對這10 組數據項重新排列:把所有關鍵字是以0 結尾的數據項排在最前面,然後是關鍵字結尾是1 的數據項,照此順序直到以9 結尾的數據。這個步驟被稱爲第一趟子排序。
3. 在第二趟子排序中,再次把所有的數據項分爲10 組,但是這一次是根據數據項十位上的值來分組的。這次分組不能改變先前的排序順序。也就是說,第二趟排序之後,從每一組數據項的內部來看,數據項的順序保持不變:這趟子排序必須是穩定的。
4. 然後再把10 組數據項重新合併,排在最前面的是十位上爲0 的數據項,然後是10 位爲1 的數據,如此排序直到十位上爲9 的數據。
5. 對剩餘位重複這個過程。

終於完了:
小結一下:參考書:數據結構(java版)。
  • 希爾排序將增量應用到插入排序,然後逐漸縮小增量。
  •  n-增量排序表示每隔n 個元素進行排序。
  • 被稱爲間隔序列或者間距序列的數列決定了希爾排序的排序間隔。
  • 常用的間隔序列是由遞歸表達式h=3*h+1 生成的, h 的初始值爲10
  • 一個容納了1000 個數據的數組,對它進行希爾排序可以是間隔序列爲364 ,121 , 40,13 , 4 ,最後是1 的增量排序。
  • 希爾排序很難分析,但是它運行的時間複雜度大約爲O(N* (logN內。這比時間複雜度爲O(N2 )的排序算法要快,例如 比插入排序快,但是比時間複雜度爲O(N*logN) 的算法慢,例如比快速排序慢。

  • 劃分數組就是把數組分爲兩個子數組,在一組中所有的數據項關鍵字的值都小於指定的
    值,而在另一組中所有數據項關鍵字的值則大於或等於給定值。
  •  樞紐是在劃分的過程中確定數據項應該放在哪一組的值。小於樞紐的數據項都放在左邊一組:而大於樞紐的數據項都放在右邊一組。
  •  快速排序劃分一個數組,然後遞歸調用自身,對劃分得到的兩個子數組進行快速排序。
  •  快速排序算法劃分時的樞紐是一個特定數據項關鍵字的值,這個數據項稱爲pivot (樞紐)。
  •  在快速排序的簡單版本中,總是由於數組的最右端的數據項作爲樞紐。

  •  快速排序的簡單版本,對已經有序(或者逆序)的數據項排序的執行效率只有O(N*N)
  •  更高級的快速排序版本中,樞紐是爲"三數據項取中" 劃分。
  •  在快速排序已經對大於切割界限的子數組排完序之後,插入排序也可用於整個的數組。
  •  基數排序的時間複雜度和快速排序相同,只是它需要兩倍的存儲空間。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章