Java语言实现九大排序算法(快速、归并、堆、选择、插入、计数、基数、希尔、冒泡)

快速排序:

/*
 * 快速排序:选取flag(这里选第一个数),先从右边开始找到小于它的数,交换,再从左边开始找到大于它的数,交换,
 * 这样它就在合适的位置,并把数组分为两个部分,分别重复上述步骤即可。
 * 时间复杂度:O(nlogn)
 * 稳定性:不稳定
 */
public class QuickSort {
	public static void quickSort(int[] a, int left, int right){
		if(left < right){
			int flag = a[left];
			int i = left;
			int j = right;
			while(true){
				while(a[j] >= flag && j > i){
					j--;
				}
				if(a[j] < flag){
					int tmp = a[j];
					a[j] = a[left];
					a[left] = tmp;
				}
				while(a[i] <= flag && i<j){
					i++;
				}
				if(a[i] > flag){
					int tmp = a[i];
					a[i] = a[j];
					a[j] = tmp;
				}
				if(i >= j){
					break;
				}
			}
			quickSort(a, left, i);
			quickSort(a, i+1, right);
		}
	}
	public static void main(String[] args){
		int[] a = {21,5,23,1,8};
		quickSort(a, 0, a.length-1);
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}

归并排序:

/*
 * 归并排序:利用分治思想,将序列每次折半划分,将划分的序列排序合并
 * http://www.cnblogs.com/jingmoxukong/p/4308823.html
 * 时间复杂度:O(nlogn)
 * 稳定性:稳定
 */
public class MergeSort {
	public static void mergesort(int[] a, int[] tmp, int left, int right){
		if(left < right){
			int mid = (right + left) / 2;		
			mergesort(a, tmp, left, mid);		//左边部分		
			mergesort(a, tmp, mid+1, right);	//右边部分
			sort(a,tmp,left,mid+1,right);		//归并
		}
	}
	public static void sort(int[] a, int[] tmp, int left, int mark, int right){
		int leftend = mark - 1;						//左边的极限
		int numElement = right - left + 1;				//数量
		int len = left;							//tmp数组长度
		while(left <= leftend && mark <= right){
			if(a[left] < a[mark]){
				tmp[len++] = a[left++];
			}else{
				tmp[len++] = a[mark++];
			}
		}	
		while(left <= leftend){
			tmp[len++] = a[left++];
		}
		while(mark <= right){
			tmp[len++] = a[mark++];
		}
		for(int i=0; i<numElement; i++,right--){
			a[right] = tmp[right];
		}
	}
	public static void main(String[] args){
		int[] a = {21,5,23,1,8};
		int[] tmp = new int[a.length];
		mergesort(a,tmp, 0, a.length-1);
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}

堆排序:

/*
 * 1. 构建一个最大堆。对于给定的包含有n个元素的数组A[n],构建一个最大堆从最底下的子树开始,
 *    调整这个堆结构,使其满足最大堆的特性。当为了满足最大堆特性时,堆结构发生变化,此时递归调整对应的子树。 
 * 2. 堆排序算法,每次取出该最大堆的根节点(因为根节点是最大的),同时,取最末尾的叶子节点来作为根节点,
 *    从此根节点开始调整堆,使其满足最大堆的特性。 
 * 3. 重复上一步操作,直到堆的大小由n个元素降到2个。 
 * 详解:http://dsbryz.iteye.com/blog/1182056
 * 时间复杂度:O(nlogn)
 * 稳定性:不稳定
 */
public class HeapSort {
	public static void heapSort(int[] a){
		buildHeapfirst(a);						//第一次构造大根堆
		int len = a.length;
		for(int i = len; i>1; i--){					//将最大值赋给 a[0]
			int tmp = a[0];
			a[0] = a[i-1];
			a[i-1] = tmp;
			buildHeapnext(a, 1, i-1);				//i为数组大小-1
		}
	}	
	//从最底下的子树构造大根堆
	public static void buildHeapfirst(int[] a){
		for(int i=a.length / 2; i>0; i--){
			buildHeapnext(a, i, a.length);
		}
	}
	//堆调整,使其生成最大堆
	public static void buildHeapnext(int[] a, int parentIndex, int heapSize){
		int left = parentIndex * 2;					//左儿子,对应数组中为:a[left-1]:(partIndex)*2-1
		int right = parentIndex * 2 + 1;
		int largestIndex = parentIndex;					//最大值:初始而父节点
	
		// 如果左子节点大于父节点,则将左子节点作为最大节点  
		if(left <= heapSize && a[left-1] > a[parentIndex-1]){
			largestIndex = left;
		}	
		// 如果右子节点比最大节点还大,那么最大节点应该是右子节点 
		if(right <= heapSize && a[right-1] > a[largestIndex-1]){
			largestIndex = right;
		}
		// 最后,如果最大节点和父节点不一致,则交换他们的值  
		if(largestIndex != parentIndex){
			int tmp = a[parentIndex-1];
			a[parentIndex-1] = a[largestIndex-1];
			a[largestIndex-1] = tmp;
			// 交换完父节点和子节点的值,对换了值的子节点检查是否符合最大堆的特性  
			buildHeapnext(a, largestIndex, heapSize);
		}
	}
	public static void main(String[] args){
		int[] a = {21,1,5,7,7,5,23,2,1,8};
		heapSort(a);
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}

选择排序:

/*
 * 选择排序:对应的位置选择对应的值,这里从前往后一次增大。
 * 时间复杂度:O(n^2)
 * 稳定性:不稳定
 */
public class SelectSort {
	public static void selectSort(int[] a){
		int len = a.length;
		for(int i=0; i<len; i++){
			for(int j=i+1; j<len; j++){
				if(a[j] < a[i]){
					int tmp = a[j];
					a[j] = a[i];
					a[i] = tmp;
				}
			}
		}
	}
	public static void main(String[] args){
		int[] a = {21,5,23,1,8};
		selectSort(a);
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}

插入排序:

/*
 * 插入排序:从第二个数开始,前面的数都是排好序的,那么新插入的数只要交换到合适的位置就是排好序的。
 * 时间复杂度:O(n^2)
 * 稳定性:稳定
 */
public class InsertSort {
	public static void insertSort(int[] a){
		int len = a.length;
		if(len == 1){
			return;
		}
		int target;
		for(int i=1; i<len; i++){					//从第二个数开始排序
			target = a[i];
			int j = i;
			while(j > 0 && target < a[j-1]){			//找到target合适的位置,并交换
				a[j] = a[j-1];					//将前面的数赋给后面的
				j--;
			}
			if(j != i){
				a[j] = target;					//如果发生过交换则将target赋给最前面的数
			}
		}
	}
	public static void main(String[] args){
		int[] a = {21,5,23,1,8};
		insertSort(a);
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}

计数排序:

/*
 * 桶排序:用一个理想的大数组保存出现的每一个值次数,即a[i]为i出现的次数,i为这个数。
 * 时间复杂度:O(N+C),其中C=N*(logN-logM),N个待排数据,M个桶,
 * 稳定性:稳定
 */
public class BucketSort {
	public static void bucketSort(int[] a, int maxlen){
		int[] max = new int[maxlen];	//桶(数组)
		for(int i=0; i<a.length; i++){
			max[a[i]]++;	//对应桶中数的数量加一
		}
		for(int i=0,j=0; i<maxlen; i++){
			if(max[i] != 0){
				while(max[i] > 0){
					a[j++] = i;
					max[i]--;
				}
			}
		}
	}
	public static void main(String[] args){
		int[] a = {21,1,5,7,7,5,23,1,8};
		int maxlen = 100;
		bucketSort(a,maxlen);
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}

基数排序:

/*
 * 初始化:  构造一个10*n的二维数组,一个长度为n的数组用于存储每次位排序时每个桶子里有多少个元素。
 * 循环操作:从低位开始(我们采用LSD的方式),将所有元素对应该位的数字存到相应的桶子里去(对应二维数组的那一列)。
 *           然后将所有桶子里的元素按照桶子标号从小到大取出,对于同一个桶子里的元素,先放进去的先取出,后放进去的后取出(保证排序稳定性)。
 *           这样原数组就按该位排序完毕了,继续下一位操作,直到最高位排序完成。
 * 详解:http://www.cnblogs.com/developerY/p/3172379.html
 * 时间复杂度:Θ(d*n),循环d次
 * 稳定性:稳定
 */
public class RedixSort {
	public static void redixSort(int[] a, int maxlen){
		System.out.println(maxlen);
		int len = a.length;
		int[][] bucket = new int[10][len];					//桶数组,保存实际的值
		int[] numOfbucket = new int[len];					//保存对应桶数组中元素的个数
		int n = 1;								//个位、十位、百位		
		while(n < maxlen){
			for(int x: a){
				int digit = (x / n) % 10;
				bucket[digit][numOfbucket[digit]] = x;
				numOfbucket[digit]++;					 //digit对应数组中元素个数加一
			}
			int k = 0;
			for(int i=0; i<len; i++){					 //遍历numOfbucket数组
	            if(numOfbucket[i] != 0){
	                for(int j=0; j < numOfbucket[i]; j++){
	                    a[k] = bucket[i][j];
	                    k++;
	                }
	            }
	            numOfbucket[i] = 0;						  	//将桶里计数器置0,用于下一次位排序
	        }
			n *= 10;									
		}
		
	}
	public static void main(String[] args){
		int[] a = {21,1,5,7,700,5,23,1,8};
		int max = 0;	//最大数
		for(int i=0; i<a.length; i++){
			if(a[i] > max){
				max = a[i];
			}
		}
		int maxlen = 0;	//最大数的位数+1
		while(max > 0){
			max /= 10;
			maxlen++;
		}
		redixSort(a,(int)Math.pow(10, maxlen));
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}

希尔排序:

/*
 * 希尔排序也成为“缩小增量排序”,其基本原理是,现将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,
 * 然后对各个子序列分别进行直接插入排序,待整个待排序列“基本有序”后,最后在对所有元素进行一次直接插入排序 。
 * 时间复杂度:O(nlogn)
 * 稳定性:不稳定
 */
public class HillSort {
	public static void hillSort(int[] a){
		int len = a.length;
		for(int increment=len/2; increment>0; increment /= 2){	//初始增量为len/2,逐渐缩小增量
			for(int i=increment; i<len; i++){
				int flag = a[i];
				int j;
				for(j = i-increment; j>=0; j -= increment){
					if(flag < a[j]){		//后面的数比前面的小
						a[j+increment] = a[j];	//将前面的数赋值给后面的
					}else{
						break;
					}
				}
				a[j+increment] = flag;			//将后面的赋值给前面的
			}
		}
	}
	public static void main(String[] args){
		int[] a = {21,5,23,1,8};
		hillSort(a);
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}

冒泡排序:

/*
 * 冒泡排序:相邻数进行比较,将大的数沉入数组低端,小的数“冒”到顶端。
 * 时间复杂度为:O(n^2)
 * 稳定性:稳定
 */
public class BubbleSort {
	public static void bubbleSort(int[] a){
		int len = a.length;
		for(int i=0; i<len-1; i++){
			for(int j=0; j<len-1-i; j++){	//每趟排序结束后数组最后都是最大的值,不用排序,所以j的最大值是len-1-i
				if(a[j] > a[j+1]){
					int tmp = a[j];
					a[j] = a[j+1];
					a[j+1] = tmp;
				}
			}
		}
	}
	public static void main(String[] args){
		int[] a = {21,5,23,1,8};
		bubbleSort(a);
		for(int x:a){
			System.out.print(x + " ");
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值