排序问题(二)
希尔排序法
希尔排序是希尔(DonaldShell) 于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为
缩小增量排序。
希尔排序法基本思想:
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;
随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰
被分成一组,算法便终止
希尔排序分两种情况:交换法和移动位置法
交换法:
依次分组,缩小增量,比较组间相应位置的元素,进行交换
public static void shell(int[] arr) {
int temp = 0;
int k = 0;
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
k++;
for (int i = gap; i < arr.length; i++) {
for (int j = i - gap; j >= 0; j -= gap) {
// 若当前元素大于加上步长之后的元素,交换
if (arr[j] > arr[j + gap]) {
temp = arr[j];
arr[j] = arr[j + gap];
arr[j + gap] = temp;
}
}
}
System.out.println("希尔排序的第" + k + "轮后=" + Arrays.toString(arr));
}
这个方法比普通的插入法的耗时更长,不适用
移动位置法:
依次分组,缩小增量,从第一个二个组开始,比较相差一个增量的各元素的大小,排序,这个方法耗时极短
// 对交换式的希尔排序进行优化,移位法
public static void shellpro(int[] arr) {
int temp = 0;
int k = 0;
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
k++;
for (int i = gap; i < arr.length; i++) {
int j = i;
temp = arr[j];
if (arr[j] < arr[j - gap]) {
while (j - gap >= 0 && temp < arr[j - gap]) {
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = temp;
}
}
System.out.println("希尔排序的第" + k + "轮后=" + Arrays.toString(arr));
}
}
对于希尔排序使用移动位置法比较好,但是理解有点费劲
快速排序
快速排序(Quicksort) 是对冒泡排序的一种改进
基本思想是:
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有 数据都比另外-部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
也就是先找个基准,然后找出比他大、小的数字出来,左右递归,重复操作,完成排序
public static void quicksort(int[] arr,int left,int right) {
int l = left;//左下标
int r = right;//右下标
int temp = 0;
int priv = arr[(left+right)/2];//中轴值
while(l<r) {//目的:把比中轴值小的放到左面大的放到右面
while(arr[l]<priv) {//在中轴左面一直找,大于等于中轴退出
l+=1;
}
while(arr[r]>priv) {//在中轴右面一直找,小于等于中轴退出
r-=1;
}
if(l >= r) {//正确顺序
break;
}
//交换
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
if(arr[l] == priv) {//如果和中轴相等则前移
r-=1;
}
if(arr[r] == priv) {//如果和中轴相等则后移
l+=1;
}
System.out.println(Arrays.toString(arr));
}
//必须的东西,否则栈溢出
if(l == r) {
l += 1;
r -=1;
}
//左递归
if(left<r) {
quicksort(arr,left,r);
}
//右递归
if(right>l) {
quicksort(arr,l,right);
}
}
每次的排序结果就像这个: