《数据结构和Java集合框架第三版》读书笔记(十二)快速排序

20 篇文章 0 订阅
1 篇文章 0 订阅

快速排序符合分治法。

分解:选择 枢轴,将数组划分成两个子数组,左子数组的每个元素都小于或等于 枢轴元素,右子数组的每个元素都大于或等于 枢轴元素,左子数组的每个元素都小于右子数组。

解决:通过递归调用快速排序分别对两个子数组进行排序。

合并:由于快速排序是就地排序,不需合并,快速排序进行完后整个数组就已经排序完毕。

private static void sort1(int x[ ], int off, int len)

对x数组从索引off开始的len个元素进行快速排序。

先找到 枢轴元素:

int m = off + (len >> 1),l = off,n = off + len - 1;
m = med3 (x, l, m, n); //3个元素的 中值
int v = x [m]; // v是枢轴
如给定数组 59 46 32 80 46 55 50 43 44 81 12 95 17 80 75 33 40 61 16 87 枢轴元素v=59

将所有小于枢轴元素v的元素移动到左子数组,将所有大于枢轴元素v的元素移到右子数组。值为v的元素可以放在任意一个子数组,两个子数组的长度并不要求一样。

采用指针b和c,创建一个循环,循环内b从off往右计数,c从off+len-1向左计数,b>c时break。这个循环包括两个内循环,第一个内循环里b不断向自增,直到x[b]>v;第二个内循环里c不断减小,直到x[c]<v。两个内循环终止后,交换x[b]和x[c],然后b增c减,继续执行外层循环,直到b>c时break。

		while(true){
			while(b<=c&&x[b]<v)
				b++;
			while(b<=c&&x[c]>v)
				c--;
			if(b>c)
				break;
			swap (x, b++, c--);//交换x[b]和x[c],然后b增c减,继续执行外层循环
		}


对这时的两个子数组如sort1方法进行快速排序

if(c+1–off>1)
    sort1 (x, off, c + 1 –off);
if(off + len –b > 1)
    sort1 (x, b, off + len -b);



快排的平均时间是O(NlogN),最差时间是O(N^2)


    public static int[] quickSort(int[] array){
        if (array == null || array.length == 0)
            return array;
        quickSortCore(array,0,array.length-1);
        return array;
    }

    private static void quickSortCore(int[] array, int start, int end) {
        //找到枢轴元素
        int pivot=getPivot(array,start,end);
        int left=start;
        int right=end;
        //将左右两个指针向枢轴移动
        // 直到左指针超过右指针或者左边元素不小于枢轴元素的时候左指针停止移动,直到左指针超过右指针或者右边元素不大于枢轴元素的时候右指针停止移动
        //如果都停止移动时,交换左右元素
        // 然后指针都向枢轴移动一步,然后继续上述循环
        //直到左指针移动到右指针右边为止
        while (left<=right){
            while (left<=right&&array[left]<pivot){
                left++;
            }
            while (left<=right&&array[right]>pivot){
                right--;
            }
            if (left<=right)
                swap(array,left++,right--);
        }
        if (start<right)
            quickSortCore(array,start,right);
        if (left<end)
            quickSortCore(array,left,end);
    }

    /**
     * 获取数组的枢轴元素
     */
    private static int getPivot(int[] array, int start, int end) {
        int midIndex=(start+end)>>>1;
        int min,max;
        if (array[start]<array[midIndex]){
            min=array[start];
            max=array[midIndex];
        }else {
            min=array[midIndex];
            max=array[start];
        }
        return array[end]<min?min:(array[end]<max?array[end]:max);
    }

    private static void swap(int[] array, int j, int i) {
        if (i==j)
            return;
        int k = array[i];
        array[i] = array[j];
        array[j] = k;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值