排序算法整理__参考MoreWindows

参考http://blog.csdn.net/column/details/algorithm-easyword.html下载的

MoreWindows白话经典算法之七大排序第2版,

下图中“类别”有误,别管它

排序算法整理__参考MoreWindows

快速排序对100000长的数组居然java.lang.StackOverflowError!!!

整理到归并算法:

package p1;

import java.util.Date;

public class SortAlgorithm {
	//----------------------------------------heap sort-----------------------------------------
	//原始的Fix up, 类似于基于后移的插入排序
	public static void minHeapFixup(int [] heap, int i){
		int temp = heap[i];
		int p = (i - 1)/2;
		while(i > 0){
			if(heap[p] <= temp)
				break;
			
			heap[i] = heap[p];//将比temp大的元素往下移
			
			i = p;
			p = (i - 1)/2;
		}
		heap[i] = temp;
		
	}
	//基于交换的Fix up
	public static void minHeapFixup1(int [] heap, int i){//把i的元素向上调整, heap已经是一个堆了
		int p;//pos的父节点
		for(p = (i-1)/2 ; p>=0 && heap[p] > heap[i] ; i=p, p=(i-1)/2){
			int temp = heap[p];
			heap[p] = heap[i];
			heap[i] = temp;
		}
	}
	
	// Fix down
	public static void minHeapFixdown(int [] heap, int i, int n){//把i元素向下调整,总节点数为n
		int temp = heap[i];
		int c = 2 * i + 1;//child 初始为 left child
		while(c < n){
			if((c+1) < n && heap[c] > heap[c+1]){//right child更小,则取right child, 别忘了(c+1) < n
				c++;
			}
			
			if(heap[c] >= temp)
				break;
			
			heap[i] = heap[c];
			
			i = c;
			c = 2 * i + 1;
		}
		heap[i] = temp;
	}
	
	//将数组建成Heap: 从最后一个节点的父亲开始( (n-1 - 1)/2 = n/2 - 1)直到根节点, 依次Fixdown
	
	//堆排序: minHeap排序后是降序, NOT稳定, 空间复杂度o(1),因为没用到递归
	public static void heapSort(int [] arr, int n){
		int i;
		//1 先把arr 转换为heap: 从最后一个节点的父亲开始直到根节点,Fixdown
		for(i = n/2 - 1; i>=0; i--){
			minHeapFixdown(arr, i, n);
		}
		
		
		//2 依次交换堆首和堆尾, Fixdown
		for(i = n-1; i>0; i--){
			int temp = arr[i];
			arr[i] = arr[0];
			arr[0] = temp;
			minHeapFixdown(arr, 0, i);
		}
		
	}
	
	
	//----------------------------------------quick sort-----------------------------------------
	//快速排序, NOT稳定的 , 空间复杂度???
	public static void quickSort(int [] arr, int n){
		
		//原始快速排序 调用Divid
		//quickSortDivid(arr, 0, n-1);
		
		//简化的
		quickSort1(arr,0,n-1);
		
	}
	
	//快速排序 简化版
	public static void quickSort1(int [] arr, int f, int t){
		
		if(f<t){
			int pivot = arr[f], l=f, r=t;

			while(l < r){
				while(l<r && arr[r] >= pivot){//注意是 >= 不是>
					r--;
				}	
				if(l<r) {
					arr[l++] = arr[r]; 				
				}
				
				while(l<r && arr[l] < pivot){ 
					l++;
				}	
				if(l<r) {
					arr[r--] = arr[l];
				}
			}//循环结束时l==r
			
			arr[l] = pivot;//别忘了最终放pivot
			
			quickSort1(arr,f,l-1);
			quickSort1(arr,l+1,t);
			
		}		
		
	}	
	
