package com.sort;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* 各种排序,包含插入排序、选择排序、交换排序和归并排序
* 插入排序:直接插入排序和希尔排序
* 选择排序:直接选择排序和堆排序
* 交换排序:冒泡排序和快速排序
* 归并排序:
* @author msk
*
*/
public class Sort {
public static void main(String[] args) {
BufferedReader br;
int i;
try {
Object[] a = {5,4,3,2,1};
br = new BufferedReader(new InputStreamReader(System.in));
while(true){
i = select(br);
switch(i){
case 1:
insertSort(a);
break;
case 2:
selectSort(a);
break;
case 3:
heapSort(a);
break;
case 4:
bubbleSort(a);
break;
case 5:
quickSort(a);
break;
case 6:
mergeSort(a);
break;
case 7:
System.out.println("退出程序!");
System.exit(1);
default:
System.out.println("输入出错,退出程序!");
System.exit(1);
}
}
} catch (Exception e) {
System.out.println("操作异常!" + e);
}
}
public static int select(BufferedReader f){
System.out.println("\n输入编号选择排序方式:");
System.out.println("1:进行直接插入排序;");
System.out.println("2:进行直接选择排序;");
System.out.println("3:堆排序;");
System.out.println("4:冒泡排序;");
System.out.println("5:快速排序;");
System.out.println("6:归并排序;");
System.out.println("7:退出运行。\n");
System.out.print("请输入您的选择:");
try {
String s = f.readLine();
int n = Integer.parseInt(s);
while(n < 0 || n > 7){
System.out.println("输入数字有误!重输:");
s = f.readLine();
n = Integer.parseInt(s);
}
System.out.println();
return n;
} catch (Exception e) {
System.out.println("操作异常!" + e);
return 0;
}
}
/***************直接插入排序*****************/
public static void insertSort(Object[] a){ //时间复杂度为O(n^2),空间复杂度为O(1),稳定排序
for(int i = 1; i < a.length; i ++){
for(int j = i; j > 0; j --){
if(((Comparable)a[j]).compareTo(a[j - 1]) < 0){
Object temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
}
}
System.out.println("直接插入排序结果为:");
for(int i = 0; i < a.length; i ++)
System.out.print(a[i] + " ");
System.out.println();
System.out.println("它的时间复杂度:平均情况为O(n^2),最好情况为O(n),最坏情况为O(n^2)");
System.out.println("空间复杂度为O(1)");
System.out.println("属于稳定排序");
}
/********************直接选择排序**************************/
public static void selectSort(Object[] a){ //时间复杂度为O(n^2),空间复杂度为,不稳定排序
for(int i = 0; i < a.length; i ++){
for(int j = i + 1; j < a.length; j ++){
if(((Comparable)a[i]).compareTo(a[j]) > 0){
Object temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
System.out.println("直接选择排序结果为:");
for(int i = 0; i < a.length; i ++)
System.out.print(a[i] + " ");
System.out.println();
System.out.println("它的时间复杂度:平均情况为O(n^2),最好情况为O(n^2),最坏情况为O(n^2)");
System.out.println("空间复杂度为O(1)");
System.out.println("属于不稳定排序");
}
/********************堆排序开始*********************/
public static void sift(Object[] a, int n, int i){ //对a[i]进行筛运算,称为构成堆的过程
Object x = a[i]; //把待筛结点的值暂存于x中
int j = 2 * i + 1; //a[j]是a[i]的左孩子
while(j <= n - 1){ //当a[i]的左孩子不为空时执行循环
if(j < n - 1 && ((Comparable)a[j]).compareTo(a[j + 1]) < 0)
j ++; //若存在右孩子并排序码较大,则把j修改为右孩子的下标
if(((Comparable)x).compareTo(a[j]) < 0){
a[i] = a[j]; //把a[j]调到双亲位置
i = j;j = 2 * i + 1; //修改i和j的值,以便继续向下筛
}
else break; //查找到x的最终位置为i,退出循环
}
a[i] = x;
}
public static void heapSort(Object[] a){ //利用堆排序的方法对数组a中的n个元素进行排序,时间复杂度为O(n^2),O(nlog2n),空间复杂度为O(1)
for(int i = a.length / 2 - 1; i >= 0; i --)
sift(a, a.length, i);
for(int i = 1; i <= a.length - 1; i ++){ //进行n-1次循环完成堆排序
//将树根结点的值同当前区间内最后一个结点的值对换
Object x = a[0];
a[0] = a[a.length - i];
a[a.length - i] = x;
//筛a[0]结点,得到前n-1个结点的堆
sift(a,a.length - i,0);
}
System.out.println("堆排序结果为:");
for(int i = 0; i < a.length; i ++)
System.out.print(a[i] + " ");
System.out.println();
System.out.println("它的时间复杂度:平均情况为O(nlogn),最好情况为O(nlogn),最坏情况为O(nlogn)");
System.out.println("空间复杂度为O(1)");
System.out.println("属于不稳定排序");
}
/********************堆排序结束*********************/
/********************冒泡排序*********************/
public static void bubbleSort(Object[] a){
for(int i = 1; i < a.length;i ++){
for(int j = a.length - 1; j >=i; j --){
if(((Comparable)a[j]).compareTo(a[j - 1]) < 0){
Object x = a[j];
a[j] = a[j - 1];
a[j - 1] = x;
}
}
}
System.out.println("冒泡排序结果为:");
for(int i = 0; i < a.length; i ++)
System.out.print(a[i] + " ");
System.out.println();
System.out.println("它的时间复杂度:平均情况为O(n^2),最好情况为O(n),最坏情况为O(n^2)");
System.out.println("空间复杂度为O(1)");
System.out.println("属于稳定排序");
}
/********************快速排序开始***************************/
public static int partition(Object[] a,int s, int t){ // 进行快速排序中完成一次划分排序的算法描述
int i = s,j = t;
Object x = a[i ++];
while(i <= j){
//从前向后顺序查找一个大于基准值需向后半区间交换的元素
while(i <= j && ((Comparable)a[i]).compareTo(x) <= 0) i ++;
//从后向前顺序查找一个小于基准值需向前半区间交换的元素
while(j >= i && ((Comparable)a[j]).compareTo(x) >= 0) j --;
//当条件成立时交换a[i]和a[j]的值
if(i < j){
Object temp = a[i];
a[i] = a[j];
a[j] = temp;
i ++; j --;
}
}
a[s] = a[j]; a[j] = x; //交换a[s]和a[j]的值,得到前后两个子区间
return j;
}
public static void quickRecursion(Object[] a, int s, int t){ //通过调用partition算法进行快速排序的递归算法描述
int j = partition(a, s, t);
if(s < j - 1) quickRecursion(a, s, j - 1); //在左区间内超过一个元素时递归排序左区间
if(t > j + 1) quickRecursion(a, j + 1, t); //在右区间超过一个元素时递归排序右区间
}
public static void quickSort(Object[] a){
//对数组a[0]到a[n - 1]进行快速排序
quickRecursion(a, 0, a.length - 1);
System.out.println("快速排序结果为:");
for(int i = 0; i < a.length; i ++)
System.out.print(a[i] + " ");
System.out.println();
System.out.println("它的时间复杂度:平均情况为O(nlogn),最好情况为O(nlogn),最坏情况为O(n^2)");
System.out.println("空间复杂度为O(nlogn)");
System.out.println("属于不稳定排序");
}
/*************************快速排序结束*************************/
/***********************归并排序开始************************/
public static void twoMerge(Object[] a, Object[] r, int s, int m, int t){ //二路归并算法描述
//把相邻有序表a[s]~a[m]和a[m+1]~a[t]归并为一个有序表r[s]~r[t]
int i,j,k;
//分别给指示每个有序表元素位置的指针赋初值
i = s;
j = m + 1;
k = s;
//两个有序表中同时存在未归并元素时的处理过程
while(i <= m && j <= t)
if(((Comparable)a[i]).compareTo(a[j]) <= 0){
r[k] = a[i];
i ++; k ++;
}
else{
r[k] = a[j];
j ++; k ++;
}
//对第一个有序表中可能存在的未归并元素进行处理
while(i <= m){
r[k] = a[i];
i ++; k++;
}
//对第二个有序表中可能存在的未归并元素进行处理
while(j <= t){
r[k] = a[j];
j ++; k ++;
}
}
public static void mergePass(Object[] a, Object[] r, int n, int len){ //进行一趟二路归并的算法描述
//把数组a[n]中每个长度为len的有序表两两归并到数组r[n]中
int p = 0; //p为每一对待合并表的第一个元素的下标,初值为0
while(p + 2 * len - 1 <= n - 1){ //两两归并长度为len的有序表
twoMerge(a, r, p, p + len - 1, p + 2 * len - 1);
p += 2 * len;
}
if(p + len - 1 < n - 1) //归并最后两个长度不等的有序表
twoMerge(a, r, p, p + len - 1, n - 1);
else //把剩下的最后一个有序表复制到r中
for(int i = p; i <= n - 1; i ++)
r[i] = a[i];
}
public static void mergeSort(Object[] a){
//采用归并排序的方法对数组a中的n个记录进行排序
Object[] r = new Object[a.length];
int len = 1;
while(len < a.length){
//从a归并到r中,得到每个有序表的长度为2*len
mergePass(a, r, a.length, len);
//修改len的值为r中的每个有序表的长度
len *= 2;
//从r归并到a中,得到每个有序表的长度为2*len
mergePass(r, a, a.length, len);
//修改len的值为a中的每个有序表的长度
len *= 2;
}
System.out.println("归并排序结果为:");
for(int i = 0; i < a.length; i ++)
System.out.print(a[i] + " ");
System.out.println();
System.out.println("它的时间复杂度:平均情况为O(nlogn),最好情况为O(nlogn),最坏情况为O(n^2)");
System.out.println("空间复杂度为O(1)");
System.out.println("属于稳定排序");
}
/***********************归并排序结束************************/
}