第二篇:十大经典排序算法

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_29648139/article/details/93055055

1 引入的文件

1.1 定义一个工具类

package com.wanzh.util;

import java.util.Date;
import java.util.Random;

/**
 * 工具类
 *
 */
public class CommonUtils {
	
	/**
	 * 获取bean
	 * @param classPath
	 * @return
	 * @throws Exception
	 */
	public static Object getBean(String classPath) throws Exception{
		Class<?> forName = Class.forName(classPath);
		Object newInstance = forName.newInstance();
		return newInstance;
	}
	
	/**
	 * 显示两个日期的时间差
	 * @param endDate
	 * @param startDate
	 * @return
	 */
	public static String showDiffDate(Date endDate, Date startDate) {
	    long nd = 1000 * 24 * 60 * 60;
	    long nh = 1000 * 60 * 60;
	    long nm = 1000 * 60;
	    long ns = 1000;
	    // 获得两个时间的毫秒时间差异
	    long diff = endDate.getTime() - startDate.getTime();
	  /*  // 计算差多少天
	    long day = diff / nd;
	    // 计算差多少小时
	    long hour = diff % nd / nh;*/
	    // 计算差多少分钟
	    long min = diff % nd % nh / nm;
	    // 计算差多少秒//输出结果
	    long sec = diff % nd % nh % nm / ns;
	    // 计算差多少秒//输出结果
	    long millsec = diff % nd % nh % nm % ns;
	    return min + "分钟" + sec +"秒" + millsec + "毫秒";
	} 
	
	
	/**
	 * 随机获取一个size大小的int数组
	 * @param size
	 * @return
	 */
	public static int[] getRandomArr(int size) {
		Random random = new Random();
		int[] arr = new int[size];
		for(int i = 0; i < arr.length; i++ ) {
			arr[i] = random.nextInt(size);
		}
		return arr;

	}
}


1.2 定义一个排序的接口

package com.wanzh.sort;


public interface IArraySort {
	/**
	 * 待排序数组
	 * @param arr
	 */
	public void sort(int[] arr);
}

2 冒泡排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html

package com.wanzh.sort.impl;


import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;

/**
 * 冒泡排序
 * 原理:比较相邻的元素。如果第一个比第二个大,就交换他们两个。
 * 		对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
 * 		针对所有的元素重复以上的步骤,除了最后一个。
 * 		持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
 * 时间复杂度:O(n^2)
 * 算法稳定性: 稳定
 */
public class BubbleSort implements IArraySort{
	
	public void sort(int[] arr) {
		int temp = 0;
		boolean flag = false;
		for(int i = 0; i < arr.length - 1; i++) {
			//需要比较的次数
			for(int j = 0; j < arr.length - 1 - i; j++) {
				//相邻元素比较,若前面的数大于后面的数则交换两个数的位置。
				if(arr[j] > arr[j+1]) {
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
					flag = true;
				}
			}
			//若没有交换意味着数组有序 
			if(!flag) {
				break;
			}
			flag = false;
		}
	}
	
	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new BubbleSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}

}

运行结果

排序前:[23, 5, 28, 12, 2, 19, 16, 17, 25, 8, 3, 11, 2, 22, 12, 14, 23, 27, 12, 10, 1, 26, 0, 5, 20, 11, 14, 21, 2, 0]
排序后:[0, 0, 1, 2, 2, 2, 3, 5, 5, 8, 10, 11, 11, 12, 12, 12, 14, 14, 16, 17, 19, 20, 21, 22, 23, 23, 25, 26, 27, 28]

3 选择排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html

package com.wanzh.sort.impl;


import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;

/**
 * 选择排序
 * 原理:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置。
 * 		然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
 * 		以此类推,直到全部待排序的数据元素排完。 
 * 时间复杂度:O(n^2)
 * 算法稳定性: 不稳定
 */
public class SelectionSort implements IArraySort{

	@Override
	public void sort(int[] arr) {
		int temp = 0;
		for(int i = 0; i < arr.length; i++) {
			//当前遍历数与后面所有的数比较
			for(int j = i+1; j < arr.length; j++) {
				//若遍历数比后面的数大则交换位置
				if(arr[i] > arr[j]) {
					temp = arr[i];
					arr[i] = arr[j];
					arr[j] = temp;
				}
			}
		}
	}
	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new SelectionSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}
}