	//原始快速排序__子函数分治
	public static void quickSortDivid(int [] arr, int f, int t){
		if(f < t){
			int pos = quickSortAdjust(arr, f, t);//pos位置上的元素已是在其最终位置上了
			quickSortDivid(arr, f, pos-1);
			quickSortDivid(arr, pos+1, t);
		}
	}
	//原始快速排序__子函数,将首元素调整到 最终位置
	public static int quickSortAdjust(int [] arr, int l, int r){//left, right
		int pivot = arr[l];

		while(l < r){
			while(l<r && arr[r] >= pivot){//如果右边找不到比pivot小的值,那么right就会递减至等于left,注意如果是 && arr[r] > pivot会导致{3, 4,  1, 3, 2}出错
				r--;
			}	
			if(l<r) {
				arr[l++] = arr[r];//将比pivot大的值移到left				
			}
			
			while(l<r && arr[l] < pivot){//注意不是 && arr[r] <= pivot!!!
				l++;
			}	
			if(l<r) {
				arr[r--] = arr[l];
			}
		}//循环结束时l==r
		
		arr[l] = pivot;//别忘了最终放pivot
		
		return l;
	}
	
	
	//----------------------------------------merge sort-----------------------------------------
	//归并排序, 稳定的, 对于second test data 性能很好,空间复杂度O(N)
	public static void mergeSort(int [] arr, int n){
		int [] tempArr = new int [n];
		int first =0, last = n-1;
		mergeSortDivid(arr, first, last, tempArr);
		
	}
	//归并的子函数__递归分解
	public static void mergeSortDivid(int [] a, int first, int last, int [] tempArr){
		if(first < last){//若从 first到last长度为1则什么都不做
			int mid = (first + last)/2;
			mergeSortDivid(a, first, mid, tempArr);
			mergeSortDivid(a, mid+1, last, tempArr);
			
			mergeSortMerge(a, first, mid, last, tempArr);
		}
	}
	//归并的子函数__归并
	public static void mergeSortMerge(int [] a, int first, int mid, int last, int [] tempArr){
		int l1 = mid, l2 = last;//两个有序数组的末尾
		int i = first, j = mid+1, k = 0;
		
		while(i<=l1 && j<=l2){//不是i<l1 && j<l2以防从first到last长度为2的情况 
			if(a[i] < a[j]){
				tempArr[k++] = a[i++];				
			}else{
				tempArr[k++] = a[j++];
			}			
		}
		
		while(i<=l1){
			tempArr[k++] = a[i++];
		}
		while(j<=l2){
			tempArr[k++] = a[j++];
		}
		
		//再把 排序后的元素拷回原数组
		for(i=0; i<k; i++){
			a[first + i] = tempArr[i];//注意不是a[i] = tempArr[i]
		}
		
		
	}
	
	//----------------------------------------select sort-----------------------------------------
	//选择排序,选择是NOT稳定的,如3 3 2, 对于first test data真糟糕, 即使最好情况下仍然是O(n的平方)
	public static void selectSort(int [] arr, int n){
		int i, j;
		for(i=0; i<n; i++){
			int minPos = i;
			//每次从i到n-1中找到最小值,将其与i进行互换
			for(j=i+1; j<n; j++){				
				if(arr[j] < arr[minPos]){
					minPos = j;
				}
			}
			if(minPos > i){
				int temp = arr[i];
				arr[i] = arr[minPos];
				arr[minPos] = temp;
			}
			
		}
	}
	
	
	//----------------------------------------shell sort-----------------------------------------
	//原始的希尔排序    希尔是 NOT稳定的
	public static void shellSort(int [] arr, int n){
		int i,j,k, gap;
		
		for(gap = n/2;	gap>0;	gap/=2){//步长每次减半
			for(i = 0; i<gap; i++){//从0到gap-1共有gap个分组 
				//每个分组内进行insert sort
				for(j = gap; j<n; j+=gap){
					if(arr[j-gap] > arr[j]){
						int temp = arr[j];
						for(k = j-gap; k>=0 && arr[k] > temp; k-=gap){//k>=0要写在&&之前
							arr[k+gap] = arr[k];
						}
						arr[k+gap] = temp;
						
					}	
				}
				
			}			
		}
		
		
	}
	//代码简洁后的希尔排序,对于second test data性能出奇得好!
	public static void shellSort2(int [] arr, int n){
		int i, j, gap;
		for(gap = n/2; gap>0; gap /=2){
			for(j = gap; j<n; j++){//从gap到n-1共n-gap个元素
				if(arr[j-gap] > arr[j]){	
					//改用exchange实现的insert sort
					for(i = j-gap; i>=0 && arr[i]>arr[i+gap]; i-=gap){
						int temp = arr[i];
						arr[i] = arr[i+gap];
						arr[i+gap] = temp;
					}
				}
					
					
			}
			
		}
	}
	
