排序算法思想及Java實現

import java.util.Arrays;

/**
 *@author 255166
 *@version Feb 27, 2012 10:39:00 AM
 */
public class SortAlgorithm {

	/**
	 * 對數組的i,j位置的內容交換
	 * @param inputArray
	 * @param i
	 * @param j
	 * @return
	 */
	public static int[] exchangeValue(int[] inputArray, int i, int j) {
		int temp = inputArray[i];
		inputArray[i] = inputArray[j];
		inputArray[j] = temp;
		return inputArray;
	}

	/**
	 * 冒泡排序
	 * 冒泡排序(BubbleSort)的基本概念是:依次比較相鄰的兩個數,將小數放在前面,大數放在後面。即在第一趟:首先比較第1個和第2個數,
	 * 將小數放前,大數放後。然後比較第2個數和第3個數,將小數放前,大數放後,如此繼續,直至比較最後兩個數,將小數放前,大數放後。
	 * 至此第一趟結束,將最大的數放到了最後。在第二趟:仍從第一對數開始比較(因爲可能由於第2個數和第3個數的交換,使得第1個數不再小於第2個數),
	 * 將小數放前,大數放後,一直比較到倒數第二個數(倒數第一的位置上已經是最大的),第二趟結束,在倒數第二的位置上得到一個新的最大數(其實在整個數列中是第二大的數)。
	 * 如此下去,重複以上過程,直至最終完成排序。 
	 * @param inputArray
	 * @return
	 */
	public static int[] BubbleSort(int[] inputArray) {
		for (int i = 0; i < inputArray.length; i++) {

			for (int j = 0; j < inputArray.length - i - 1; j++) {
				if (inputArray[j] > inputArray[j + 1]) {
					exchangeValue(inputArray, j, j + 1);
				}
			}
		}
		return inputArray;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int[] sortInt = { 8, 5, 12, 1, 22, 2, 99, 6, 3, 7, 100, 4, 44, 9 ,88};
		//BubbleSort(sortInt);
		//quickSort(sortInt, 0, sortInt.length - 1);
		//selectionSort(sortInt);
		//insertSort(sortInt);
		shellSort(sortInt);
		System.out.println("Sort ASC:" + Arrays.toString(sortInt));
	}
	
	/**
	 * 希爾排序
	 * 基本思想:
         * 先取一個小於n的整數d1作爲第一個增量,把文件的全部記錄分成d1個組。所有距離爲dl的倍數的記錄放在同一個組中。
	 * 先在各組內進行直接插人排序;然後,取第二個增量d2<d1重複上述的分組和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),
	 * 即所有記錄放在同一組中進行直接插入排序爲止。
	 * @param inputArray
	 */
	public static void shellSort(int[] inputArray){
		//對記錄進行分組
		for(int increment=inputArray.length/2;increment>0;increment/=2){
			//對同一個組的數據進行插入排序
			for(int i=increment;i<inputArray.length;i++){
				int temp=inputArray[i];
				int j=0;
				for(j=i;j>=increment;j-=increment){
					if(temp<inputArray[j-increment]){
						inputArray[j]=inputArray[j-increment];
					}else{
						break;
					}
				}
				inputArray[j]=temp;
			}
		}
	}
	
	/**
	 * 插入排序
	 * 將n個元素的數列分爲已有序和無序兩個部分,如
     * {,{a2,a3,a4,…,an}}
     * {{a1(1),a2(1)},{a3(1),a4(1) …,an(1)}}
     * …
     * {{a1(n-1),a2(n-1) ,…}, {an(n-1)}}
     * 每次處理就是將無序數列的第一個元素與有序數列的元素從後往前逐個進行比較,找出插入位置,將該元素插入到有序數列的合適位置中。
	 * @param inputArray
	 * @return
	 */
	public static int[] insertSort(int[] inputArray){
		
		for (int i = 1; i < inputArray.length; i++) {// i從一開始,因爲第一個數已經是排好序的啦  
			   //將無序數列的第一個元素與有序數列的元素從後往前逐個進行比較
			   for (int j = i; j > 0; j--) {  
			    if (inputArray[j] < inputArray[j - 1]) {  
			     int temp = inputArray[j];  
			     inputArray[j] = inputArray[j - 1];  
			     inputArray[j - 1] = temp;  
			    }  
			   }  
			  }  
		return inputArray;
	}
	
