/**
* @Author herky
* @Date 2019/8/7 9:47
* @Version 1.0
*/
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 各种排序
*/
public class Sort {
/**
* 冒泡排序
* 两两相互比较,将大的数放后面,这样每次循环找出最大的值放在后面,时间复杂度为n^2 速度最慢
*/
public static void bubbleSort(int[] arg){
int temp=0;
for (int i=0 ;i<arg.length ; i++){
boolean flag =false;
for (int j=0;j<arg.length-i-1;j++){
if(arg[j]>arg[j+1]){
flag=true;
temp=arg[j];
arg[j]=arg[j+1];
arg[j+1]=temp;
}
}
if(!flag){
break;
}
}
}
/**
* 选择排序
* 每次循环将数组中最小的值放在前面,时间复杂度为n^2 速度比冒泡快
* @param args
*/
public static void selectSort(int[] args){
for(int i =0;i<args.length-1;i++){
int min =i;
int minValue=args[min];
for(int j=i+1;j<args.length;j++){
if(args[j]<args[min]){
min=j;
}
}
if(min!=i){
args[i]=args[min];
args[min]=minValue;
}
}
}
/**
* 插入排序,每次将数组的下一个元素插入到前面
* 例【5,3,1,7】
* 第一次【3,5,1,7】
* 第二次【1,3,5,7】
* 第三次【1,3,5,7】
* 时间复杂度n^2 速度比选择快
* @param args
*/
public static void insertSort(int[] args) {
//从第一个数后开始插入
for (int i = 1; i < args.length; i++) {
int index = i - 1;
int indexValue = args[i];
while (index>=0 && args[index] > indexValue){
args[index+1]=args[index];
index--;
}
if(index!=i-1){
args[index+1]=indexValue;
}
System.out.println();
}
}
/**
* 希尔排序 是插入排序的加强版
* 将每次的数据进行分组,每次分组的长度为length=length/2
* 交换法是每次将每个组里面的数进行排序交换 由于每次循环涉及到交换,所以效率低
* 移位法是每次将每个组中最小的值放到最前面
* @param args
*/
public static void shellSort(int[] args){
//交换法,效率低,速度慢
// for (int i=args.length/2;i>0;i=i/2){
// for(int j=i;j<args.length;j++){
// for(int k=j-i;k+i<args.length;k=k+i){
// if(args[k]>args[k+i]){
// int temp=args[k];
// args[k]=args[k+i];
// args[k+i]=temp;
// }
// }
// }
// }
//移位法
for (int gap=args.length/2;gap>0;gap=gap/2){
for(int i =gap;i<args.length;i++){
int j=i;
int value = args[i];
if(args[i]<args[i-gap]){
while (j >= gap && value < args[j-gap]){
args[j]=args[j-gap];
j=j-gap;
}
args[j]=value;
}
}
}
}
/**
* 快速排序
* 选择一个基数,将比基数大的数放在右边,比基数小的放在左边
* 比希尔排序略快
* @param args
*/
public static void quickSort(int[] args,int left,int right){
if(left<right){
int l=left;
int r=right;
int temp=args[left];
while(l<r){
while(args[r]>=temp && l<r){
r--;
}
args[l]=args[r];
while (args[l]<=temp && l<r){
l++;
}
args[r]=args[l];
}
args[l]=temp;
quickSort(args,left,l-1);
quickSort(args,r+1,right);
}
}
/***
* 归并排序
* @param args
* @param left
* @param right
* 采用分治法思想,先将数组划分为很多个部分,然后进行排序合并。
*/
public static void mergeSort(int[] args,int left,int right){
if(left == right){
return;
}
else{
int mid=(left+right)/2;
//对左边进行划分
mergeSort(args,left,mid);
//对右边进行划分
mergeSort(args,mid+1,right);
merge(args,left,right,mid);
}
}
/**\
* 合并操作
* @param args 要合并和排序的数组
* @param left 数组的左边开始部分
* @param right 数组的右边结束部分
* @param mid 分开数组的中间值
*/
public static void merge(int[] args,int left,int right,int mid){
int leftArgs[] = new int[mid-left+1];
int rightArgs[]=new int[right-mid];
for (int i=left;i<mid+1;i++){
leftArgs[i-left]=args[i];
}
for (int j=mid+1;j<=right;j++){
rightArgs[j-mid-1]=args[j];
}
int l=0,r=0,i=left;
while(l<leftArgs.length&&r<rightArgs.length){
if(leftArgs[l]>rightArgs[r]){
args[i]=rightArgs[r];
r++;
i++;
}else{
args[i]=leftArgs[l];
l++;
i++;
}
}
//如果左边数组还有则全部放进数组
while (l<leftArgs.length){
args[i]=leftArgs[l];
i++;
l++;
}
//如果右边数组还有则全部放进数组
while(r<rightArgs.length){
args[i]=rightArgs[r];
i++;
r++;
}
}
/**
* 基数排序 用空间换时间,当要排序的数很大的时候会花费很大的空间
* @param
*/
public static void radixSort(int[] array){
int maxLength=0;
int max=0;
for(int i=1;i<array.length;i++){
if(array[i]>array[i-1]){
max=i;
}
}
maxLength=(array[max]+"").length();//求出数组中最大的数得位数
int n=1;//代表位数对应的数:1,10,100...
int k=0;//保存每一位排序后的结果用于下一位的排序输入
int length=array.length;
int[][] bucket=new int[10][length];//排序桶用于保存每次排序后的结果,这一位上排序结果相同的数字放在同一个桶里
int[] order=new int[10];//用于保存每个桶里有多少个数字
while(n<Math.pow(10,maxLength))
{
for(int num:array) //将数组array里的每个数字放在相应的桶里
{
int digit=(num/n)%10;
bucket[digit][order[digit]]=num;
order[digit]++;
}
for(int i=0;i<10;i++)//将前一个循环生成的桶里的数据覆盖到原数组中用于保存这一位的排序结果
{
if(order[i]!=0)//这个桶里有数据,从上到下遍历这个桶并将数据保存到原数组中
{
for(int j=0;j<order[i];j++)
{
array[k]=bucket[i][j];
k++;
}
}
order[i]=0;//将桶里计数器置0,用于下一次位排序
}
n*=10;
k=0;//将k置0,用于下一轮保存位排序结果
}
}
public static void main(String[] args) {
int[] i=new int[10];
for (int j=0;j<i.length;j++){
//(数据类型)(最小值+Math.random()*(最大值-最小值+1))
i[j]= (int)(1+Math.random()*(80000-1+1));
}
System.out.println("排序前数组"+Arrays.toString(i));
radixSort(i);
System.out.println("基数排序"+Arrays.toString(i));
quickSort(i,0,i.length-1);
System.out.println("基数排序"+Arrays.toString(i));
System.out.println("快速排序"+Arrays.toString(i));
mergeSort(i,0,i.length-1);
System.out.println("归并排序"+Arrays.toString(i));
bubbleSort(i);
System.out.println("冒泡排序"+Arrays.toString(i));
insertSort(i);
System.out.println("插入排序"+Arrays.toString(i));
selectSort(i);
System.out.println("选择排序"+Arrays.toString(i));
shellSort(i);
System.out.println("希尔排序"+Arrays.toString(i));
}
}
以上的排序都已经测试过,并且上面排序的执行顺序也打乱过,没有问题。