1. 程式人生 > >手寫常用演算法(插入,希爾,快排),java實現

手寫常用演算法(插入,希爾,快排),java實現

在排序演算法的複習當中,有些演算法還是比較難理解的,好在以前打下的基礎,再次學習輕鬆很多,下面記錄下手寫常用的排序演算法。

直接插入排序的效能分析

時間複雜度:  1. 最好情況:O(n)  2. 平均情況:O(n^2)  3. 最壞情況:O(n^2)  空間複雜度:O(1)  穩定性:穩定(相同元素的相對位置不會改變)

希爾排序(第一個突破O(n^2)的排序演算法)的效能分析:

會根據增量的不同而不同,一般來說:  時間複雜度:  1. 最好情況:O(n^1.3)  2. 最壞情況:O(n^2)  空間複雜度:O(1)  穩定性:不穩定(相同元素的相對位置會改變)

快速排序的效能分析:

時間複雜度:  1. 最好情況:O(nlog2(n))  2. 平均情況:O(nlog2(n))  3. 最壞情況:O(n^2)  空間複雜度:O(log2(n))  穩定性:不穩定(相同元素的相對位置會改變)

public class Sorts {
	/**
	 * 插入排序
	 * @param a 
	 */
	public static void InsertSort(int[] a) {
		if (a==null || a.length<=0) { //排空
			System.out.println("陣列為空");
			return ;
		}

		int temp=0; //暫存要插入的元素
		int j=0;
		for (int i = 1,len=a.length; i <len; i++) {  //遍歷陣列
			temp=a[i];
			j=i-1;   
			for (; j>=0 && a[j]>temp;j--) {  //如果a[i]之前的數比要插入的temp大,該數後移。注意j>=0
				a[j+1]=a[j];
			}
			a[j+1]=temp; //當迴圈結束,也就是temp比a[j]大或者相等,或者最小時(j=-1),插入到a[j]後面
		}
	}

	/**
	 * 希爾排序
	 * @param a
	 */
	public static void shellSort(int[] a) {
		if (a==null || a.length<=0) { //排空
			System.out.println("陣列為空");
			return ;
		}
		int temp=0; //暫存要插入的元素
		int len=a.length;
		int j=0;
		for (int d = len/2; d>0; d/=2) { //取d/2來分割排序記錄
			for (int i = d; i<len; i++) {//從d開始,迴圈到結束
				temp=a[i];
				j=i-d;  //取第前d個元素作為比較
				for (; j>=0 && a[j]>temp; j-=d) { //連續以d為分割比較
					a[j+d]=a[j];
				}
				a[j+d]=temp; //插入
			}
		}
	}

	/**
	 * 氣泡排序改進版
	 * @param a
	 */
	public static void bubbleSort(int[] a) {
		int exchange=a.length-1;
		int bound=0;
		while (exchange!=0) {
			bound=exchange;
			exchange=0;
			for (int i = 0; i < bound; i++) {
				if (a[i]>a[i+1]) {
					a[i]=a[i]+a[i+1];
					a[i+1]=a[i]-a[i+1];
					a[i]=a[i]-a[i+1];
					exchange=i;
				}
			}
		}
	}

	/**
	 * 快速排序演算法
	 * @param a
	 * @param first
	 * @param end
	 */
	public static void quickSort(int[] a,int first,int end) {
		if (first<end) {
			int pivot=partition(a, first, end); //開始對區間進行排序,返回最終的軸值
			quickSort(a, first, pivot-1);       //遞迴排序左區間,軸值不需要參與排序
			quickSort(a, pivot+1, end);         //遞迴排序右區間
		}
	}
	/**
	 * 快速排序一次劃分演算法
	 * @param a
	 * @param first
	 * @param end
	 * @return
	 */
	public static int partition(int a[],int first,int end) {
		int i=first,j=end;
		while (i<j) {
			while (i<j && a[j]>=a[i]) { //從右側開始掃描,直到找到右側的比左側小的數,然後交換位置
				j--;
			}
			if (i<j) {  //交換位置
				a[i]=a[i]+a[j];
				a[j]=a[i]-a[j];
				a[i]=a[i]-a[j];
				i++;
			}

			while (i<j && a[j]>=a[i]) { //從左側開始掃描,直到找到右側的比左側小的數,然後交換位置
				i++;
			}
			if (i<j) { //交換位置
				a[i]=a[i]+a[j];
				a[j]=a[i]-a[j];
				a[i]=a[i]-a[j];
				j--;
			}
		}
		return i;  //軸值記錄的最終位置
	}


	public static void main(String[] args) {
		int[] a = {3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
		InsertSort(a);
		System.out.print("直接插入排序:");
		for(int i = 0; i < a.length; i++) {
			System.out.print(a[i] + " ");
		}

		System.out.println();
		int[] b={3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
		shellSort(b);
		System.out.print("希爾排序:");
		for(int i = 0; i < b.length; i++) {
			System.out.print(b[i] + " ");
		}

		System.out.println();
		int[] c={3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
		bubbleSort(c);
		System.out.print("氣泡排序改進版:");
		for(int i = 0; i < c.length; i++) {
			System.out.print(c[i] + " ");
		}

		System.out.println();
		int[] d={3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
		quickSort(d, 0, d.length-1);		
		System.out.print("快速排序:");
		for(int i = 0; i < d.length; i++) {
			System.out.print(d[i] + " ");
		}
	}
}