运行结果

排序前:[5, 15, 19, 16, 25, 24, 28, 6, 18, 3, 0, 1, 18, 13, 29, 29, 12, 21, 6, 28, 5, 9, 1, 15, 4, 4, 4, 1, 16, 21]
排序后:[0, 1, 1, 1, 3, 4, 4, 4, 5, 5, 6, 6, 9, 12, 13, 15, 15, 16, 16, 18, 18, 19, 21, 21, 24, 25, 28, 28, 29, 29]

4 插入排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html

package com.wanzh.sort.impl;


import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;

/**
 * 插入排序
 * 原理:每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
 * 时间复杂度:O(n^2)
 * 算法稳定性: 稳定
 */
public class InsertSort implements IArraySort{

	@Override
	public void sort(int[] arr) {
		//从下标为1的元素开始插入到合适的位置
		for(int i = 1; i< arr.length; i++) {
			
			//记录当前要插入的元素
			int tempElement = arr[i];
			//记录最后交换元素的下标
			int tempIndex = -1;
			
			//插入元素前面元素个数
			for(int j = i - 1; j >= 0; j--) {
				if(tempElement < arr[j]) {
					//若插入元素较小则交换位置
					tempIndex = j;
					arr[j+1] = arr[j];
				
				}else {
					//否则直接退出循环
					break;
				}
			}
			
			//若存在较小的数 则插入
			if(tempIndex >= 0) {
				arr[tempIndex] = tempElement;
			}
		}
	}
	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new InsertSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}
}

运行结果

排序前:[27, 2, 11, 11, 23, 2, 18, 13, 22, 20, 26, 19, 18, 25, 25, 19, 12, 5, 26, 12, 19, 2, 22, 12, 25, 0, 13, 13, 9, 16]
排序后:[0, 2, 2, 2, 5, 9, 11, 11, 12, 12, 12, 13, 13, 13, 16, 18, 18, 19, 19, 19, 20, 22, 22, 23, 25, 25, 25, 26, 26, 27]

5 希尔排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html

package com.wanzh.sort.impl;


import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;

/**
 * 希尔排序
 * 原理:直接插入排序算法的一种更高效的改进版本。
 * 		把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;
 * 		随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
 * 时间复杂度:O(n^(1.3—2))
 * 算法稳定性: 不稳定
 */
public class ShellSort implements IArraySort{

	@Override
	public void sort(int[] arr) {
		int size = arr.length;
		//遍历所有的步长(增量)
		for(int step = size / 2; step > 0; step /= 2) {
			//按增量分组
			for(int i = step ; i < size; i++) {
				//每组的元素进行插入排序
				insertSort(arr, step, i);
			}
		}
	}
	
	/**
	 * 直接插入排序
	 * @param arr 待排序数组
	 * @param step 步长
	 * @param index 插入元素下标
	 */
	private void insertSort(int[] arr,int step,int index){
		//记录当前要插入的元素
		int tempElement = arr[index];
		//记录最后交换元素的下标
		int tempIndex = -1;
		//插入元素前面元素个数
		for(int z = index - step; z >= 0; z -= step) {
			if(tempElement < arr[z]) {
				//若插入元素较小则交换位置
				tempIndex = z;
				arr[z + step] = arr[z];
			}else {
				//否则直接退出循环
				break;
			}
		}
		//若存在较小的数 则插入
		if(tempIndex >= 0) {
			arr[tempIndex] = tempElement;
		}
	}
	
	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new ShellSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}
}

运行结果

排序前:[23, 4, 24, 9, 14, 19, 22, 3, 23, 18, 10, 27, 4, 4, 29, 23, 19, 28, 1, 24, 23, 2, 0, 1, 14, 21, 24, 24, 13, 20]
排序后:[0, 1, 1, 2, 3, 4, 4, 4, 9, 10, 13, 14, 14, 18, 19, 19, 20, 21, 22, 23, 23, 23, 23, 24, 24, 24, 24, 27, 28, 29]

6 归并排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html

package com.wanzh.sort.impl;


import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;

/**
 * 归并排序
 * 原理:采用分治法,将已有序的子序列合并,得到完全有序的序列。
 * 时间复杂度:O(nlogn)
 * 算法稳定性: 稳定
 */
