排序算法思想及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;
	}

}


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