Java 实现排序

排序

注意:本系列排序都为升序,降序同理。

冒泡

/* 冒泡排序
* 遍历所有元素,相邻元素两两比较,如果与原定顺序(升序或降序)不同,则交换
* 遍历一次就会得到一个最大元素(升序)或最小元素(降序)
* 稳定,t:O(n^2),s:O(1)
* @param array
*/

	public static void bubbleSort(int[] array) {
		if(array==null) return;	//空数组
		for(int i=0;i<array.length-1;i++) {
			boolean flag=true;	//冒泡优化:设置一个标志位
			for(int j=0;j<array.length-1-i;j++) {
				if(array[j]>array[j+1]) {
					int temp=array[j];
					array[j]=array[j+1];
					array[j+1]=temp;
					flag=false;
				}
			}
			if(flag) break;	//标志位没有改变,表示没有执行if内容,前面的元素已经有序了,不用再遍历比较
		}
	}

快排

/* 快排  递归实现
* 快速排序采用 分治,从元素中挑一个作为基准数,
* 遍历元素,比基准数小的放左边,大的放右边,
* 同样的方法对基准数左右两个子数组进行 递归 操作
* 不稳定,t:O(nlogn),s:O(logn)
*/

	private static int quickOne(int[] array,int left,int right) {
		int key=array[left];
		while(left<right) {
			while(left<right && array[right]>=key) right--;	//两个while不能交换顺序
			array[left]=array[right];
			while(left<right && array[left]<key) left++;
			array[right]=array[left];
		}
		array[left]=key;
		return left;
	}
	
	private static void quickSort(int[] array,int left,int right) {
		int mid=quickOne(array,left,right);
		if(left<mid-1) quickSort(array,left,mid-1);
		if(mid+1<right) quickSort(array,mid+1,right);
	}
	
	public static void quickSort(int[] array)
	{
		if(array==null) return;
		quickSort(array,0,array.length-1);
	}
	
	public static void quickSort2(int[] array) {	//快排  非递归
		if(array==null) return;
		Stack<Integer> stack=new Stack<>();	//栈,先进后出
		stack.push(0);
		stack.push(array.length-1);
		while(!stack.isEmpty())
		{
			int right=stack.pop();
			int left=stack.pop();
			int mid=quickOne(array,left,right);
			if(left<mid-1)
			{
				stack.push(left);
				stack.push(mid-1);
			}
			if(mid+1<right)
			{
				stack.push(mid+1);
				stack.push(right);
			}
		}
	}

归并

/* 归并排序
* 将已有序的子序列合并,得到完全有序的序列
* 稳定,t:O(nlogn),s:O(n)
*/

	private static void mergeOne(int[] array,int left,int mid,int right) 	{
		if(array[mid]<=array[mid+1]) return;
		for(int i=mid+1;i<=right;i++)
		{
			for(int j=i;j>left;j--)
			{
				if(array[j]<array[j-1])
				{
					int temp=array[j];
					array[j]=array[j-1];
					array[j-1]=temp;
				}
				else break;
			}
		}
	}
	
	private static void mergeSort(int[] array,int left,int right)
	{
		int mid=(left+right)/2;
		if(left<mid) mergeSort(array,left,mid);
		if(mid+1<right) mergeSort(array,mid+1,right);
		mergeOne(array,left,mid,right);
	}
	
	public static void mergeSort(int[] array)//递归归并
	{
		if(array==null) return;
		mergeSort(array,0,array.length-1);
	}
	
	public static void mergeSort2(int[] array)//非递归归并
	{
		if(array==null) return;
		Queue<Integer> queue=new LinkedList<>();
		for(int i=0;i<array.length;i++)
		{
			queue.add(i);
			queue.add(i);
		}
		while(!queue.isEmpty())
		{
			int left1=queue.poll();
			int right1=queue.poll();
			int left2=queue.poll();
			int right2=queue.poll();
			if(right1+1!=left2)
			{
				queue.add(left1);
				queue.add(right1);
				left1=left2;
				right1=right2;
				left2=queue.poll();
				right2=queue.poll();
			}
			mergeOne(array,left1,right1,right2);
			if(queue.isEmpty()) break;
			queue.add(left1);
			queue.add(right2);
		}
	}

选择排序

