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

7 篇文章 0 订阅
6 篇文章 0 订阅

        看数据结构的书,关于快速排序.算法倒是不难理解.  网上随便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);
		}
	}
}

      

     

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值