本文总结算法第四版中几大基本排序算法的实现,用Java语言描述。文章结构安排如下:
1.通用模板介绍
2.插入排序
3.选择排序
4.希尔排序
5.归并排序
6.快速排序
7.冒泡排序
通用模板介绍
通用模板将排序算法中的基本操作做了封装,如交换元素、比较元素大小等,可以使排序算法的主函数逻辑更简洁,增加代码的可读性。
public class Example {
//交换两个元素
public static void exch(Comparable[] a,int i,int j) {
Comparable temp = a[i];
a[i]=a[j];
a[j]=temp;
}
//从小到大排列
public static boolean less(Comparable v,Comparable w) {
return v.compareTo(w)<0;
}
//打印全部元素
public static void show(Comparable [] a) {
for(int i=0;i
插入排序
插入排序的操作设置两个扫描指针,i指针在外层循环,扫描方向为下标递增方向,指向的元素代表:此时为该元素寻找插入位置。j指针在内层循环,扫描方向与i指向元素相反。
public static void InsertSort(Comparable[] a) {
int N = a.length;
for(int i=1;i0 && less(a[j],a[j-1]);--j)
exch(a, j, j-1);
}
}
public static void insert_sort(int[] arr) {
if(arr == null || arr.length ==0) return;
for(int i=1;i0 && arr[j] < arr[j-1];--j) { //将arr[i]插入arr[i-1],arr[i-2]..中
int temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
}
}
}
选择排序
选择排序有两层循环,算法的核心思想是,每一轮循环都将当前最小的元素放在正确的位置上。外层循环的指针指向当前排序的位置,内层循环负责寻找当前最小的元素。
public static void SelectSort(Comparable[] a) {
int min=0;
int N = a.length;
for(int i=0;i
//选择排序,每次从当前序列中,选出最小的那个放在正确的位置上
public static void select_sort(int[] arr) {
if(arr == null || arr.length ==0) return;
for(int i=0;i
希尔排序
根据步长将待排数组划分为若干组,然后组内交换排序。
public static void ShellSort(Comparable[] a) {
int N = a.length;
for(int h=N/2;h>0;h/=2)
for(int i=h;i=h && less(a[i],a[j-h]);j-=h)
exch(a, i, j-h);
}
//希尔排序
public static void shell_sort(int[] arr) {
if(arr == null || arr.length ==0) return;
for(int h = arr.length/2;h>=1;h/=2) { //步长h
for(int i=h;i=0;j-=h) { //比较 arr[i-h],arr[i-2h],arr[i-3h]...
if(arr[j+h] < arr[j]) {
int temp = arr[j];
arr[j] = arr[j+h];
arr[j+h] = temp;
}
}
}
}
}
归并排序
本文介绍自顶向下的归并排序,采用递归方法实现,需要辅助数组aux[]。
private static void sort(Comparable []a,int low,int high) {
if(low>=high) return;
int mid = (low+high)/2;
sort(a,low, mid);
sort(a, mid+1, high);
merge(a, low, mid, high);
}
//两个数组归并
private static void merge(Comparable [] a,int low,int mid,int high) {
int i = low;
int j = mid+1;
int k;
for(k=low;k<=high;k++) aux[k]=a[k];
for(k=low;k<=high;k++) {
if(i>mid) a[k]=aux[j++];
else if(j>high) a[k]=aux[i++];
else if(less(a[j], a[i])) a[k]=a[j++];
else a[k]=a[i++];
}
}
public static void sort(Comparable[] a) {
aux = new Comparable [a.length];
sort(a, 0, a.length-1);
}
算法实现
class MergeSort
{
static int[] aux = null;
public static void main(String[] args)
{
int[] arr = {3,1,2,5,4,6,0,9,1,3};
aux = new int[arr.length];
merge_sort(arr);
for(int tmp:arr)
System.out.print(tmp+" ");
System.out.println();
}
public static void merge_sort(int[] arr) {
if(arr == null || arr.length ==0) return;
merge_sort(arr,0,arr.length-1);
}
private static void merge_sort(int[] arr, int low, int high) {
if(low >= high) return; //返回条件 取=,单个元素的时候不用排序
int mid = (low + high)/2;
merge_sort(arr,low,mid);
merge_sort(arr,mid+1,high);
merge(arr,low,mid,high);
}
private static void merge(int[] arr,int low,int mid,int high) {
if(low >= high) return;
for(int k = low;k<=high;k++) //每次merge都要复制aux
aux[k] = arr[k];
int i=low,j = mid+1;
for(int k=low;k<=high;k++) {
if(i>mid) arr[k] = aux[j++];
else if(j>high) arr[k] = aux[i++]; //注意是else if
else if(aux[i] < aux[j]) arr[k] = aux[i++];
else arr[k] = aux[j++];
}
}
}
快速排序
快速排序的核心函数是partition,用于确定分割点,然后分别对分割点左边和右边sort排序。快排设置头、尾两个指针i和j,相向而行进行扫描,以及一个比较标准val(通常为arr[low])。
private static void sort(Comparable[] a,int low,int high) {
if (high <= low) return;
int j = partition(a, low, high);
sort(a, low, j-1);
sort(a, j+1, high);
}
private static int partition(Comparable a[],int low,int high) {
//两个指针
int i = low;
int j = high+1;
Comparable v = a[low];
while(true) {
while(less(a[++i],v)) if(i==high) break;
while(less(v, a[--j])) if(j==low) break;
if(i>=j) break; //次轮结束标志
exch(a, i, j);
}
exch(a, low, j);
return j;
}
public static void sort(Comparable[] a) {
sort(a,0,a.length-1);
}
具体实现。
//整合优化
public static void quick_sort(int[] arr,int low,int high) {
if(low >= high) return;
//int j = partition(arr,low,high);
int i=low, j = high;
int x = arr[low]; //Pivot
while(i=x) --j; //从后向前找小于x的元素
if(i
冒泡排序
冒泡排序总是交换两个相邻的元素。每一轮冒泡,都将当前最小的元素固定在数组前列。
public static void bubble_sort(int[] arr) {
for(int i=0;ii;--j) {
if(arr[j] < arr[j-1]) { //每次总是交换相邻元素
int temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
}
}
}
}