public class MergeSort implements IArraySort{

	@Override
	public void sort(int[] arr) {
		mergeSort(arr, 0, arr.length - 1);
	}
	private void mergeSort(int[] arr, int start, int end) {
		if(start == end) {
			return ;
		}
		int middle = (start + end) / 2;
		//处理左边数据
		mergeSort(arr, start, middle);
		//处理右边数据
		mergeSort(arr, middle + 1, end);
		//合并数据
		merge(arr, start, middle, end);
	}
	
	private void merge(int[] arr, int start, int middle, int end) {
		//定义一个临时数组来存储归并后的数组
		int[] tempArr = new int[end - start + 1];
		//记录临时数组的下标
		int tempIndex = 0;
		//存储左数组当前的下标
		int low= start;
		//存储右数组当前的下标
		int high = middle + 1;
		
		//遍历两个数组,取出小的数字放入临时数组中,并把当前较小值所在数组下标往后移一位。
		while(low <= middle && high <=end) {
			if(arr[low] <= arr[high]) {
				tempArr[tempIndex] = arr[low];
				low ++;
			}else {
				tempArr[tempIndex] = arr[high];
				high ++;
			}
			tempIndex ++;
		}
		
		//若某个数组全部遍历结束 需把相反的另一组数组剩余的数赋给临时数组
		int startIndex = low > middle ? high : low;
		int endIndex = low > middle ? end : middle;
		for(int i = startIndex; i <= endIndex; i++) {
			tempArr[tempIndex] = arr[i];
			tempIndex ++;
		}
		
		//把临时数组的值赋给原数组
		System.arraycopy(tempArr, 0, arr, start, tempArr.length);
	}
	
	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new MergeSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}
}

运行结果

排序前:[10, 20, 11, 22, 26, 6, 15, 4, 25, 11, 10, 3, 3, 15, 11, 15, 12, 3, 21, 15, 8, 0, 12, 17, 4, 6, 7, 11, 4, 13]
排序后:[0, 3, 3, 3, 4, 4, 4, 6, 6, 7, 8, 10, 10, 11, 11, 11, 11, 12, 12, 13, 15, 15, 15, 15, 17, 20, 21, 22, 25, 26]

7 快速排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html

package com.wanzh.sort.impl;

import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;
/**
 * 快速排序
 * 原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,
 * 		然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
 * 时间复杂度:O(nlogn)
 * 算法稳定性: 不稳定
 */
public class QuickSort implements IArraySort{

	@Override
	public void sort(int[] arr) {
		quickSort(arr, 0, arr.length - 1);
	}
	
	private void quickSort(int[] arr, int start, int end) {
		if(start < end) {
			//把数组的首个数字作为标准数
			int stard=arr[start];
			int low = start;
			int high = end;
			while(low < high) {
				//右边的数比标准数小替换左边的数,否则右下标往左移。
				while(low < high && arr[high] >= stard) {
					high --;
				}
				arr[low] = arr[high];
				
				//左边的数比标准数大替换右边的数,否则左下标往右移。
				while(low < high && arr[low] <= stard) {
					low ++;
				}
				arr[high] = arr[low];
			}
			
			//将标准数赋给最后停留位置 此时  low==high
			arr[low] = stard;
			//处理左边比标准数小的数组
			quickSort(arr, start, low);
			//处理右边比标准数大的数组
			quickSort(arr, low + 1,end);
		}
	}
	
	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new QuickSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}
	
}

运行结果

排序前:[5, 14, 23, 2, 12, 20, 24, 21, 11, 20, 1, 10, 25, 28, 0, 6, 10, 11, 2, 19, 18, 13, 8, 15, 8, 7, 22, 14, 25, 24]
排序后:[0, 1, 2, 2, 5, 6, 7, 8, 8, 10, 10, 11, 11, 12, 13, 14, 14, 15, 18, 19, 20, 20, 21, 22, 23, 24, 24, 25, 25, 28]

8 堆排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/HeapSort.html

package com.wanzh.sort.impl;

import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;
/**
 * 堆排序
 * 原理:利用堆这种数据结构所设计的一种排序算法。
 * 		 堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
 * 时间复杂度:O(nlogn)
 * 算法稳定性: 不稳定
 */
public class HeapSort implements IArraySort{