	/**
	 * 選擇排序
	 * n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果:
     * ①初始狀態:無序區爲R[1..n],有序區爲空。
 	 * ②第1趟排序
      * 在無序區R[1..n]中選出關鍵字最小的記錄R[k],將它與無序區的第1個記錄R[1]交換,使R[1..1]和R[2..n]分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
      * ……
      * ③第i趟排序
      * 第i趟排序開始時,當前有序區和無序區分別爲R[1..i-1]和R(1≤i≤n-1)。該趟排序從當前無序區中選出關鍵字最小的記錄 R[k],將它與無序區的第1個記錄R交換,
	 *	使R[1..i]和R分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
      * 這樣,n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果。 
	 * @param inputArray
	 * @return
	 */
	public static int[] selectionSort(int[] inputArray){
		
		for(int i=0;i<inputArray.length;i++){
			int initialIndex=i;
			int initialValue=inputArray[i];
			for(int j=i+1;j<inputArray.length;j++){
				if(inputArray[j]<initialValue){
					initialIndex=j;
					initialValue=inputArray[j];
				}
			}
			int temp=inputArray[i];
			inputArray[i]=initialValue;
			inputArray[initialIndex]=temp;
		}
		
		return inputArray;
	}

	/**
	 * 快速排序
	 * 一趟快速排序的算法是:
     * 1)設置兩個變量I、J,排序開始的時候:I=0,J=N-1;
     * 2)以第一個數組元素作爲關鍵數據,賦值給key,即 key=A[0];
    * 3)從J開始向前搜索,即由後開始向前搜索(J=J-1),找到第一個小於key的值A[J],A[j]與A[i]交換;
    * 4)從I開始向後搜索,即由前開始向後搜索(I=I+1),找到第一個大於key的A[I],A[i]與A[j]交換;
    * 5)重複第3、4、5步,直到 I=J; (3,4步是在程序中沒找到時候j=j-1,i=i+1,直至找到爲止。找到並交換的時候i, j指針位置不變。另外當i=j這過程一定正好是i+或j-完成的最後另循環結束。)
    * 例如:待排序的數組A的值分別是:(初始關鍵數據:key=49) 注意關鍵key永遠不變,永遠是和key進行比較,無論在什麼位子,最後的目的就是把X放在中間,小的放前面大的放後面。
   * A[0] A[1] A[2] A[3] A[4] A[5] A[6]:
	* 49 38 65 97 76 13 27
	* 進行第一次交換後:27 38 65 97 76 13 49
	* ( 按照算法的第三步從後面開始找)
	* 進行第二次交換後:27 38 49 97 76 13 65
	* ( 按照算法的第四步從前面開始找>X的值,65>49,兩者交換,此時:I=3 )
	* 進行第三次交換後:27 38 13 97 76 49 65
	* ( 按照算法的第五步將又一次執行算法的第三步從後開始找
	* 進行第四次交換後:27 38 13 49 76 97 65
	* ( 按照算法的第四步從前面開始找大於X的值,97>49,兩者交換,此時:I=4,J=6 )
	* 此時再執行第三步的時候就發現I=J,從而結束一趟快速排序,那麼經過一趟快速排序之後的結果是:27 38 13 49 76 97 65,即所有大於49的數全部在49的後面,所有小於49的數全部在49的前面。
	 * @param inputArray
	 * @param left
	 * @param right
	 * @return
	 */
	public static int[] quickSort(int[] inputArray, int left, int right) {
		int middleValue = inputArray[left];
		int i = left;
		int j = right;
		//第一趟排序
		while (i < j) {
			if (left < right) {
				while (i < j && inputArray[j] > middleValue) {
					j--;
				}
				if (i < j) {
					int temp = inputArray[i];
					inputArray[i] = inputArray[j];
					inputArray[j] = temp;
				}
			}
			if (left < right) {
				while (i < j && inputArray[i] < middleValue) {
					i++;
				}
				if (i < j) {
					int temp = inputArray[i];
					inputArray[i] = inputArray[j];
					inputArray[j] = temp;
				}
			}
		}
		//遞歸前部分內容
		if(left<j){
			quickSort(inputArray, left, i - 1);
		}  
		//遞歸後部分內容
		 if(right>i){
			 quickSort(inputArray, i + 1, right);
		 }
		return inputArray;
	}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章