希尔排序
每隔一定间隔组成一个序列,对这个序列进行排序。逐渐缩短间隔,最后一次间隔必定是1。间隔的变化可以自行确定,书中介绍了h = 3*h + 1的变化策略。
public class Main {
public static void main(String[] args){
int[] a = {2, 3, 9, 1, 66, 4};
shellSort(a);
print(a);
}
public static void shellSort(int[] a){
int inner, outer;
int tmp;
int h = 1;
while(h <= a.length/3){
h = 3*h + 1;
}
while(h >=1 ){ //最后的间隔必定是1
for(outer = h; outer < a.length; outer++){
tmp = a[outer];
inner = outer;
while(inner >= h && tmp < a[inner-h]){
a[inner] = a[inner-h];
inner -= h;
}
a[inner] = tmp;
}
h = (h-1)/3;
}
}
public static void print(int[] a){
for(int i = 0; i < a.length; i++){
System.out.print(a[i]+" ");
}
System.out.println();
}
}
快速排序
快速排序很重要的一点就是划分,所以先说划分。
划分
划分就是需要选定一个枢纽(pivot),把小于枢纽的数挪到枢纽左边,把大于枢纽的数挪到枢纽右边。
public class Main {
public static int[] a = {2, 34, 9, 10, 66, 4};
public static void main(String[] args){
recursionQuickSort(0, a.length-1);
print(a);
}
//快速排序(递归、分治),区间[left, right]
public static void recursionQuickSort(int left, int right){
if(left >= right){
return;
}else{
int pivot = a[right];//每次都选择最右边的那个元素作为枢纽,对枢纽左边
//的元素进行划分,之后把划分的分界元素和枢纽交换
int boundary = partition(left, right, pivot);
recursionQuickSort(left, boundary-1);
recursionQuickSort(boundary+1, right);
}
}
//划分,返回划分的分界元素下标
public static int partition(int left, int right, int pivot){
int leftPtr = left - 1;
int rightPtr = right;//注意,这里实际上把最右边的元素a[right]用作枢纽,后面是--right
while(true){
while(leftPtr < right && a[++leftPtr] < pivot){}//从左便开始找,找一个大于枢纽的数
while(rightPtr > 0 && a[--rightPtr] > pivot){}//从右边开始找,找一个小于枢纽的数
if(leftPtr >= rightPtr){
break;
}else{
swap(leftPtr, rightPtr);
}
}
swap(leftPtr, right);
return leftPtr;//返回的是分界处元素下标,该分界属于右边部分
}
public static void swap(int index1, int index2){
int tmp = a[index1];
a[index1] = a[index2];
a[index2] = tmp;
}
public static void print(int[] a){
for(int i = 0; i < a.length; i++){
System.out.print(a[i]+" ");
}
System.out.println();
}
}