排序算法
1. 冒泡排序
2. 选择排序
3. 插入排序
4. 希尔排序
5. 快速排序
6. 归并排序
7. 基数排序
8. 堆排序
冒泡排序
BubbleSort.java
package com.Taking.sort;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Demo class
* 冒泡排序
*
* @author Taking
* @date 2020/5/20
*/
public class BubbleSort {
public static void main(String[] args) {
System.out.println("------------------------");
System.out.println("*******冒泡排序算法*******");
startTime();
bubbleSort(randomArray());
endTime();
System.out.println("------------------------");
}
/**
* 产生长度为100000的随机数组
*/
public static int[] randomArray() {
int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
//随机产生数据
arr[i] = (int) (Math.random() * 100000);
}
return arr;
}
/**
* 算法开始时时间
*/
public static void startTime() {
//开始时间
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String start = simpleDateFormat.format(date1);
System.out.println("开始时间为:" + start);
}
/**
* 算法结束时时间
*/
public static void endTime() {
//结束时间
Date date2 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String end = simpleDateFormat.format(date2);
System.out.println("结束时间为:" + end);
}
/**
* 冒泡排序
* O(n^2)
* @param arr
*/
public static void bubbleSort(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]) {
flag = true;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
//无逆序,跳出循环
if (!flag) {
break;
} else {
flag = false;
}
}
}
}
选择排序
SelectSort.java
package com.Taking.sort;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Demo class
* 选择排序
*
* @author Taking
* @date 2020/5/20
*/
public class SelectSort {
public static void main(String[] args) {
System.out.println("------------------------");
System.out.println("*******选择排序算法*******");
startTime();
selectSort(randomArray());
endTime();
System.out.println("------------------------");
}
/**
* 产生长度为100000的随机数组
*/
public static int[] randomArray() {
int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
//随机产生数据
arr[i] = (int) (Math.random() * 100000);
}
return arr;
}
/**
* 算法开始时时间
*/
public static void startTime() {
//开始时间
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String start = simpleDateFormat.format(date1);
System.out.println("开始时间为:" + start);
}
/**
* 算法结束时时间
*/
public static void endTime() {
//结束时间
Date date2 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String end = simpleDateFormat.format(date2);
System.out.println("结束时间为:" + end);
}
/**
* 选择排序
* O(n^2)
* @param arr
*/
public static void selectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
//假设最小值的坐标为i
int minIndex = i;
//假设最小值为arr[i]
int min = arr[i];
for (int j = i + 1; j < arr.length; j++) {
//若arr[j]小于min,则把下标赋值给minIndex,把值赋给min
if (min > arr[j]) {
minIndex = j;
min = arr[j];
}
}
//一趟比较结束,交换位置,确定最小数的位置
arr[minIndex] = arr[i];
arr[i] = min;
}
}
}
插入排序
InsertSort.java
package com.Taking.sort;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Demo class
* 插入排序
*
* @author Taking
* @date 2020/5/20
*/
public class InsertSort {
public static void main(String[] args) {
System.out.println("------------------------");
System.out.println("*******插入排序算法*******");
startTime();
insertSort(randomArray());
endTime();
System.out.println("------------------------");
}
/**
* 产生长度为100000的随机数组
*/
public static int[] randomArray() {
int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
//随机产生数据
arr[i] = (int) (Math.random() * 100000);
}
return arr;
}
/**
* 算法开始时时间
*/
public static void startTime() {
//开始时间
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String start = simpleDateFormat.format(date1);
System.out.println("开始时间为:" + start);
}
/**
* 算法结束时时间
*/
public static void endTime() {
//结束时间
Date date2 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String end = simpleDateFormat.format(date2);
System.out.println("结束时间为:" + end);
}
/**
* 插入排序
* O(n^2)
* @param arr
*/
public static void insertSort(int[] arr) {
// 定义待插入的变量,插入位置的索引
int insertVal = 0;
int insertIndex = 0;
for(int i=0;i<arr.length-1;i++){
//待插入的数赋值
insertVal = arr[i+1];
//与待插入的位置的数进行比较
insertIndex = i;
//进行判断:索引越界或者找到位置,跳出循环
while(insertIndex>=0 && insertVal<arr[insertIndex]){
arr[insertIndex+1] = arr[insertIndex];
insertIndex--;
}
if(insertIndex+1 != i){
arr[insertIndex+1] = insertVal;
}
}
}
}
希尔排序
ShellSort.java
package com.Taking.sort;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Demo class
* 希尔排序
*
* @author Taking
* @date 2020/5/21
*/
public class ShellSort {
public static void main(String[] args) {
shellSort(randomArray());
shellSort2(randomArray());
}
/**
* 产生长度为100000的随机数组
*/
public static int[] randomArray() {
int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
//随机产生数据
arr[i] = (int) (Math.random() * 100000);
}
return arr;
}
/**
* 算法开始时时间
*/
public static void startTime() {
//开始时间
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String start = simpleDateFormat.format(date1);
System.out.println("开始时间为:" + start);
}
/**
* 算法结束时时间
*/
public static void endTime() {
//结束时间
Date date2 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String end = simpleDateFormat.format(date2);
System.out.println("结束时间为:" + end);
}
/**
* 希尔排序
* O(n^2*log(n))
* @param arr
*/
public static void shellSort(int[] arr) {
System.out.println("------------------------");
System.out.println("*******希尔排序算法(交换)*******");
startTime();
//临时变量
int temp = 0;
int count = 0;
for(int gap = arr.length/2 ; gap>0 ; gap/=2){
for(int i=gap; i<arr.length ; i++){
for(int j=i-gap;j>=0;j-=gap){
if(arr[j]>arr[j+gap]){
temp = arr[j];
arr[j] =arr[j+gap];
arr[j+gap] = temp;
}
}
}
}
endTime();
System.out.println("------------------------");
}
/**
* 希尔排序
* O(n*log(n))
* @param arr
*/
public static void shellSort2(int[] arr) {
System.out.println("------------------------");
System.out.println("*******希尔排序算法(移位)*******");
startTime();
//临时变量
int temp=0;
//分组
for(int gap=arr.length/2;gap>0;gap/=2){
for(int i=gap;i<arr.length;i++){
int j=i;
temp = arr[j];
if(arr[j-gap]>arr[j]){
while(j-gap>=0 && temp < arr[j-gap]){
arr[j] = arr[j-gap];
j-=gap;
}
arr[j]=temp;
}
}
}
endTime();
System.out.println("------------------------");
}
}
快速排序
QuickSort.java
package com.Taking.sort;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Demo class
* 快速排序
*
* @author Taking
* @date 2020/5/21
*/
public class QuickSort {
public static void main(String[] args) {
System.out.println("------------------------");
System.out.println("*******快速排序算法*******");
startTime();
quickSort(randomArray(), 0, randomArray().length - 1);
endTime();
System.out.println("------------------------");
}
/**
* 产生长度为100000的随机数组
*/
public static int[] randomArray() {
int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
//随机产生数据
arr[i] = (int) (Math.random() * 100000);
}
return arr;
}
/**
* 算法开始时时间
*/
public static void startTime() {
//开始时间
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String start = simpleDateFormat.format(date1);
System.out.println("开始时间为:" + start);
}
/**
* 算法结束时时间
*/
public static void endTime() {
//结束时间
Date date2 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String end = simpleDateFormat.format(date2);
System.out.println("结束时间为:" + end);
}
/**
* 快速排序
* O(n^log(n))
* @param arr
* @param left
* @param right
*/
public static void quickSort(int[] arr, int left, int right) {
//定义两个索引
int l = left;
int r = right;
//中值赋值给pivot
int pivot = arr[(left + right) / 2];
int temp = pivot;
while (l < r) {
//中轴左边的数值小于中轴值,则右移,大于中轴值,跳出循环
while (arr[l] < pivot) {
l++;
}
//中轴右边的数值大于中轴值,则左移,小于中轴值,跳出循环
while (arr[r] > pivot) {
r--;
}
//将左边比中轴值大的数与右边比中轴值小的数交换位置
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//如果l>=r跳出循环
if (l >= r) {
break;
}
//如果左边存在等于中轴值的数,则r左移
if (arr[l] == pivot) {
r--;
}
//如果右边存在等于中轴值的数,则l右移
if (arr[r] == pivot) {
l++;
}
}
//防止栈溢出
if (l == r) {
l++;
r--;
}
//向左递归
if (left < r) {
quickSort(arr, left, r);
}
//向右递归
if (right > l) {
quickSort(arr, l, right);
}
}
}
归并排序
MergeSort.java
package com.Taking.sort;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Demo class
* 归并排序
*
* @author Taking
* @date 2020/5/21
*/
public class MergeSort {
public static void main(String[] args) {
System.out.println("------------------------");
System.out.println("*******归并排序算法*******");
startTime();
mergeSort(randomArray(),0,randomArray().length-1,new int[randomArray().length]);
endTime();
System.out.println("------------------------");
}
/**
* 产生长度为100000的随机数组
*/
public static int[] randomArray() {
int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
//随机产生数据
arr[i] = (int) (Math.random() * 100000);
}
return arr;
}
/**
* 算法开始时时间
*/
public static void startTime() {
//开始时间
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String start = simpleDateFormat.format(date1);
System.out.println("开始时间为:" + start);
}
/**
* 算法结束时时间
*/
public static void endTime() {
//结束时间
Date date2 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String end = simpleDateFormat.format(date2);
System.out.println("结束时间为:" + end);
}
/**
* 归并排序
* O(n^log(n))
* @param arr
* @param left
* @param right
* @param temp
*/
public static void mergeSort(int[] arr,int left,int right,int[] temp) {
if(left<right){
//确定中值索引
int mid = (left+right)/2;
//左递归
mergeSort(arr,left,mid,temp);
//右递归
mergeSort(arr,mid+1,right,temp);
//合并
merge(arr,left,mid,right,temp);
}
}
/**
* 合并过程
* @param arr
* @param left
* @param mid
* @param right
* @param temp 临时数组
*/
public static void merge(int[] arr,int left,int mid,int right,int[] temp){
//分成左右两组
//左索引
int i=left;
//右索引
int j=mid+1;
//临时数组索引
int t = 0;
//比较左右两组数的大小
while(i<=mid && j<=right){
//如果左边小,存入临时数组,左索引右移,临时数组索引右移
if(arr[i]<=arr[j]){
temp[t] = arr[i];
t++;
i++;
}else{
//如果右边小,存入临时数组,右索引右移,临时数组索引右移
temp[t] = arr[j];
t++;
j++;
}
}
//如果右组都已存入临时数组,则将左组剩下的值依次存入临时数组
while(i<=mid){
temp[t] = arr[i];
t++;
i++;
}
//如果左组都已存入临时数组,则将右组剩下的值依次存入临时数组
while(j<=right){
temp[t] = arr[j];
t++;
j++;
}
//将临时数组置0,将临时数组的值赋值给原数组
t=0;
//定义原数组索引
int tl = left;
while(tl<=right){
arr[tl] = temp[t];
tl++;
t++;
}
}
}
基数排序
RadixSort.java
package com.Taking.sort;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Demo class
* 基数排序
*
* @author Taking
* @date 2020/5/22
*/
public class RadixSort {
public static void main(String[] args) {
System.out.println("------------------------");
System.out.println("*******基数排序算法*******");
startTime();
radixSort(randomArray());
endTime();
System.out.println("------------------------");
}
/**
* 产生长度为100000的随机数组
*/
public static int[] randomArray() {
int[] arr = new int[100000];
//若数组过大会出现:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
for (int i = 0; i < arr.length; i++) {
//随机产生数据
arr[i] = (int) (Math.random() * 100000);
}
return arr;
}
/**
* 算法开始时时间
*/
public static void startTime() {
//开始时间
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String start = simpleDateFormat.format(date1);
System.out.println("开始时间为:" + start);
}
/**
* 算法结束时时间
*/
public static void endTime() {
//结束时间
Date date2 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String end = simpleDateFormat.format(date2);
System.out.println("结束时间为:" + end);
}
/**
* 基数排序
* O(d(n+r))
* @param arr
*/
public static void radixSort(int[] arr) {
//定义一个二维数组,[桶的个数,桶中存放的数据]
int[][] bucket = new int[10][arr.length];
//定义一个一维数组,用于计数存放某个桶中的元素个数
int[] bucketElementCounts = new int[10];
//确定元素中最高位
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
int length = (max + "").length();
//有几位数,就循环几次
for (int i = 0, n = 1; i < length; i++, n *= 10) {
//确定相应位数值,并存放到对应桶中
for (int j = 0; j < arr.length; j++) {
int digitOfElement = arr[j] / n % 10;
//存放桶中,然后计数+1
bucket[digitOfElement][bucketElementCounts[digitOfElement]++] = arr[j];
}
//定义一个原数组的索引
int index = 0;
//遍历二维数组,按顺序存放到原数组
for (int j = 0; j < bucket.length; j++) {
if (bucketElementCounts[j] != 0) {
for (int k = 0; k < bucketElementCounts[j]; k++) {
arr[index++] = bucket[j][k];
}
}
//将每个桶的计数值清零,方便下一次计数
bucketElementCounts[j] = 0;
}
}
}
}
堆排序
HeapSort.java
package com.Taking.sort;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Demo class
* 堆排序
*
* @author Taking
* @date 2020/5/22
*/
public class HeapSort {
public static void main(String[] args) {
System.out.println("------------------------");
System.out.println("*******堆排序算法*******");
startTime();
heapSort(randomArray());
endTime();
System.out.println("------------------------");
}
/**
* 产生长度为100000的随机数组
*/
public static int[] randomArray() {
int[] arr = new int[100000];
for (int i = 0; i < arr.length; i++) {
//随机产生数据
arr[i] = (int) (Math.random() * 100000);
}
return arr;
}
/**
* 算法开始时时间
*/
public static void startTime() {
//开始时间
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String start = simpleDateFormat.format(date1);
System.out.println("开始时间为:" + start);
}
/**
* 算法结束时时间
*/
public static void endTime() {
//结束时间
Date date2 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String end = simpleDateFormat.format(date2);
System.out.println("结束时间为:" + end);
}
/**
* 构造大顶堆
*
* @param arr
* @param i
* @param length
*/
public static void constructLargeHeap(int[] arr, int i, int length) {
//将非子叶点的值赋值给临时变量temp
int temp = arr[i];
//比较左右孩子节点大小,将值大的与其父节点比较
//定义孩子节点索引k
for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
//左孩子节点小于右孩子节点,将索引k右移
if (k + 1 < length && arr[k] < arr[k + 1]) {
k++;
}
//大于互换位置
if (arr[k] > temp) {
arr[i] = arr[k];
i = k;
} else {
//小于则跳出循环
break;
}
//将非叶子节点的值与最大值的值的位置交换
arr[i] = temp;
}
}
/**
* 堆排序
* O(n^log(n))
* @param arr
*/
public static void heapSort(int[] arr) {
//定义临时变量
int temp = 0;
//构造大顶堆
for (int i = arr.length / 2 - 1; i >= 0; i--) {
constructLargeHeap(arr, i, arr.length);
}
//将堆顶数与堆末尾的数进行交换,使得最大值在数组最后
for (int j = arr.length - 1; j >= 0; j--) {
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
//交换完,再对最大值前面的子数组构造大顶堆
constructLargeHeap(arr, 0, j);
}
}
}
算法速度测试(针对随机数组)
运行环境:Intel® Core™ i5-7300HQ CPU @ 2.50GHz 2.5GHz RAM:8.00GB
排序算法\数量级 | 100000 | 500000 | 1000000 | 5000000 | 10000000 |
---|---|---|---|---|---|
冒泡排序 | 20s | 400s | 1600s | - - | - - |
选择排序 | 5s | 96s | 400s | - - | - - |
插入排序 | 1s | 26s | 100s | - - | - - |
希尔排序(交换|移位) | 12s~14s|<1s | 240s|1s | 913s|1s | - - | - - |
快速排序 | <1s | <1s | <=1s | 1s | 2s |
归并排序 | <1s | <=1s | <=1s | 1~2s | 2~3s |
基数排序 | <1s | <1s | <=1s | 1s | 1s |
堆排序 | <1s | <1s | <=1s | 1~2s | 3s |