	@Override
	public void sort(int[] arr) {
		//找最后一个非叶子节点
		int last = (arr.length - 2) / 2;
		//将无需序列构建成大顶堆;
		for(int i = last; i >= 0; i--) {
			swapData(arr, i, arr.length);
		}
		
		int temp = 0;
		//将堆顶元素与末尾元素交换,最大元素在数组尾端,其他元素调整为大顶堆 ,重复操作;
		for(int i = arr.length -1; i > 0; i--) {
			temp = arr[0];
			arr[0] = arr[i];
			arr[i] = temp;
			swapData(arr, 0, i);
		} 
	}
	
	/**
	 * 交换父子节点的数据
	 * @param arr 数组
	 * @param start 父节点下标
	 * @param size	数组长度
	 */
	private void swapData(int[] arr,int start,int size) {
		//左子节点下标
		int left = start * 2 + 1;
		//右子节点下标
		int right = start * 2 + 2;
		//用于交换数据的临时存储
		int tempIndex = -1;
		int tempElement = 0;
		
		//若左子节点值大于父节点记录下标
		if(left < size && arr[left] > arr[start]) {
			tempIndex = left;
		}
		//若右子节点值大于父节点记录下标
		if(right < size && arr[right] > arr[start]) {
			if(tempIndex == -1) {
				tempIndex = right;
			}else {
				tempIndex = arr[left] > arr[right] ? left : right;
			}
		}
		
		//若存在子节点大于父节点则交换顺序
		if(tempIndex != -1) {
			tempElement = arr[tempIndex];
			arr[tempIndex] = arr[start];
			arr[start] = tempElement;
			//交换顺序后可能会破坏平衡
			swapData(arr, tempIndex, size);
		}
	}


	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new HeapSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}
	
}

运行结果

排序前:[6, 15, 8, 19, 28, 2, 20, 28, 28, 13, 22, 4, 29, 3, 26, 16, 1, 8, 11, 22, 6, 21, 3, 2, 4, 20, 3, 16, 0, 10]
排序后:[0, 1, 2, 2, 3, 3, 3, 4, 4, 6, 6, 8, 8, 10, 11, 13, 15, 16, 16, 19, 20, 20, 21, 22, 22, 26, 28, 28, 28, 29]

9 计数排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/CountingSort.html

package com.wanzh.sort.impl;


import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;

/**
 * 计数排序
 *原理:计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。
* 	   作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
 * 时间复杂度:O(n+k),其中 k = max - min
 * 算法稳定性: 稳定
 */
public class CountSort implements IArraySort{
	
	public void sort(int[] arr) {
		//获取最大值、最小值
		int min = Arrays.stream(arr).min().getAsInt();
		int max = Arrays.stream(arr).max().getAsInt();
		for(int i = 1; i < arr.length; i++) {
			if(arr[i] < min) {
				min = arr[i];
			}
			if(arr[i] > max) {
				max = arr[i];
			}
		}
		//计算每个数字出现次数
		int[] temp = new int[max - min + 1];
		for(int i = 0; i < arr.length; i++) {
			temp[arr[i] - min] ++;
		}
		int index = 0;
		//组装数据
		for(int i = 0; i < temp.length; i++) {
			for(int j = 0; j < temp[i]; j++) {
				arr[index ++] = min + i;
			}
		}
		
	}
	
	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new CountSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
	}

}

运行结果

排序前:[22, 5, 11, 1, 11, 9, 29, 27, 26, 17, 29, 17, 3, 19, 14, 26, 1, 23, 5, 9, 2, 23, 0, 7, 25, 16, 0, 4, 10, 0]
排序后:[0, 0, 0, 1, 1, 2, 3, 4, 5, 5, 7, 9, 9, 10, 11, 11, 14, 16, 17, 17, 19, 22, 23, 23, 25, 26, 26, 27, 29, 29]

10 桶排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/BucketSort.html

package com.wanzh.sort.impl;

import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;
/**
 * 桶排序
 * 原理:将数组的数据分到有限数量的桶里,再对每个桶的数据进行排序。
 * 	  数据分散的约平均效率越快,牺牲空间换时间。
 * 时间复杂度:O(N+C)
 * 算法稳定性: 稳定
 */
public class BucketSort implements IArraySort{

