快速排序,实现简单

但是N长度的数组所需的时间和NlgN成正比,并且是原地排序,缺点是十分脆弱,导致性能低劣

快速排序的实现简单来说可以是,将一个数组分成两个数组进行分开排序,分别使用递归的方法,是两个数组有序,两个数组有序的话,自然完成了

主要就是这个分开的点的问题,怎么选择?

这个点的选择必须满足:

1.对于某个j,a[j]已经排好了;

2.a[stat]到a[j-1]都小于a[j]

3.a[j+1]到a[end]都大于a[j]

上述三个条件必须同时满足

我们需要一个方法,专门的帮我们去寻找中间点

public static void sort(Comparable[] a) {// 进行排序的方法

sort(a, 0, a.length – 1);

}

public static void sort(Comparable[] a,int start,int end) {// 进行排序的方法

if (end<=start)

return;

int mid = partition(a, start, end);

sort(a, start, mid-1);

sort(a, mid+1, end);

}

private static int partition(Comparable[] a, int start, int end) {// 进行断点寻找

int i = start;// 初始化变量

int j = end + 1;

Comparable temp = a[start];

while (true) {// 设置无限循环

while (less(a[++i], temp)) {

if (i == end) {// 进行判断是否一直小于,从头到尾

break;

}

}

while (less(temp, a[–j])) {

if (j == start) {

break;

}

}

if (i >= j)

break;

exch(a, i, j);// 上面两个如果都遇到违反条件的,进行交换

}

exch(a, start, j);// 交换到中间

return j;// 交换完成,返回

}

先去左侧寻找一个比临时值小的,然后去右侧找一个比临时值大的,然后交换

需要注意的点有:

1.使用辅助数组,要注意开销

2.别越界,如果切分元素正好为最大或者最小的元素,注意别让指针跑出数组边界

3.终止元素时候,要考虑到数组中可能包含和切分元素相同的元素

4.如果相同,处理起来左侧扫描最好遇到大于等于切分元素值停下

5.右侧扫描最好遇到小于等于元素值停下

优点在于和其他的算法比较,移动数据较少,

实现的特点在于用一个递增的索引和数组元素进行比较

有极端的情况,极端情况基本等于选择排序

三分法去排序数组,增加了等于的元素部分

对于有重复元素的数组进行改进,从左到右遍历数组,维护一个指针使左边的元素都小于插入点,右边的元素都大于插入点, 还有一部分等于元素

图片

public static void sort(Comparable[] a) {// 进行排序的方法

sort(a, 0, a.length- 1);

}

private static void sort(Comparable[] a,int start,int end) {// 进行排序的方法

if (end<=start)

return;

int x = start;

int i = start + 1;

int y = end;//设置条件

Comparable v = a[start];

while (i<=y) {//不断缩小未确定的范围,如果写成了start会出现指针报错

int cmp = a[i].compareTo(v);

if (cmp<0)//如果小于

exch(a, x++, i++);//交换两者,使小的值在前

else if (cmp>0)//如果大于

exch(a, i, y–);//交换两者,使大值在后面,i不自增的原因是要看是否还大的

else

i++;//相同则自增

}//现在小于v的(start,x-1),等于的(x,y),大于的(y+1,end)

sort(a, start, x-1);

sort(a, y+1, end);

}

流程图也在上面

接下来考虑算法的性能

考虑字符串键都很长的情况下且键的前大部分首字母相同,

三向字符串算法速度最多比普通的少2lnN个

其性能的优越来源于并不依赖字母表的大小

发表评论

邮箱地址不会被公开。 必填项已用*标注