O(nlgn)排序-歸併排序-快速排序及優化

1.歸併排序---等分數組-遞歸合併

/**
	 * 遞歸使用歸併排序,對arr[l...r]的範圍進行排序
	 *
	 * @param arr
	 * @param l
	 * @param r
	 */
	private static void mergeSortOwn(int[] arr, int l, int r) {
//		if (l >= r) {
//			return;
//		}
		if(r-l<=15){
			insertionSort(arr,l,r);
			return;
		}

		int mid = (l + r) / 2;
		mergeSortOwn(arr, l, mid);
		mergeSortOwn(arr, mid + 1, r);
		if (arr[mid] > arr[mid + 1]) {
			merge(arr, l, mid, r);
		}
	}

	private static void insertionSort(int[] arr, int l, int r) {
		for(int i=l+1;i<=r;i++){
			//尋找元素arr[i]合適的插入位置
			int tmp = arr[i];
			int j; //j保存元素tmp應該插入的位置
			for(j=i;j>l && arr[j-1]>tmp;j--){
				arr[j] = arr[j-1];
			}
			arr[j] = tmp;
		}
	}


	private static void merge(int[] arr, int l, int mid, int r) {

		int[] aux = Arrays.copyOfRange(arr, l, r+1);

		// 初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1
		int i = l, j = mid+1;
		for( int k = l ; k <= r; k ++ ){

			if( i > mid ){  // 如果左半部分元素已經全部處理完畢
				arr[k] = aux[j-l];
				j ++;
			}
			else if( j > r ){   // 如果右半部分元素已經全部處理完畢
				arr[k] = aux[i-l];
				i ++;
			}
			else if( aux[i-l]<aux[j-l] ){  // 左半部分所指元素 < 右半部分所指元素
				arr[k] = aux[i-l];
				i ++;
			}
			else{  // 左半部分所指元素 >= 右半部分所指元素
				arr[k] = aux[j-l];
				j ++;
			}
		}
	}

2.快速排序--找到標定點(隨機選擇標定值-優化),將左邊右邊分別進行排序

public static void quickSort(int arr[],int l,int r){
		if(l>=r){
			return;
		}
		int p = optimizePartition(arr,l,r);
		quickSort(arr,l,p-1);
		quickSort(arr,p+1,r);
	}

	/**
	 * 對arr[l...r]部分進行partion操作
	 * @param arr
	 * @param l
	 * @param r
	 * @return  p  使得arr[l,p-1]<arr[p];arr[p+1,r]>p
	 */
	private static int partition(int[] arr, int l, int r) {
		//起始位置的值
		int v = arr[l];
		int j = l;
		//arr[l+1...j]<v;arr[j+1...i)>v
		for(int i=l+1;i<=r;i++){
			if(arr[i]<v){
				//交換j+1的元素和當前考察的元素
				j++;
				SortTestHelper.swap(arr,j,i);
			}
		}
		SortTestHelper.swap(arr,l,j);
		return j;
	}


	/**
	 * 優化  起始值爲隨機數
	 * 對arr[l...r]部分進行partion操作
	 * @param arr
	 * @param l
	 * @param r
	 * @return  p  使得arr[l,p-1]<arr[p];arr[p+1,r]>p
	 */
	private static int optimizePartition(int[] arr, int l, int r) {
		//起始位置的值
		int random = new Random().nextInt(r-l+1)+l;
		SortTestHelper.swap(arr,l,random);
		int v = arr[l];
		int j = l;
		//arr[l+1...j]<v;arr[j+1...i)>v
		for(int i=l+1;i<=r;i++){
			if(arr[i]<v){
				//交換j+1的元素和當前考察的元素
				j++;
				SortTestHelper.swap(arr,j,i);
			}
		}
		SortTestHelper.swap(arr,l,j);
		return j;
	}

3.兩路快速排序

 

4.3路快速排序---常用

public static void quickSort(int arr[],int l,int r){
		if(l>=r){
			return;
		}
		int random = new Random().nextInt(r-l+1)+l;
		SortTestHelper.swap(arr,l,random);
		int v = arr[l];
		int lt = l; //arr[l+1...lt]<v
		int gt = r+1; //arr[gt...r]>v
		int i = l+1; //arr[lt+1...i)=v
		while(i<gt){
			if(arr[i]<v){
				SortTestHelper.swap(arr,i,lt+1);
				lt++;
				i++;
			}else if(arr[i]>v){
				SortTestHelper.swap(arr,i,gt-1);
				gt--;
			}else{
				i++;
			}
		}
		SortTestHelper.swap(arr,l,lt);
		quickSort(arr,l,lt-1);
		quickSort(arr,gt,r);
	}

 

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