您的位置:首页 > 其它

亲历快速排序算法,有感于程序的边界条件

2014-12-04 02:05 162 查看
看数据结构的书,关于快速排序.算法倒是不难理解. 网上随便baidu了一个算法. 看起来似乎也像那么回事.

然而原程序中只对10个数排序,并且排序前的数组的元素的值和顺序已经确定. 改成用java.util.Random产生随机数,来运行, 此时发现程序陷入死循环的几率非常大,即使没有死循环, 排序的结果也不对.

于是改一改吧.. 发现连界情况很是微妙. 也是本人愚钝,加上晚上思路不清,有些迷糊, 改了大约两个小时才改好.

现在随机数的上限和数组的大小均可以由参数指定 ,如果随机数的上限和数组的大小接近,可以考验程序在数组中有多个重复值时的运行情况;程序运行完后会打印出比较次数和交换次数.

具体边界情况我都加上了注释.

import java.util.Random;

/**
* 快速排序 通过一趟排序将要排序的数据分割成独立的两部分, 其中一部分的所有数据都比另外一部分的所有数据都要小,
* 然后再按此方法对这两部分数据分别进行快速排序, 整个排序过程可以递归进行,以此达到整个数据变成有序序列。
*
*/
public class QuickSort {

private static int compareTime = 0;
private static int swapTime = 0;

public static void main(String[] args) throws Exception {
int size = 15;
int sead = 20;

if (args.length < 2) {

System.out
.println("下次请输入两个参数,第一个为数组的大小,第二个为随机数的上限,例如 java QuickSort 15 20");
System.out.println("现在程序以size=15,sead=20以运行");
} else {
size = Integer.valueOf(args[0]);
sead = Integer.valueOf(args[1]);
}

Random ran = new Random();
int[] sort = new int[size];
for (int i = 0; i < size; i++) {
sort[i] = ran.nextInt(sead);
}
System.out.print("排序前的数组为");
for (int i : sort) {
System.out.print(i + " ");
}

quickSort(sort, 0, sort.length - 1);
System.out.println();
System.out.print("排序后的数组为");
for (int i : sort) {
System.out.print(i + " ");
}
System.out.println("\n程序比较次数-->"+compareTime+"\n程序交换次数-->"+swapTime);
}

/**
* 快速排序
*
* @param sort 要排序的数组
* @param start 排序的开始座标
* @param end  排序的结束座标
*/
public static void quickSort(int[] sort, int start, int end) {

// 此时说明已经排序完成
if (end - start <= 0){
compareTime++;
return;

}

// 设置关键数据key为要排序数组的第一个元素,
// 即第一趟排序后,key右边的数全部比key大,key左边的数全部比key小
int key = sort[start];
// 设置数组左边的索引,往右移动判断比key大的数
int i = start + 1;   //注意此处要加上1
// 设置数组右边的索引,往左移动判断比key小的数
int j = end;
// 如果左边索引比右边索引小,则还有数据没有排序
while (i <= j) {   //等号用于当只有两个元素比如 0,6的排序,如果不加等号,排序后会交换0和6从而产生错误.
while (sort[j] >= key && j > start) {    //这里如果去掉等号,程序即可能会产生while死循环
j--;
compareTime++;
}
while (sort[i] < key && i < end) {
i++;
compareTime++;
}
if (i < j) {
int temp = sort[i];
sort[i] = sort[j];
sort[j] = temp;
swapTime++;
} else {
break;   // 如果i>=j 说明j的位置即是key要交换的位置.交换后j前的元素均比key小,j后均比key大

}

}

// 此时j停留在需要交换的位置,i的位置不定,可能比j大也可能和j相等
// 将sort[start]和sort[j]交换

sort[start] = sort[j];
sort[j] = key;

swapTime++;
// 递归调用
if (j >= start && j <= end) {    //如果去掉这两个等号 对于48,37,35,36这种情况便无法正确排序
swapTime+=2;
quickSort(sort, start, j - 1);
quickSort(sort, j + 1, end);
}
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: