常用排序方法

package com.sort;

public class Sort {
	//选择排序
	/*算法规则:将待排序集合(0...n)看成两部分,在起始状态中,一部分为(k..n)的待排序unsorted
	 * 集合,另一部分为(0...k)的已排序sorted集合,在待排序集合中挑选出最小元素并且记录下标i,
	 * 若该下标不等于k,那么 unsorted[i] 与 sorted[k]交换 ,一直重复这个过程,直到unsorted集
	 * 合中元素为空为止。
	 */
	public void selectSort(int[] arrays) {
		for(int i=0;i<arrays.length;i++){
			//记录从i到arrays.length结尾的最小值的下标
			int pos = i;			
			for(int j=i+1;j<arrays.length;j++){				
				if (arrays[j]<arrays[pos]) {
					pos = j;
				}
			}
			if (i!=pos) {
				int temp = arrays[i];
				arrays[i] = arrays[pos];
				arrays[pos] = temp;
			}
		}
	}
	//冒泡排序:相邻元素进行比较和交换
	/*算法规则:由于算法每次都将一个最小的元素往上冒,我们可以将待排序集合(0...n)看成两部分,
	 * 一部分为(k..n)的已排序sorted集合,另一部分为(0...k)的待排序unsorted集合,每一次都在
	 * unsorted集合从前往后遍历,选出一个数,如果这个数比其后面的数大,则进行交换。完成一轮
	 * 之后,就肯定能将这一轮unsorted集合中最大的数移动到集合的最后,并且将这个数从unsorted
	 * 中删除,移入sorted中。
	 */
	public void bubbleSort(int[] arrays) {
		for(int i=arrays.length-1;i>0;i--){
			for(int j=0;j<i;j++){
				if (arrays[j]>arrays[j+1]) {
					int temp = arrays[j];
					arrays[j] = arrays[j+1];
					arrays[j+1] = temp;
				}
			}
		}
	}
	//快速排序
	//算法规则:将数组划分为大于基准数字和不大于基准数字的两组集合,然后重读操作直
	//到数组中只有一个元素
	private int getMiddle(int[] arrays,int lo,int hi) {
		int basenum = arrays[lo];
		while(lo<hi){
			//从右向左找到第一个比基准数字小的数字然后跳出循环
			while(lo<hi&&arrays[hi]>basenum)
				hi--;
			if (lo<hi) {
				arrays[lo++]=arrays[hi];
			}
			//从左向右找到第一个比基准数字大的数字然后跳出循环
			while(lo<hi&&arrays[lo]<basenum)
				lo++;
			if (lo<hi) {
				arrays[hi--]=arrays[lo];
			}
		}
		arrays[lo]=basenum;
		return lo;
	}
	public void quickSort(int[] arrays,int lo,int hi) {
		if (lo<hi) {
			int mid = getMiddle(arrays,lo,hi);
			//对左半部分进行排序
			quickSort(arrays, lo, mid-1);
			//对右半部分进行排序
			quickSort(arrays, mid+1, hi);
		}
	}
	//插入排序
	public void insertSort(int[] arrays) {
		for(int i=1;i<arrays.length;i++){
			/*int j=i-1;
			//在后移元素之前,需要提前保存arrays[i]的值
			int temp = arrays[i];
			for(;j>=0&&arrays[j]>temp;j--)
				arrays[j+1]=arrays[j];*/
			int j=i;
			int temp = arrays[i];
			for(;j>0&&arrays[j-1]>temp;j--)
				arrays[j]=arrays[j-1];
			arrays[j]=temp;
		}
	}
	//希尔排序
	//希尔排序是插入排序的改进,时间复杂度与步长有关,Hibbard{1, 3, ..., 2^k-1}增量的
	//希尔排序的时间复杂度为O(N3/2)。
	public void shellSort(int[] arrays) {
		//此写法,代码不够简洁
		for(int gap = arrays.length/2;gap>0;gap/=2)//步长
			for(int i=0;i<gap;i++){
				//每个组别都采用直接插入排序
				for(int j=i+gap;j<arrays.length;j+=gap){
					if (arrays[j]<arrays[j-gap]) {
						int temp = arrays[j];
						int k=j-gap;
						//找到插入位置
						while(k>=0&&arrays[k]>temp){
							arrays[k+gap] = arrays[k];
							k-=gap;
						}
						arrays[k+gap] = temp;
					}
				}
			}
		
		/* int len = arrays.length;
		 * for(int gap=len/2;gap>0;gap/=2)
			for(int i=gap;i<len;i++)
				for(int j=i-gap;j>=0&&arrays[j]>arrays[j+gap];j-=gap)
					Swap(arrays, j, j+gap);
		*/
	}
	//交换数组中的两个元素
	private void Swap(int[] arrays,int first,int second) {
		int temp = arrays[first];
		arrays[first] = arrays[second];
		arrays[second] = temp;
	}
	//堆排序
	//两大问题:1、由无序序列建立一个大根堆;2、在输出堆顶元素之后重新建立一个大根堆
	//堆排序对于序列的原始顺序并不敏感,但是在构建堆的过程中会花费较长的时间
	public void heapSort(int[] arrays){
		//由数组建立一个大根堆
		int len = arrays.length;
		for(int i=(len-1)/2;i>=0;i--){
			AdjustHeap(arrays, i, len);
		}
		//输出堆顶元素,然后重新建立堆
		for(int j=len-1;j>0;j--){
			Swap(arrays, 0, j);
			AdjustHeap(arrays, 0, j);
		}
	}
	private void AdjustHeap(int[] arrays,int root,int length) {
		int temp = arrays[root];
		for(int j=root*2+1;j<length;j*=2){
			//记录此节点左右孩子节点较大的下标
			if (j<length-1&&arrays[j]<arrays[j+1]) {
				++j;
			}
			if(temp>arrays[j])
				break;
			arrays[root]=arrays[j];
			root=j;
		}
		arrays[root]=temp;
	}
	//归并排序:将待排序列分为若干个序列,每个子序列是有序的,然后将子序列合并
	public void mergeSort(int[] arrays) {
		getSort(arrays, 0, arrays.length-1);
	}
	private void getSort(int[] arrays,int left,int right) {
		if (left<right) {
			int center = (left + right)/2;
			//对左边数组进行递归
			getSort(arrays, left, center);
		    //对右边数组进行递归
			getSort(arrays, center+1,right);
			//合并
			merge(arrays, left, center, right);
		}
	}
	private void merge(int[] arrays,int left,int center,int right) {
		//i为第一有序区的第一个元素
		int i=left;
		//j为第二有序区的第一个元素
		int j=center+1;
		int[] temArrays=new int[right-left+1];
		//临时数组的指示下标
		int k=0;
		while(i<=center&&j<=right){
			if (arrays[i]<=arrays[j]) {
				temArrays[k++]=arrays[i++];
			}else {
				temArrays[k++]=arrays[j++];
			}
		}
		//将有剩余的有序区的元素全部复制到临时数组中
		while(i<=center){
			temArrays[k++]=arrays[i++];
		}
		while(j<=right){
			temArrays[k++]=arrays[j++];
		}
		//将排序后的数组,重新回到arrays中left到right区间
		for(i=left,k=0;i<=right;i++,k++){
			arrays[i]=temArrays[k];
		}
	}
	public static void main(String[] args) {
		int[] arrays = {1,-5,6,8,7,2};
		new Sort().mergeSort(arrays);
		for (int i = 0; i < arrays.length; i++) {
			System.out.println(arrays[i]);
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值