java排序算法(冒泡,插入,选择,快速,堆,归并,希尔,基数)

import java.util.Arrays;
import java.util.LinkedList;


/**
 * 
 * 
 * 各种排序: 冒泡,插入,选择,快速,堆,归并,希尔,基数
 */
public class Sorts {
	//1. 冒泡:
	//时间复杂度:n(n-1)/2=O(n^2)
	//1. 第一次把最大的放后面
	//2. 把最大的放后面。。。
	//3. 。。。
	static void BubbleSort(int arr[], int start, int end){
		int len = end - start + 1;
		for(int i = 0; i < len; i++){
			for(int j = 0; j < len - i - 1; j++){
				if(arr[j] > arr[j + 1]){
					int tmp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = tmp;
				}
			}
		}
	}
	//2. 插入排序:
	//时间复杂度:最好O(n), 最坏O(n^2)
	//评价:稍快于冒泡
	//1.先认为第一个最小
	//2.第二个与第一个比较,如果第二个小,则交换。
	//3.第N次循环的时候,前面N个元素都是排好序的。
	static void standInsertSort(int arr[], int start, int end){
		int len = end - start + 1;
		for(int i = 1; i < len; i++){
			int tmp = arr[i];
			int j = -1;
			for(j = i - 1 ; j >= 0; j--){
				if(arr[j] > tmp){
					arr[j+1] = arr[j];
				}else{
					break;
				}
			}
			arr[j+1] = tmp;
		}
	}
	//3. 选择排序
	//时间复杂度:同插入排序,可能比冒泡快点,比插入慢点。
	//评价:无
	//1.找到最小的放在最前面
	//2.找到最小的放在第二位
	//3. ... ...
	static void selectSort(int arr[], int start, int end){
		int len = end - start + 1;
		int min = Integer.MAX_VALUE;
		for(int i = 0; i < len - 1; i++){//给arr按位赋值
			int mark = -1;
			for(int j = i; j < len; j++){//找出最小值
				if(arr[j] < min){
					min = arr[j];
					mark = j;
				}
			}
			arr[mark] = arr[i];
			arr[i] = min;//找到最小值
			min = Integer.MAX_VALUE;//重置min
		}
	}
	
	//4. 快速排序
	//时间复杂度:n(logn)
	//评价:比插入排序快
	static void quickSort(int arr[], int start, int end){
		int sStore = start, eStore = end;
		int len = end - start + 1;
		switch(len){
			case 0:
			case 1:
				return;
			case 2:
				arr[0] = arr[0]^arr[1];
				arr[1] = arr[0]^arr[1];
				arr[0] = arr[0]^arr[1];
				return;
		}
		int mark = arr[start];//需要从右面找一个比mark小的值来填充arr[start]
		//System.out.println("Sorts.quickSort() 时间复杂度为 " + len);
		while(start < end){
			while(arr[end] > mark && end > start){
				end--;
			}
			if(end > start){//找到了,则填充arr[start]
				arr[start] = arr[end];
				start++;//start值确定所以,加一。
			}else{//没有找到,这表示start右面的值全都比mark大了。。此时end == start,循环结束
				
			}
			//此时,arr[start]与arr[end]重复了。。需要从左面找一个比mark大的值来填充arr[end]。
			//方法同上
			while(arr[start] < mark&& end > start){
				start++;
			}
			if(end > start){//找到了,填充arr[end]
				arr[end] = arr[start];
				end--;//end值确定,所以减一。
			}else{//没找到,这表示start左面的值全部比mark小了。。
				
			}
		}
		
		//我们知道,每次按照算法计算一次循环之后,数组中都会出现2个相同的值,所以会缺少一个值,这个值就是mark。
		//因为我们从开头把mark提取之后,就没有把它赋回。
		//所以mark应该放哪呢?
		//因为循环结束只有一种可能,就是(start == end)这意味着什么?
		//意味着:start的左面全部比mark小,end的右面全部比mark大。
		//结果明确了吧。把start赋值成mark就恰好达到我们的要求了。
		arr[start] = mark;
		//至此,数组从0-->start的值,全部比start+1 --> end的值要小了。
		//果断递归
		quickSort(arr, sStore, start - 1);//之前写的不是start-1而是start,结果数据若超过65536会栈溢出。
		quickSort(arr, start+1, eStore);
	}
	//5. 堆排序
	//时间复杂度: n/2 + log(n) + log(n-1) + ...+ log1 ==> n(logn)
	static class heapSort{
		private static void swapArrayElement(int array[], int a, int b){
			if(a == b){
				return;
			}
			array[a] = array[a]^array[b];
			array[b] = array[a]^array[b];
			array[a] = array[a]^array[b];
		}
		private static void judgeHeap(int array[], int i, int len){//调整第i个元素为顶的3元大根堆
			int lChild = 2*i + 1;
			int rChild = 2*i + 2;
			if(lChild > len - 1){
				return;
			}
			if(rChild > len - 1){
				if(array[i] < array[lChild]){
					swapArrayElement(array, i, lChild);
				}
				return;
			}
			int max = i;
			if(array[i] < array[lChild]){
				max = lChild;
			}


			if(array[max] < array[rChild]){
				max = rChild;
			}
			if(max != i){
				swapArrayElement(array, max, i);
				judgeHeap(array, max, len);
			}
		}