	// 999 --- 10   0-99->0 100-199->1 200-299->2 ...900-999->9
	/// 999/99 = 10
	@Override
	public void sort(int[] arr) {
		//获取最大值、最小值
		int min = Arrays.stream(arr).min().getAsInt();
		int max = Arrays.stream(arr).max().getAsInt();
		for(int i = 1; i < arr.length; i++) {
			if(arr[i] < min) {
				min = arr[i];
			}
			if(arr[i] > max) {
				max = arr[i];
			}
		}
		
		int bucketSize = arr.length / 500+ 1;
		int bucketNum = (max - min)/bucketSize + 1;
		int[][] bucketArr = new int[bucketNum][arr.length];
		int[] indexArr = new int[bucketNum];
		int oneIndex = 0;
		int twoIndex = 0;
		//将数据放入桶中并插入排序
		for(int i = 0; i < arr.length; i++) {
			oneIndex = (arr[i] - min) / bucketSize;
			twoIndex = indexArr[oneIndex];
			bucketArr[oneIndex][twoIndex] = arr[i];
			if(twoIndex > 0) {
				//若该桶超过两个数则进行插入排序
				insertSort(bucketArr[oneIndex],twoIndex);
			}
			indexArr[oneIndex] ++;
			
		}
		
		//从桶取出数据放到原数组中
		int index = 0;
		for(int i = 0; i < bucketNum; i++) {
			twoIndex = indexArr[i];
			for(int j = 0; j < twoIndex; j++ ) {
				arr[index++] = bucketArr[i][j];
			}
		}
		
 	}
	
	private void insertSort(int[] arr,int start) {
		int element = arr[start];
		int index = -1;
		for(int i = start - 1; i >= 0; i--) {
			if(element < arr[i]) {
				arr[i + 1] = arr[i];
				index = i;
			}else {
				break;
			}
		}
		if(index != -1) {
			arr[index] = element;
		}
	}

	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new BucketSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
		
	}

}

运行结果

排序前:[5, 14, 6, 9, 18, 3, 6, 7, 23, 7, 24, 7, 18, 23, 12, 26, 27, 26, 20, 14, 22, 16, 10, 19, 25, 19, 27, 25, 13, 26]
排序后:[3, 5, 6, 6, 7, 7, 7, 9, 10, 12, 13, 14, 14, 16, 18, 18, 19, 19, 20, 22, 23, 23, 24, 25, 25, 26, 26, 26, 27, 27]

11 基数排序

动态演示地址:https://www.cs.usfca.edu/~galles/visualization/RadixSort.html

package com.wanzh.sort.impl;

import java.util.Arrays;

import com.wanzh.sort.IArraySort;
import com.wanzh.util.CommonUtils;

/**
 * 基数排序
 * 原理:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。
 * 		然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
 * 		基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),
 * 		LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。。
 * 时间复杂度:O(nlog(r)m)
 * 算法稳定性: 稳定
 */
public class RadixSort implements IArraySort{

	// 个位数  /1%10  十位数  /10%10  百位数 /100%10 
	@Override
	public void sort(int[] arr) {
		//求数组最大值
		int max = Arrays.stream(arr).max().getAsInt();
		//最大值的位数
		int len = String.valueOf(max).length();
		int[][] elementArr = new int[10][arr.length];
		int[] indexArr = new int[10];
		//从个位数开始遍历
		for(int n = 1, i = 1; n <= len; n++,i *= 10) {
			for(int j = 0; j < arr.length; j++) {
				//求余数
				int value = arr[j]/ i % 10;
				//存到对应的位置
				elementArr[value][indexArr[value]++] = arr[j];
			}
			//把排好序的数组赋给原数组
			int index = 0;
			for(int j = 0; j < indexArr.length; j++) {
				for(int k = 0; k < indexArr[j]; k++) {
					arr[index++] = elementArr[j][k];
				}
			}
			indexArr = new int[10];
		}
		
	}
	

	public static void main(String[] args) {
		int[] arr = CommonUtils.getRandomArr(30);
		IArraySort arraySort = new RadixSort();
		System.out.println("排序前:"+Arrays.toString(arr));
		arraySort.sort(arr);
		System.out.println("排序后:"+Arrays.toString(arr));
		
	}
}

运行结果

