参考http://blog.youkuaiyun.com/column/details/algorithm-easyword.html下载的
MoreWindows白话经典算法之七大排序第2版,
下图中“类别”有误,别管它
快速排序对100000长的数组居然java.lang.StackOverflowError!!!
整理到归并算法:
package p1;
import java.util.Date;
public class SortAlgorithm {
//----------------------------------------heap sort-----------------------------------------
//原始的Fix up, 类似于基于后移的插入排序
public static void minHeapFixup(int [] heap, int i){
int temp = heap[i];
int p = (i - 1)/2;
while(i > 0){
if(heap[p] <= temp)
break;
heap[i] = heap[p];//将比temp大的元素往下移
i = p;
p = (i - 1)/2;
}
heap[i] = temp;
}
//基于交换的Fix up
public static void minHeapFixup1(int [] heap, int i){//把i的元素向上调整, heap已经是一个堆了
int p;//pos的父节点
for(p = (i-1)/2 ; p>=0 && heap[p] > heap[i] ; i=p, p=(i-1)/2){
int temp = heap[p];
heap[p] = heap[i];
heap[i] = temp;
}
}
// Fix down
public static void minHeapFixdown(int [] heap, int i, int n){//把i元素向下调整,总节点数为n
int temp = heap[i];
int c = 2 * i + 1;//child 初始为 left child
while(c < n){
if((c+1) < n && heap[c] > heap[c+1]){//right child更小,则取right child, 别忘了(c+1) < n
c++;
}
if(heap[c] >= temp)
break;
heap[i] = heap[c];
i = c;
c = 2 * i + 1;
}
heap[i] = temp;
}
//将数组建成Heap: 从最后一个节点的父亲开始( (n-1 - 1)/2 = n/2 - 1)直到根节点, 依次Fixdown
//堆排序: minHeap排序后是降序, NOT稳定, 空间复杂度o(1),因为没用到递归
public static void heapSort(int [] arr, int n){
int i;
//1 先把arr 转换为heap: 从最后一个节点的父亲开始直到根节点,Fixdown
for(i = n/2 - 1; i>=0; i--){
minHeapFixdown(arr, i, n);
}
//2 依次交换堆首和堆尾, Fixdown
for(i = n-1; i>0; i--){
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
minHeapFixdown(arr, 0, i);
}
}
//----------------------------------------quick sort-----------------------------------------
//快速排序, NOT稳定的 , 空间复杂度???
public static void quickSort(int [] arr, int n){
//原始快速排序 调用Divid
//quickSortDivid(arr, 0, n-1);
//简化的
quickSort1(arr,0,n-1);
}
//快速排序 简化版
public static void quickSort1(int [] arr, int f, int t){
if(f<t){
int pivot = arr[f], l=f, r=t;
while(l < r){
while(l<r && arr[r] >= pivot){//注意是 >= 不是>
r--;
}
if(l<r) {
arr[l++] = arr[r];
}
while(l<r && arr[l] < pivot){
l++;
}
if(l<r) {
arr[r--] = arr[l];
}
}//循环结束时l==r
arr[l] = pivot;//别忘了最终放pivot
quickSort1(arr,f,l-1);
quickSort1(arr,l+1,t);
}
}
//原始快速排序__子函数分治
public static void quickSortDivid(int [] arr, int f, int t){
if(f < t){
int pos = quickSortAdjust(arr, f, t);//pos位置上的元素已是在其最终位置上了
quickSortDivid(arr, f, pos-1);
quickSortDivid(arr, pos+1, t);
}
}
//原始快速排序__子函数,将首元素调整到 最终位置
public static int quickSortAdjust(int [] arr, int l, int r){//left, right
int pivot = arr[l];
while(l < r){
while(l<r && arr[r] >= pivot){//如果右边找不到比pivot小的值,那么right就会递减至等于left,注意如果是 && arr[r] > pivot会导致{3, 4, 1, 3, 2}出错
r--;
}
if(l<r) {
arr[l++] = arr[r];//将比pivot大的值移到left
}
while(l<r && arr[l] < pivot){//注意不是 && arr[r] <= pivot!!!
l++;
}
if(l<r) {
arr[r--] = arr[l];
}
}//循环结束时l==r
arr[l] = pivot;//别忘了最终放pivot
return l;
}
//----------------------------------------merge sort-----------------------------------------
//归并排序, 稳定的, 对于second test data 性能很好,空间复杂度O(N)
public static void mergeSort(int [] arr, int n){
int [] tempArr = new int [n];
int first =0, last = n-1;
mergeSortDivid(arr, first, last, tempArr);
}
//归并的子函数__递归分解
public static void mergeSortDivid(int [] a, int first, int last, int [] tempArr){
if(first < last){//若从 first到last长度为1则什么都不做
int mid = (first + last)/2;
mergeSortDivid(a, first, mid, tempArr);
mergeSortDivid(a, mid+1, last, tempArr);
mergeSortMerge(a, first, mid, last, tempArr);
}
}
//归并的子函数__归并
public static void mergeSortMerge(int [] a, int first, int mid, int last, int [] tempArr){
int l1 = mid, l2 = last;//两个有序数组的末尾
int i = first, j = mid+1, k = 0;
while(i<=l1 && j<=l2){//不是i<l1 && j<l2以防从first到last长度为2的情况
if(a[i] < a[j]){
tempArr[k++] = a[i++];
}else{
tempArr[k++] = a[j++];
}
}
while(i<=l1){
tempArr[k++] = a[i++];
}
while(j<=l2){
tempArr[k++] = a[j++];
}
//再把 排序后的元素拷回原数组
for(i=0; i<k; i++){
a[first + i] = tempArr[i];//注意不是a[i] = tempArr[i]
}
}
//----------------------------------------select sort-----------------------------------------
//选择排序,选择是NOT稳定的,如3 3 2, 对于first test data真糟糕, 即使最好情况下仍然是O(n的平方)
public static void selectSort(int [] arr, int n){
int i, j;
for(i=0; i<n; i++){
int minPos = i;
//每次从i到n-1中找到最小值,将其与i进行互换
for(j=i+1; j<n; j++){
if(arr[j] < arr[minPos]){
minPos = j;
}
}
if(minPos > i){
int temp = arr[i];
arr[i] = arr[minPos];
arr[minPos] = temp;
}
}
}
//----------------------------------------shell sort-----------------------------------------
//原始的希尔排序 希尔是 NOT稳定的
public static void shellSort(int [] arr, int n){
int i,j,k, gap;
for(gap = n/2; gap>0; gap/=2){//步长每次减半
for(i = 0; i<gap; i++){//从0到gap-1共有gap个分组
//每个分组内进行insert sort
for(j = gap; j<n; j+=gap){
if(arr[j-gap] > arr[j]){
int temp = arr[j];
for(k = j-gap; k>=0 && arr[k] > temp; k-=gap){//k>=0要写在&&之前
arr[k+gap] = arr[k];
}
arr[k+gap] = temp;
}
}
}
}
}
//代码简洁后的希尔排序,对于second test data性能出奇得好!
public static void shellSort2(int [] arr, int n){
int i, j, gap;
for(gap = n/2; gap>0; gap /=2){
for(j = gap; j<n; j++){//从gap到n-1共n-gap个元素
if(arr[j-gap] > arr[j]){
//改用exchange实现的insert sort
for(i = j-gap; i>=0 && arr[i]>arr[i+gap]; i-=gap){
int temp = arr[i];
arr[i] = arr[i+gap];
arr[i+gap] = temp;
}
}
}
}
}
//----------------------------------------insert sort-----------------------------------------
//插入排序_后移, 插入是稳定的
public static void insertSortBackWhileSearch(int [] arr, int n){
int i,j;
for(i=1; i<n; i++){
if(arr[i] < arr[i-1]){//1 发现 逆序
int temp = arr[i];//插入值
//2 搜索 插入位置, 与此同时, 后移一位,腾出位置; 因为要后移,所以是从i-1到 0倒着搜索
for(j=i-1; j>=0 && arr[j]>temp; j--){
arr[j+1] = arr[j];
}
//3 搜索和后移都结束了,插入
arr[j+1] = temp;
}
}
}
//插入排序_交换
public static void insertSortExchange(int [] arr, int n){
int i,j;
for(i=1; i<n; i++){
//每一次i循环结束,使得从0到i都是顺序的,下一次循环判断从0到i+1是否存在逆序,如果逆序就交换 ,类似于冒泡!
for(j=i-1; j>=0 && arr[j]>arr[j+1]; j--){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//----------------------------------------bubble sort-----------------------------------------
//冒泡排序_使用了两个优化技术 , 冒泡是稳定的
public static void bubbleSort(int [] arr, int n){
int i,j;
boolean flag = true;
int k = n-1;
int pos = n-1;
while(k>0){
flag = false;
for(j = 0; j < k; j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
pos = j;//优化2
flag = true;//优化1
}
}
k = pos;//
if(!flag)
break;
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
long t1,t2;
t1 = (new Date()).getTime();
int [] arr = new int[100000];
int i,j;
//1st test data
for(i=0;i<100;i++){
arr[i] = 100-i;
}
for(i=100;i<100000;i++){
arr[i] = i+100;
}
//2nd test data
// for(i=0;i<100;i++){
// arr[i] = 100-i;
// }
// for(i=100;i<100000;i++){
// //arr[i] = i+100;
// arr[i] = 100000-i;
// }
//3rd test data for quick sort
// for(i=0;i<6000;i++){
// arr[i] = 6000-i;
// }
// for(i=2000;i<4000;i++){
// if(i%2==0){
// arr[i] = arr[i+1];
// }
// }
System.out.println("before--------");
//for 1st and 2nd test data
for(i=0;i<100;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
for(i=99901;i<100000;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
//for 3rd test data
// for(i=0;i<100;i++){
// System.out.print(arr[i]+" ");
// }
// System.out.println();
// for(i=5900;i<6000;i++){
// System.out.print(arr[i]+" ");
// }
// System.out.println();
// bubbleSort(arr,100000);//10 //22062
// insertSortBackWhileSearch(arr,100000);//10 //17328
// insertSortExchange(arr,100000);//11 //29830
// shellSort(arr,100000);//16 //9114
// shellSort2(arr,100000);//15 //25
// selectSort(arr,100000);//14940
// mergeSort(arr,100000);//25 //26
// quickSort(arr,6000);// 41 //quickSort(arr,6395)就会java.lang.StackOverflowError
heapSort(arr,100000);// 24 //23
//---------temp test for quick sort
// int [] bb = {3, 4, 1, 3, 2};
// quickSortAdjust(bb, 0, 4);
// for(int b:bb){
// System.out.println("--"+b);
// }
//
t2 = new Date().getTime();
System.out.println("time used:"+(t2-t1));
//---------temp test for heap sort
// int [] bb = {3, 4, 1, 3, 2};
// heapSort(bb,5);
// for(int b:bb){
// System.out.println("--"+b);
// }
System.out.println("after--------");
//for 1st and 2nd test data
for(i=0;i<100;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
for(i=99901;i<100000;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
//for 3rd test data
// for(i=0;i<100;i++){
// System.out.print(arr[i]+" ");
// }
// System.out.println();
// for(i=5900;i<6000;i++){
// System.out.print(arr[i]+" ");
// }
// System.out.println();
}
}