		static void hSort(int array[], int from, int to) {
			int len = to - from + 1;
			if (len <= 1) {
				return;
			}
			for (int i = len - 1; i >= 0; i--) {//创建初始堆,从最后一个元素开始作为3元堆顶,
												//使其满足堆定义。这样总能把最大元素推到堆顶。
				judgeHeap(array, i, len);
			}
			for(int i = 0; i < len; i++){
				swapArrayElement(array, 0, len - i - 1);//把最大元素放到末尾。
				judgeHeap(array, 0, len - i - 1);//改变的元素可能不符合堆定义。
			}
		}
	}
	//6.归并
	//分治法
	//>如果问题缩小到一定规模可以很容易求解
	//>可以分解成相同的子问题
	//>问题可由子问题的结果合并而得出。(是否使用分治法,完全取决于此点)
	//>各个子问题之间是相互独立的,不包含公共子问题。(动态规划)
	
	//晕了 搞了好久。。这样是不是占用空间太大了阿。。fak
	
	//时间复杂度:n(logn)
	
	static class MergerSort{
		static void printArr(String tag, int arr[], int f, int to){}
		static int[] merge(int arr1[],int arr2[]){
			int l1 = arr1.length;
			int l2 = arr2.length;
			int re[] = new int[l1 + l2];
			int o = 0;
			int t = 0;
			for(int i = 0; i < re.length; i++){
				if(o > l1 - 1){
					re[i] = arr2[t];
					t++;
				}else if(t > l2 - 1){
					re[i] = arr1[o];
					o++;
				}else if(arr1[o] < arr2[t]){
					re[i] = arr1[o];
					o++;
				}else{
					re[i] = arr2[t];
					t++;
				}
			}
			return re;
		}
		static int [] mSort(int []arr, int from, int to){
			int len = to - from + 1;
			if(len == 1){
				return new int[]{arr[from]};
			}
			int mid = (from + to) / 2;
			int[] l = mSort(arr, from, mid);
			int[] r = mSort(arr, mid+1, to);
			return merge(l, r);
		}
	}
	