	//----------------------------------------insert sort-----------------------------------------
	//插入排序_后移, 插入是稳定的
	public static void insertSortBackWhileSearch(int [] arr, int n){
		int i,j;
		for(i=1; i<n; i++){
			if(arr[i] < arr[i-1]){//1 发现 逆序 
				int temp = arr[i];//插入值
				//2 搜索 插入位置, 与此同时, 后移一位,腾出位置; 因为要后移,所以是从i-1到 0倒着搜索 
				for(j=i-1; j>=0 && arr[j]>temp; j--){
					arr[j+1] = arr[j];
				}
				//3 搜索和后移都结束了,插入
				arr[j+1] = temp;
			}
		}
		
	}
	//插入排序_交换
	public static void insertSortExchange(int [] arr, int n){
		int i,j;
		for(i=1; i<n; i++){
			//每一次i循环结束,使得从0到i都是顺序的,下一次循环判断从0到i+1是否存在逆序,如果逆序就交换 ,类似于冒泡!
			for(j=i-1; j>=0 && arr[j]>arr[j+1]; j--){
				int temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
		}
		
	}
	
	//----------------------------------------bubble sort-----------------------------------------
	//冒泡排序_使用了两个优化技术 , 冒泡是稳定的 
	public static void bubbleSort(int [] arr, int n){
		int i,j;
		boolean flag = true;
		int k = n-1;
		int pos = n-1;
		while(k>0){
			flag = false;
			for(j = 0; j < k; j++){
				if(arr[j] > arr[j+1]){
					
					int temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
					
					pos = j;//优化2
					flag = true;//优化1
					
				}	
			}
			
			k = pos;//
			
			if(!flag)
				break;
		}
		
		
	} 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		long t1,t2;
		
		t1 = (new Date()).getTime();
		int [] arr = new int[100000];
		int i,j;

		//1st test data
		for(i=0;i<100;i++){
			arr[i] = 100-i;
		}
		for(i=100;i<100000;i++){
			arr[i] = i+100;
			
		}		
		//2nd test data
//		for(i=0;i<100;i++){
//			arr[i] = 100-i;
//		}
//		for(i=100;i<100000;i++){
//			//arr[i] = i+100;
//			arr[i] = 100000-i;
//		}
		//3rd test data for quick sort
//		for(i=0;i<6000;i++){
//			arr[i] = 6000-i;
//		}
//		for(i=2000;i<4000;i++){
//			if(i%2==0){
//				arr[i] = arr[i+1];
//			}
//		}
		
		
		System.out.println("before--------");
		
		//for 1st and 2nd test data
		for(i=0;i<100;i++){
			System.out.print(arr[i]+" ");
		}
		System.out.println();
		for(i=99901;i<100000;i++){
			System.out.print(arr[i]+" ");
		}
		System.out.println();
		
		
		//for 3rd test data 
//		for(i=0;i<100;i++){
//			System.out.print(arr[i]+" ");
//		}
//		System.out.println();		
//		for(i=5900;i<6000;i++){
//			System.out.print(arr[i]+" ");
//		}
//		System.out.println();
		
		
		
//		bubbleSort(arr,100000);//10  			//22062
//		insertSortBackWhileSearch(arr,100000);//10     //17328
//		insertSortExchange(arr,100000);//11		//29830
//		shellSort(arr,100000);//16   //9114
//		shellSort2(arr,100000);//15		//25
//		selectSort(arr,100000);//14940
//		mergeSort(arr,100000);//25    //26
//		quickSort(arr,6000);//    41   //quickSort(arr,6395)就会java.lang.StackOverflowError
		heapSort(arr,100000);//	24		//23
		
		//---------temp test for quick sort 
//		int [] bb = {3, 4,  1, 3, 2};
//		quickSortAdjust(bb, 0, 4);
//		for(int b:bb){
//			System.out.println("--"+b);
//		}
//
		t2 = new Date().getTime();
		System.out.println("time used:"+(t2-t1));
		
		//---------temp test for heap sort
//		int [] bb = {3, 4,  1, 3, 2};
//		heapSort(bb,5);
//		for(int b:bb){
//			System.out.println("--"+b);
//		}
		
		
		
		
		System.out.println("after--------");
		//for 1st and 2nd test data
		for(i=0;i<100;i++){
			System.out.print(arr[i]+" ");
		}
		System.out.println();
		for(i=99901;i<100000;i++){
			System.out.print(arr[i]+" ");
		}
		System.out.println();
		
		//for 3rd test data 
//		for(i=0;i<100;i++){
//			System.out.print(arr[i]+" ");
//		}
//		System.out.println();		
//		for(i=5900;i<6000;i++){
//			System.out.print(arr[i]+" ");
//		}
//		System.out.println();
		
	}

}


你可能感兴趣的:(算法)