JAVA实现六种排序方法

java实现六种排序方法

介绍

  1. 选择排序
  2. 冒泡排序
  3. 插入排序
  4. 基数排序
  5. 快速排序
  6. 归并排序

各种排序算法已封装好,注释详细,可直接复制使用。

代码

import java.util.Arrays;

/**
 * 测试排序算法
 * 因为排序算法经常使用,所以将其设置为静态的 
 * 排序结果都是升序
 * 1. 选择排序
 * 2. 冒泡排序
 * 3. 插入排序
 * 4. 基数排序
 * 5. 快速排序
 * 6. 归并排序
 * @author dxt
 *
 */
public class Sort {
	
	public static void main(String[] args){
		int[] arr = {4, 3, 2, 1, 100, 30, 0, 22};
		System.out.println("待排序的数组为:" + Arrays.toString(arr));
		//selectSort(arr);	//选择排序
		//bubbleSort(arr);	//冒泡排序
		//insertSort(arr);	//插入排序
		//radixSort(arr);	//基数排序
		//quickSort(arr, 0, arr.length-1);	//快速排序
		mergeSort(arr);		//归并排序
		System.out.println("排序后的数组为:" + Arrays.toString(arr));
	}
	/**
	 * java中无实现swap()函数
	 * @param arr
	 * @param index1
	 * @param index2
	 */
	public static void swap(int[] arr, int index1, int index2){
		int temp = arr[index1];
		arr[index1] = arr[index2];
		arr[index2] = temp;
	}
	/**
	 * 选择排序
	 * 内循环每次在无序数组中选择一个最大的
	 * 外循环将内循环中选出的最大的数据放到无序数据的最后一个位置
	 * @param array
	 */
	public static void selectSort(int[] array){
		for(int i=0; i<array.length-1; i++){
			int max_num_index = 0;
			for(int j=0; j<array.length-i; j++){
				if(array[max_num_index] < array[j]){
					max_num_index = j;
				}
			}
			swap(array, max_num_index, array.length-1-i);
		}
	}
	/**
	 * 及时终止的冒泡排序
	 * 内层循环通过依次比较相邻的两个数据,在无序数据中找出最大的那个数,然后将最大的那个数放到
	 * 无序区域的最后位置
	 * @param arr
	 */
	public static void bubbleSort(int[] arr){
		for(int i=0; i<arr.length-1; i++){
			boolean flag = true;
			for(int j=0; j<arr.length-1-i; j++){
				if(arr[j] > arr[j+1]){
					swap(arr, j, j+1);
					flag = false;
				}
			}
			if(flag){
				break;
			}
		}
	}
	/**
	 * 插入排序
	 * 1. 将待排序数组分为两部分,前一部分(索引靠前)是有序的,后一部分(索引在后)是无序的
	 * 2. 初始时,将数组中的第1个元素作为有序部分, 其它数据作为无序部分
	 * 3. 之后每次选取无序部分的第一个元素,作为要排序的元素,将其插入到有序部分
	 * 4. 因为有序部分是有序的,所以插入过程,可以从有序部分的最后一个数据开始,就是找对应位置,数组元素后移
	 * @param arr
	 */
	public static void insertSort(int[] arr){
		for(int i=1; i<arr.length; i++){	//从第二个元素开始
			int temp = arr[i];	//要插入的第i个元素
			int j;
			for(j=i-1; j>=0 && temp<arr[j]; j--){	
				arr[j+1] = arr[j];
			}
			arr[j+1] = temp;
		}
	}
	/**
	 * 基数排序
	 * @param arr
	 */
	public static void radixSort(int[] arr){
		//1. 确定最大位数,决定分配收集的轮数
		int times = 1;
		int p = 10;
		for(int i=0; i<arr.length; i++){
			while(arr[i] >= p){
				times++;
				p *= 10;
			}
		}
		System.out.println(times);
		//2. 进行分配 收集操作
		int[] temp = new int[arr.length];
		int[] bucket = new int[10];	//0-9 共10个桶
		int i, j, k;
		int radix = 1;
		for(i=0; i<times; i++){	//共分配 收集times次
			//2.1 每次分配前,都清空桶
			for(j=0; j<bucket.length; j++){	
				bucket[j] = 0;
			}
			//2.2 将数据分配到桶中:
			//具体操作就是依据取余方式,获得对应数位上的数,将对应桶中的数据个数+1
			for(j=0; j<arr.length; j++){
				k = (arr[j] / radix) % 10;
				bucket[k]++;
			}
			//2.3 确定每个桶中的数据对应的位置
			//比如:第2个桶中的数据都比第1个桶中的数据大,设第1个桶中的数据有a个,第2个同中有b个
			//那么第2个桶中的的数据的对应位置就是(a, a+b], 在这里计算对应的a+b
			//第三个桶对应的位置就是(a+b, a+b+c]
			for(j=1; j<10; j++){
				bucket[j] = bucket[j-1] + bucket[j];
			}
			//2.4 收集数据
			//首先将数据收集到临时存储对象temp[]中,
			//收集数据是从arr[]索引最大处向arr[]索引为0处进行收集
			//因为第一次分配 收集之后,数据的对应数位的数值大小是按照从小到大排列的
			for(j=arr.length-1; j>=0; j--){
				k = (arr[j] / radix) % 10;
				temp[bucket[k] -1] = arr[j];	//将对应数据放到对应位置
				bucket[k]--;
			}
			//2.5 将临时数组中的内容复制到arr[]中
			for(j = 0; j<arr.length; j++){
				arr[j] = temp[j];
			}
			//2.6 确定下一轮比较的数位
			radix = radix * 10;
		}
	}
	/**
	 * 快速排序
	 * 1. 先从数列中取出一个数作为基准数。
	 * 2. 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边
	 * 3. 再对左右区间重复第二步,直到各区间只有一个数。  
	 * @param arr
	 * @param low
	 * @param high
	 */
	public static void quickSort(int[] arr, int low, int high){
		if(low < high){
			int i = low;
			int j = high;
			int key = arr[i];	//归并排序中的基准数(选第一个),temp = arr[i],此时arr[i]处为一个坑
			while(i < j){
				//从右向左,找小于key的,其索引存放在j中
				while(i < j && arr[j] >= key){	
					j--;
				}
				//然后将右边大于key的数放到左边,此时key中保存着arr[i], arr[j]填入到arr[i]这个坑中
				//arr[j]处产生一个新坑
				if(i < j){
					arr[i] = arr[j];
					i++;
				}
				//从左向右,找大于key的,其索引存放在i中
				while(i < j && arr[i] < key){
					i++;
				}
				//然后将arr[i]处的元素填入到上面产生的坑中,arr[i]处又产生一个坑,等下一轮循环填
				if(i < j){
					arr[j] = arr[i];
					j--;
				}
			}
			//循环条件不成立 i==j
			arr[i] = key;	//将坑填满
			//对左右两个子数组再进行快速排序,递归
			quickSort(arr, low, j-1);
			quickSort(arr, j+1, high);
		}
	}
	/**
	 * 归并排序中的归并部分
	 * 将有序数列arr[first...mid]和arr[mid...last]合并。
	 * @param arr
	 * @param first
	 * @param mid
	 * @param last
	 * @param temp
	 */
	public static void mergeSort_merge(int[] arr, int first, int mid, int last, int[] temp){
		int i = first, j = mid+1;
		int m = mid, n = last;
		int k = 0;
		//合并两个arr[]中的两个部分
		while(i <= m && j<= n){
			if(arr[i] <= arr[j]){
				temp[k] = arr[i];
				k++;
				i++;
			}else{
				temp[k] = arr[j];
				k++;
				j++;
			}
		}
		while(i <= m){
			temp[k] = arr[i];
			k++;
			i++;
		}
		while(j <= n){
			temp[k] = arr[j];
			k++;
			j++;
		}
		//重新复制到arr[]
		for(i=0; i<k; i++){
			arr[first+i] = temp[i];
		}
	}
	/**
	 * 归并排序中的排序部分
	 * @param arr
	 * @param first
	 * @param last
	 * @param temp
	 */
	public static void mergeSort_sort(int[] arr, int first, int last, int[] temp){
		if(first < last){
			int mid = (first + last) / 2;
			mergeSort_sort(arr, first, mid, temp);
			mergeSort_sort(arr, mid+1, last, temp);
			mergeSort_merge(arr, first, mid, last, temp);
		}
	}
	/**
	 * 归并排序的入口,需要维持一个临时数组对象
	 * @param arr
	 */
	public static void mergeSort(int[] arr){
		int[] temp = new int[arr.length];
		mergeSort_sort(arr, 0, arr.length-1, temp);
	}
	
}

总结

从一个 知乎回答 中偷的一张图:
p1
(1)选择排序的不稳定性:对于数组9* 9 2,第一次外层循环将数字9*和第三个数字2进行交换,这样就破坏了稳定性。最后结果为2 9 9*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值