/* 选择排序
* 任选一个(通常选第一个元素)作为最小值,与其后面的元素一一比较,如果找到比它更小的,则交换
* 每次得到一个最小值
* 不稳定,t:O(n^2),s:O(1)
*/

	public static void selectSort(int[] array) {
		if(array==null) return;
		for(int i=0;i<array.length-1;i++) {
			int min=i;	//下标
			for(int j=i;j<array.length;j++) {	//遍历,找出最小值下标
				if(array[min]>array[j]) min=j;	//交换,min始终是较小元素的下标
			}
			if(min!=i) {	//交换过了,将遍历出的最小元素放到起始位置
				int temp=array[min];
				array[min]=array[i];
				array[i]=temp;
			}
		}
	}

直接插入排序

/* 直接插入排序
* 假定前i个元素有序了,依次遍历数据,将当前数据插入到适当位置,形成i+1个由于元素
* 从第二个元素开始,依次设置为待插入元素,从后往前 比较,确定要插入的位置
* 稳定,t:O(n^2),s:O(1)
*/

	public static void insertSort(int[] array) {
		if(array==null) return;
		for(int i=1;i<array.length;i++) {
			int temp=array[i];	//当前待插入的元素
			int j=i-1;
			while(j>=0 && array[j]>temp) {
				array[j+1]=array[j];	//元素后移,给待插入元素让位
				j--;
			}
			array[j+1]=temp;
		}
	}

二分法排序

/* 二分法排序(直接插入排序的改进)
* 在速度上有提升
* 直接插入是与前面的逐个比较,二分法则是二分比较
* 稳定,t:O(nlogn),s:O(1)
*/

	public static void halfSort(int[] array) {
		for(int i=1;i<array.length;i++) {
			int temp=array[i];	//待插入元素
			int left=0;
			int right=i-1;
			int mid=-1;
			while(left<=right) {
				mid=left+(right-left)/2;	//二分了
				if(array[mid]>temp) right=mid-1;
				else left=mid+1;
			}
			for(int j=i-1;j>=left;j--) array[j+1]=array[j];
			array[left]=temp;	//插入
		}
	}

希尔排序

/* 希尔排序 (插入排序的改进)
* 将整个数组分割成 若干个子序列,分别进行直接插入排序
* 待基本有序时,再对全部数据依次直接插入排序
* 不稳定,t:O(n^3/2),s:O(1)
*/

	public static void shellSort(int[] array) {
		if(array==null) return;
		int d=array.length/2;	//以d的长度划分子区域
		while(d>0) {
			for(int i=0;i+d<array.length;i++) {
				if(array[i]>array[i+d]) {
					int temp=array[i];
					array[i]=array[i+d];
					array[i+d]=temp;
				}
			}
			d--;
		}
	}

堆排序

/* 堆排序
* 利用堆(近似完全二叉树的数据结构排序
* 不稳定,s:O(nlogn),t:(1)
*/

	public static void heapSort(int[] array) {
		if(array==null) return;
		int n=array.length;
		while(n>1) {
			for(int i=n/2;i>=1;i--) {
				if(2*i+1<=n && array[i-1]<array[2*i])
				{
					int t=array[i-1];
					array[i-1]=array[2*i];
					array[2*i]=t;
				}
				if(array[i-1]<array[2*i-1])
				{
					int temp=array[i-1];
					array[i-1]=array[2*i-1];
					array[2*i-1]=temp;
				}
			}
			int temp=array[0];
			array[0]=array[n-1];
			array[n-1]=temp;
			n--;
		}
	}

基数排序

/* 基数排序
* 是一种基于非比较的整数排序算法,原理是将整数按 位数 切割成不同的数字,
* 然后按每个不同 数位 分别比较
* 原始算法思想是将所有待比较的数值统一为同样的数位长度,不足的前面补零,然后从 最低位 开始依次进行依次排序
* 直到所有数据有序
* 稳定,t:O(n*k),s:O(n+k)
* n是数据个数,k是数据位数
*/
	public static void radixSort(int[] array) {
		if(array==null) return;
		int max=array[0];
		for(int i=1;i<array.length;i++)
		{
			if(max<array[i])
			{
				max=array[i];
			}
		}
		MyHashMap<Integer> myHash=new MyHashMap<>(10);
		int k=1;
		System.out.println("max="+max);
		while(max>0)
		{
			k=k*10;
			for(int i=0;i<array.length;i++)
			{
				int key=array[i]%k/(k/10);
				System.out.print(key+" ");
				myHash.add(key, array[i]);
			}
			System.out.println();
			myHash.hashToArray(array);
			max=max/10;
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值