快速排序(v 2.0)

取中间的元素s作比较,同样的先得往右找比s大的索引 i,然后往左找比s小的索引 j,只要两边的索引还没有交叉(也就i=j),就交换 i 与 j 的元素值。这里不用再进行轴的交换,因为在寻找交换的过程中,轴位置的元素也会参与交换的动作,轴已经成为一个抽象的概念,代表的是一个数值而已。


public static void QuickSort(int[] number)
{
QuickSort(number, 0, number.length - 1);
}

/**
* 将轴设定为中间的元素,依这个元素作基准进行比较,这可以增加快速排序法的效率
* @param number 待排序数组
* @param left 最小index
* @param right 最大index
*/
private static void QuickSort(int[] number, int left, int right)
{
if (left < right)
{
int s = number[(left + right) / 2];
int i = left - 1;//中间元素作为基准,从0开始比较
int j = right + 1;

while (true)
{
// 1. 令索引 i 从数组左方往右方找,直到找到大于(不小于) s 的数的索引
while (number[++i] < s){}
// 2. 令索引 j 从数组右方往左方找,直到找到小于(不大于) s 的数的索引
while (number[--j] > s){}
// 3. 如果 i >= j,则退出循环
if (i >= j) break;
// 4. 如果 i < j,则交换索引i与j两处的值
swap(number, i, j);
}
// 5. 对轴左边进行递归
QuickSort(number, left, i - 1);
// 6. 对轴右边进行递归
QuickSort(number, j + 1, right);
}
}

private static void swap(int[] number, int i, int j)
{
int t;
t = number[i];
number[i] = number[j];
number[j] = t;
}


有比较,才有进步,才能更清晰地认识事物。下面是两种算法代码差异比较:
[b]1, 轴的选定:[/b]

int s = number[left];//V1:将最左边的数设定为轴,并记录其值为 s
int s = number[(left + right) / 2];//V2:中间元素作为基准

[b]2, 左边界的赋值[/b]

int i = left;//V1:轴在左边,比较该从index为1的地方开始,参考3
int i = left - 1;//V2:轴在中间,比较该从index为0的地方开始,参考3

[b]3, 比较的不同[/b]

while (i + 1 < number.length && number[++i] < s){}
while (j - 1 >= 0 && number[--j] > s) {}
//V1:对i, j进行了越界判断
while (number[++i] < s){}
while (number[--j] > s){}
/*V2:未对i, j进行了越界判断。当number[i]<s的时候循环继续,而s在中间,如果s左边的数都比s小,循环到number[i]=s的时候,s !< s,条件不成立,退出循环。i或者j为s的下标。所以不需要判断。对于V1,因为总是从边界的下一个数开始比较,当左右边界已经靠近时就有可能发生ArrayIndexOutOfBoundsException异常。所以要判断!*/

[b]4, 递归的不同[/b]

quicksort(number, left, j - 1);
quicksort(number, j + 1, right);
//V1:因为将新的轴在j处交换,所以递归与j相关
QuickSort(number, left, i - 1);
QuickSort(number, j + 1, right);
//V2:轴在中间,i, j的值也最多能到中间,所以递归与各自的i, j相关。


小结:撇开效率,仅从代码精简来说,也应该考虑V2,何况V2少了判断与移动轴,效率更高!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值