排序,即按照特定规则改变一组元素的顺序。其目的在于高效地进行查找。比如有一组数,我们要从中取出第N大的数。如果我们没有排序的话,则每次都要进行多次比较,十分麻烦。以下是用java实现一些排序算法的代码和理解。对于一组元素,要采取什么排序算法,要根据元素的特征来进行选择。在一般情况下,快速排序是最快的通用排序算法。如果元素之间的交换相对于元素之间的比较需要耗费大的多,则可以选择交换次数最少的选择排序。如果元素的的顺序接近有序,则可以选择插入排序或者希尔排序。如果元素的数量非常大,则可以选择希尔排序或者归并排序。如果元素数量非常大且允许占用更多的存储空间,则可以选择归并排序或者归并排序组合其他排序算法。如果比起平均情况下的性能,更注重最坏情况时的性能,且不能占用太多的存储空间,可以选择堆排序。
package template;
import javax.print.attribute.standard.Copies;
import java.util.Scanner;
public class SortAlgorithm {
/*
名字:选择排序
简介:首先找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置,
再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置.
如此反复,直到整个数组排序完毕.不断地在剩余元素中选择最小的元素放在剩余元素的第一位.
分析:
1,运行时间和输入无关.排序一组随机的元素和一组有序的元素时间是一样的.
2,数据移动是最少的.假设数组长度为N,则只会交换N次.
*/
public static void selection(Comparable[] a) {
int N = a.length;
for(int i = 0; i < N; i++) {
int min = i;
for(int j = i+1; j < N; j++) {
if(a[j].compareTo(a[min]) < 0) {
min = j;
}
}
Comparable t = a[i];
a[i] = a[min];
a[min] = t;
}
}
/*
名字:插入排序
简介:当前索引的左边是有序的,右边是无序的.
索引从二个元素开始,当索引指向一个元素时.在左边找到合适的位置并插入.
并接着往右移动,进行同样的操作.直到到达最右端.
分析:插入排序所用时间取决于输入元素的初始位置.更接近有序的数组,所用时间越少.
*/
public static void insertion(Comparable[] a) {
int N = a.length;
for(int i = 1; i < N; i++) {
for(int j = i; j > 0 && a[j].compareTo(a[j-1]) < 0; j--) {
Comparable t = a[j];
a[j] = a[j-1];
a[j-1] = t;
}
}
}
/*
名字:希尔排序
简介:通过一个步长序列,将一组元素分为几组,再对这几组元素进行插入排序.
之后依次缩小步长,对各组元素进行插入排序.直到步长为1.
分析:插入排序的改进,有利于对大型数组进行排序.
*/
public static void shell(Comparable[] a) {
int N = a.length;
int h = 1;
while(h < N/3)
h = 3*h + 1;
while(h >= 1) {
for(int i = h; i < N; i++) {
for(int j = i; j >= h && a[j].compareTo(a[j-h]) < 0; j-=h) {
Comparable t = a[j];
a[j] = a[j-h];
a[j-h] = t;
}
}
h = h/3;
}
}
/*
名字:归并排序
简介:归并是指将两组有序的元素,组合成一组有序的元素.
归并排序是递归的将要排序的元素分为对等的两组,接着一一归并.
分析:适合排序大型数组,与其他排序方式组合.
*/
private static Comparable[] aux;
public static void merge(Comparable[] a, int lo, int mid, int hi) {
//lo是a数组的第一个元素的坐标,hi是数组最后一个元素数组的坐标.
//mid是数组中间元素的坐标.
int i = lo, j = mid+1;
for(int k = lo; k <= hi; k++) {
aux[k] = a[k];
}
for(int k = lo; k <= hi; k++) {
if(i > mid) a[k] = aux[j++];
else if(j > hi) a[k] = aux[i++];
else if(aux[i].compareTo(aux[j]) < 0) a[k] = aux[i++];
else a[k] = aux[j++];
}
}
//自顶向下的归并排序
public static void mergeSort(Comparable[] a) {
aux = new Comparable[a.length];
mergeSort(a, 0, a.length-1);
}
private static void mergeSort(Comparable[] a, int lo, int hi) {
if(hi <= lo)
return;
int mid = lo + (hi-lo)/2;
mergeSort(a, lo, mid);
mergeSort(a, mid+1, hi);
merge(a, lo, mid, hi);
}
//自底向上的归并排序
public static void mergeSortBU(Comparable[] a) {
int N = a.length;
aux = new Comparable[N];
for(int sz = 1; sz < N; sz = sz*2) {
for(int lo = 0; lo+sz < N; lo+=sz+sz) {
merge(a, lo, lo+sz-1, Math.min(lo+sz+sz-1, N-1));
}
}
}
/*
名字:快速排序
简介:在将要排序的数组里面找一个切分位置,把比其小的放在左边,比其大的放在右边.
然后递归地对左右两边进行相同的处理.
分析:在一般应用中比其他排序算法快.但是两种情况下效率会比较低下.
对于在排序过程中,切分不平衡,会会十分低效.
对于小数组,快速排序比插入排序慢.
*/
public static void quick(Comparable[] a) {
quickSort(a, 0, a.length-1);
}
public static void quickSort(Comparable[] a, int lo, int hi) {
if(lo >= hi)
return;
//找出切分位置
int i = lo, j = hi+1;
Comparable t;
while(true) {
while(a[++i].compareTo(a[lo]) < 0 && i!=hi);
while(a[--j].compareTo(a[lo]) > 0 && j!=lo);
if(i >= j)
break;
t = a[i];
a[i] = a[j];
a[j] = t;
}
t = a[lo];
a[lo] = a[j];
a[j] = t;
quickSort(a, lo, j);
quickSort(a, j+1, hi);
}
/*
名字:堆排序
简介:本质上为优先队列,先进行堆有序化, 在不断将优先级高的元素放置到最后一位,剩余再进行有序化,
不断的重复此操作,直到剩下最后一个元素。
分析:堆排序一般比快排慢,但最差的时间为nlogn,比快排好
*/
public static void heapSort(Comparable[] a) {
int N = a.length;
for(int k = N/2; k >= 1; k--)
sink(a, k, N);
while(N > 1) {
Comparable t = a[N-1];
a[N-1] = a[0];
a[0] = t;
sink(a, 1, --N);
}
}
public static void sink(Comparable[] a, int begin, int end) {
while(begin*2 <= end) {
int i = begin*2;
//此分支选择主要比较begin结点的左右子结点,找到更大优先级的字结点
if(i < end && a[i-1].compareTo(a[i]) < 0)
i++;
if(a[begin-1].compareTo(a[i-1]) >= 0)
break;
Comparable t = a[begin-1];
a[begin-1] = a[i-1];
a[i-1] = t;
begin = i;
}
}
public static void main(String[] args) {
java.util.Scanner sc = new java.util.Scanner(System.in);
String s = sc.nextLine();
Integer[] a = new Integer[]{4,6,2,9,1};
if("selection".equals(s))
SortAlgorithm.selection(a);
else if("insertion".equals(s))
SortAlgorithm.insertion(a);
else if("shell".equals(s))
SortAlgorithm.shell(a);
else if("merge".equals(s))
SortAlgorithm.mergeSort(a);
else if("mergeBU".equals(s))
SortAlgorithm.mergeSortBU(a);
else if("quick".equals(s))
SortAlgorithm.quick(a);
else if("heap".equals(s))
SortAlgorithm.heapSort(a);
for(int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
}
}