	// 7.希尔
	static void shellSort(int arr[], int from, int to) {
		int len = to - from + 1;
		if (len == 1) {
			return;
		}
		int d = len % 2 == 0 ? len / 2 : len / 2 + 1;
		while (d >= 1) {
			//下面是一个典型插入排序
			for (int i = d; i < len; i++) {
				int tmp = arr[i];
				int j = -1;
				for (j = i - d; j >= 0; j -= d) {
					if (arr[j] > tmp) {
						arr[j + d] = arr[j];
					} else {
						break;// !!
					}
				}
				arr[j + d] = tmp;// 因为最后一位
			}
			d = d % 2 == 0 || d == 1 ? d / 2 : d / 2 + 1;
		}
	}
	//8.基数
	//基数排序很厉害哇
	//时间复杂度: 2 * n * (最大的数的位数)
	static class RadixSort{
		private static class list{
			LinkedList<Integer> l = new LinkedList<Integer>();
			LinkedList<Integer> getL(){
				return l;
			}
			public list(){
				
			}
			void add(int value){
				l.add(value);
			}
			void clear(){
				l.clear();
			}
			int size(){
				return l.size();
			}
		}
		private static class lists{
			private static list []l = new list[10];
			static void reset(){//重置所有的桶
				for(int i = 0; i < l.length; i++){
					if(l[i] != null && l[i].size()!=0){
						l[i].clear();
					}
					if(l[i] == null){
						l[i] = new list();
					}
				}
			}
			static list get(int index){//得到一个桶
				return l[index];
			}
			static void set(int index, int value){//往某个桶中添加数据
				l[index].add(value);
			}
		}
		
		static void rSort(int arr[], int from, int to){
			int len  = to - from + 1;
			if(len <= 1){
				return;
			}
			int times = 1;
			int currentTime = 0;
			int label = 1;
			while(currentTime < times){
				label = 10 * label;
				lists.reset();
				boolean timesMark = false;
				for(int i = 0; i < len; i++){//进桶
					int invalue = (arr[i]%label)/(label/10);//计算当前数放到哪个桶
					lists.set(invalue, arr[i]);
					if(!timesMark && arr[i]/label >= 1){//支持数值最大值为(9,9999,9999)否则。label超过Integer.MAX_VALUE会出错。
						times++;
						timesMark = true;
					}
				}
				int i = 0;
				for(int j = 0; j < 10; j++){
					for(Integer value: lists.get(j).getL()){
						arr[i] = value;
						i++;
					}
				}
				currentTime++;
			}
		}
	}
	public static void main(String[] args) {//测试
		int arr[] = {8, 91, 411, 2222, 33333, 744444, 6555555, 56666666,1010101010,1010101011, 15554444, 212112211,};
		//int arr[] = {81, 19, 44, 222, 323, 712, 56, 523, 15, 12,};
		System.out.println("Sorts.main() before");
		System.out.println(Arrays.toString(arr));
		
		//BubbleSort(arr, 0, arr.length - 1);
		//arr = insertSort(arr, 0, arr.length - 1);
		//arr = selectSort(arr, 0, arr.length - 1);
		//quickSort(arr, 0, arr.length - 1);
//		heapSort.hSort(arr, 0, arr.length-1);
		//arr = MergerSort.mSort(arr, 0, arr.length-1);
		//standInsertSort(arr, 0, arr.length-1);
		//selectSort(arr, 0, arr.length-1);
//		shellSort(arr, 0, arr.length-1);
		RadixSort.rSort(arr, 0, arr.length-1);
		System.out.println("Sorts.main() after");
		System.out.println(Arrays.toString(arr));
		
		int x[] = new int[8000000];
		for(int i = 0; i < x.length; i++){
			x[i] = (int)(Math.random()* (Integer.MAX_VALUE/100));
		}
		long currentTime = System.currentTimeMillis();
		System.out.println("Sorts.main() startTime = " + currentTime);
		//selectSort(x, 0, x.length - 1);
		//quickSort(x, 0, x.length - 1);
		//heapSort.hSort(x, 0, x.length - 1);
//		MergerSort.mSort(x, 0, x.length-1);
//		shellSort(x, 0, x.length-1);
		RadixSort.rSort(x, 0, x.length-1);//发现不如快速排序快。。估计是用了ArrayList的缘故。。
		System.out.println("Sorts.main() consumeTime = " + (System.currentTimeMillis() - currentTime));
		
	}
}

你可能感兴趣的:(java排序算法(冒泡,插入,选择,快速,堆,归并,希尔,基数))