排序前:[22, 10, 13, 27, 1, 17, 21, 28, 10, 18, 14, 9, 0, 28, 19, 8, 12, 23, 12, 11, 9, 17, 11, 17, 12, 1, 8, 5, 1, 1]
排序后:[0, 1, 1, 1, 1, 5, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 14, 17, 17, 17, 18, 19, 21, 22, 23, 27, 28, 28]

12 测试运行效率

12.1 定义算法的枚举类

package com.wanzh.sort.enums;

public enum SortEnum {
	INSERTSORT("com.wanzh.sort.impl.InsertSort","插入排序"),
	SHELLSORT("com.wanzh.sort.impl.ShellSort","希尔排序"),
	MERGESORT("com.wanzh.sort.impl.MergeSort","归并排序"),
	QUICKSORT("com.wanzh.sort.impl.QuickSort","快速排序"),
	HEAPSORT("com.wanzh.sort.impl.HeapSort","堆排序"),
	COUNTSORT("com.wanzh.sort.impl.CountSort","计数排序"),
	RADIXSORT("com.wanzh.sort.impl.RadixSort","基数排序"),
	BUCKETSORT("com.wanzh.sort.impl.BucketSort","桶排序"),
	BUBBLESORT("com.wanzh.sort.impl.BubbleSort","冒泡排序"),
	SELECTIONSORT("com.wanzh.sort.impl.SelectionSort","选择排序");
	
	
	private String classPath;
	private String name;
	
	SortEnum(String classPath,String name) {
		this.classPath = classPath;
		this.name = name;
	}

	public String getClassPath() {
		return classPath;
	}

	public void setClassPath(String classPath) {
		this.classPath = classPath;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	
	
}

12.2 定义测试类

package com.wanzh.sort;

import java.util.Arrays;
import java.util.Date;

import com.wanzh.sort.enums.SortEnum;
import com.wanzh.util.CommonUtils;

public class TestSort {
	public static void main(String[] args) throws Exception {
		testSort(10000);
	}
	
	public static void testSort(int size) throws Exception {
		int[] arr = CommonUtils.getRandomArr(size);
		SortEnum[] values = SortEnum.values();
		for(int i = 0; i< values.length; i++) {
			int[] copyArr = Arrays.copyOf(arr, arr.length);
			IArraySort arraySort = (IArraySort) CommonUtils.getBean(values[i].getClassPath());
			Date date = new Date();
			arraySort.sort(copyArr);
			System.out.println(values[i].getName()+"排序时间:"+CommonUtils.showDiffDate(new Date(),date));
		}
	}
	
	
}

12.3 测试结果

当size=10000时,运行结果:

插入排序时间:0分钟0秒32毫秒
希尔排序时间:0分钟0秒3毫秒
归并排序时间:0分钟0秒3毫秒
快速排序时间:0分钟0秒3毫秒
堆排序时间:0分钟0秒3毫秒
计数排序时间:0分钟0秒60毫秒
基数排序时间:0分钟0秒3毫秒
桶排序时间:0分钟0秒7毫秒
冒泡排序时间:0分钟0秒116毫秒
选择排序时间:0分钟0秒151毫秒

当size == 100000时,运行结果:

插入排序时间:0分钟2秒998毫秒
希尔排序时间:0分钟0秒18毫秒
归并排序时间:0分钟0秒20毫秒
快速排序时间:0分钟0秒17毫秒
堆排序时间:0分钟0秒12毫秒
计数排序时间:0分钟0秒56毫秒
基数排序时间:0分钟0秒11毫秒
桶排序时间:0分钟0秒120毫秒
冒泡排序时间:0分钟14秒154毫秒
选择排序时间:0分钟14秒532毫秒

当size == 500000时,运行结果:

插入排序时间:1分钟14秒481毫秒
希尔排序时间:0分钟0秒88毫秒
归并排序时间:0分钟0秒72毫秒
快速排序时间:0分钟0秒63毫秒
堆排序时间:0分钟0秒78毫秒
计数排序时间:0分钟0秒80毫秒
基数排序时间:0分钟0秒41毫秒
桶排序时间:0分钟0秒452毫秒
冒泡排序时间:5分钟58秒322毫秒
选择排序时间:6分钟5秒689毫秒
展开阅读全文

没有更多推荐了,返回首页