数据结构基础 —— 快速排序 java 实现

原创 2015年11月19日 17:47:06

快速排序 java 实现

一种代码

下面的这个 if (last > first) 一定要加

    private static void quickSort(Integer[] data, int first, int last) {
        if (last > first) {
            int pivotIndex = partion(data, first, last);
            quickSort(data, first, pivotIndex-1);
            quickSort(data, pivotIndex+1, last);
        }
    }

下面这个程序是讲 list 的 first 到 last 的元素分为两组,一组小于 pivot,一组大于 pivot。注意,组内的元素并不一定有序,所以需要递归调用,知道first == last,也就是最后只剩一个元素。

这儿我们选择第一个元素作为 pivot
这儿的思路是low 从左往右,high 从右往左
low 找到>pivot, high 找到小于

    /**
     * 
     * @param list
     *            数组
     * @param first
     *            第一个元素
     * @param last
     *            最后一个元素(包含)
     * @return
     */
    private static int partion(Integer[] list, int first, int last) {
        int pivot = list[first];

        int low = first + 1;
        int high = last;
        System.out.println("待分组的序列: "+Arrays.toString(Arrays.copyOfRange(list, first, last+1)));


        while (low < high) {

            // low <= high should be placed before list[low] <= pivot
            // otherwise it may cause ArrayIndexOutOfBoundsException
            // 改成 low < high 两个条件的顺序不重要了?这时候最多 low == high
            // 不会存在 low == high+1,超出范围
            while (low < high  && list[low] <= pivot ) {
                low++;
            }

            // 这儿倒是谁前谁后不重要,因为low<high最多就是 low == high
            // 当 low == high 时,循环结束,不存在 high 会为-1情况
            while (list[high] >= pivot && low < high) {
                high--;
            }

            /**
             * 交换这两个元素
             */
            if (low < high) {
                int temp = list[low];
                list[low] = list[high];
                list[high] = temp;
            }

        }

        /**
         * 找到小于 pivot 的锚点,找出最后的返回值
         * high > first 是防止数组越界的
         * 这时候的数据 是一部分小于pivot,一部分大于 pivot
         * 本函数从高往低走,找出
         */
        while (high > first && list[high] >= pivot) {
            high--;
        }


        // 只可能是 pivot == list[high] 或者 >
        //得到的 high 值是小于 pivot 区域的最后一个数
        //这儿交换两个数的位置
        if (pivot > list[high]) {
            list[first] = list[high];
            list[high] = pivot;
            System.out.print(Arrays.toString(Arrays.copyOfRange(list, first, high)));
            System.out.print(" [ pivot=" + list[high] + " ] ");
            if (high + 1 <= last)
                System.out.print(Arrays.toString(Arrays.copyOfRange(list, high + 1, last + 1)));
            else {
                System.out.print(" []");
            }
            System.out.println();
            return high;

        } else {

            //这种情况是 pivot 是最小值,其他数都在它右边
            System.out.println("high=" + high + " list[high]=" + list[high]);
            System.out.print("[ pivot=" + list[first] + " ]");
            System.out.println(Arrays.toString(Arrays.copyOfRange(list, first + 1, last + 1)));

            return high;
        }

    }

    public static void shellPass(Integer[] array, int d) {
        for (int i = d; i < array.length; i++) {
            int temp = array[i];
            int j = i - d;
            while (j >= 0 && array[j] > temp) {
                array[j + d] = array[j];
                j -= d;
            }
            array[j + d] = temp;
        }
    }

测试输出

public static void main(String[] args) {
        Random r = new Random();
        Integer[] data = new Integer[10];

        for (int ii = 0; ii < 10; ii++) {
            for (int i = 0; i < data.length; i++) {
                data[i] = r.nextInt(30);
            }
            System.out.println("------------------------");
            System.out.println(Arrays.toString(data));

            quickSort(data, 0, data.length - 1);

            System.out.println(Arrays.toString(data));
        }

    }

输出

------------------------
[29, 15, 2, 15, 10, 0, 2, 14, 29, 17]
待分组的序列: [29, 15, 2, 15, 10, 0, 2, 14, 29, 17]
[17, 15, 2, 15, 10, 0, 2, 14, 29] [ pivot=29 ]  []
待分组的序列: [17, 15, 2, 15, 10, 0, 2, 14, 29]
[14, 15, 2, 15, 10, 0, 2] [ pivot=17 ] [29]
待分组的序列: [14, 15, 2, 15, 10, 0, 2]
[10, 2, 2, 0] [ pivot=14 ] [15, 15]
待分组的序列: [10, 2, 2, 0]
[0, 2, 2] [ pivot=10 ]  []
待分组的序列: [0, 2, 2]
high=0 list[high]=0
[ pivot=0 ][2, 2]
待分组的序列: [2, 2]
high=1 list[high]=2
[ pivot=2 ][2]
待分组的序列: [15, 15]
high=5 list[high]=15
[ pivot=15 ][15]
[0, 2, 2, 10, 14, 15, 15, 17, 29, 29]

改进

选取线性表的第一个元素作为主元。
理想情况下是 主元可以把一组数据分为相同个数的两部分

改进简单方法是,选取第一个元素、中间元素、最后一个元素作为主元。

对于有序序列采用快排是个灾难,因为选取第一个元素作为主元,会使得一边空,一边是剩下的元素。
这样递归的次数比两边个数均等时候更多

第二种划分算法

    private static int partion2(Integer[] list, int low, int high) {

        int pivot = list[low];

        while (low < high) {
            while (low < high && list[high] >= pivot)
                high--;
            if (low < high) 
                list[low++]=list[high];

            while (low < high && list[low] <= pivot) 
                low++;
            if (low < high)
                list[high--] = list[low];
        }
        //while循环结束肯定 low == high
        System.out.println("low == high ? " + (low == high));
        list[low] = pivot;

        return low;

    }

上面这个方法很简洁,利用了 pivot = list[low],多了一个冗余的数组位置。所以,先从 high 从右往左,把小于 pivot 的元素放在 low 处,list[low++]=list[high];这儿 low+1,再从左往右。刚才的list[high]元素也有两个值,可以把大于 pivot 的元素放在 list[high--] = list[low]处、

测试 partion2

输出

------------------------
[27, 18, 5, 19, 24, 10, 1, 24, 14, 7]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[1, 5, 7, 10, 14, 18, 19, 24, 24, 27]
------------------------
[12, 5, 6, 18, 27, 28, 27, 17, 23, 22]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[5, 6, 12, 17, 18, 22, 23, 27, 27, 28]
------------------------
[17, 9, 4, 8, 19, 3, 29, 5, 29, 21]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[3, 4, 5, 8, 9, 17, 19, 21, 29, 29]
------------------------
[25, 25, 11, 19, 5, 2, 2, 13, 7, 15]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[2, 2, 5, 7, 11, 13, 15, 19, 25, 25]
------------------------
[27, 2, 21, 20, 11, 2, 9, 21, 15, 29]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[2, 2, 9, 11, 15, 20, 21, 21, 27, 29]
------------------------
[10, 5, 14, 21, 27, 9, 11, 29, 4, 23]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[4, 5, 9, 10, 11, 14, 21, 23, 27, 29]
------------------------
[21, 22, 23, 8, 0, 26, 12, 5, 2, 24]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[0, 2, 5, 8, 12, 21, 22, 23, 24, 26]
------------------------
[16, 25, 14, 19, 21, 27, 19, 1, 14, 6]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[1, 6, 14, 14, 16, 19, 19, 21, 25, 27]
------------------------
[26, 3, 4, 26, 4, 20, 1, 26, 29, 25]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[1, 3, 4, 4, 20, 25, 26, 26, 26, 29]
------------------------
[23, 5, 14, 8, 8, 5, 16, 14, 22, 29]
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
low == high ? true
[5, 5, 8, 8, 14, 14, 16, 22, 23, 29]
版权声明:转载请注明出处 博客地址 http://blog.csdn.net/never_cxb

数据结构与算法分析笔记与总结(java实现)--排序5:快速排序练习题

数据结构与算法分析笔记与总结(java实现)--排序5:快速排序练习题

Java数据结构之快速排序

前言      快速排序是面试中非常常见的排序算法,工作中,快速排序的效率也是我们常常用到的,他的发展来源于划分算法,采用的是分治策略. 实现思路     先从数组中选择一个pivo...

冒泡排序和快速排序以及Android的collections.sort排序

1.冒泡排序 (1)基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序...

算法:快速排序算法

快速排序的思想是:yitang
  • leelit
  • leelit
  • 2014年11月07日 19:19
  • 1238

排序算法(Java实现):选择排序法和快速排序法

为了方便扩展,先引入一个抽象的基础类: package com.andyidea.algorithms; /** * 排序抽象基础类 * @author Andy.Chen * * @...
  • cjjky
  • cjjky
  • 2011年11月23日 00:54
  • 6748

常见排序算法(零)(各类排序算法总结与比较)

八种排序算法(冒泡排序(BubbleSort)、选择排序(Selection Sort)、插入排序(Insertion Sort)、快速排序(Quick Sort)、归并排序(Merge Sort)、...

数据结构与算法分析(Java语言描述)(9)—— (双轴)快速排序

QuickSortTwoWays.javapackage com.algorithm.sort;public class QuickSortTwoWays { private QuickSor...

数据结构与算法分析(Java语言描述)(7)—— 快速排序

伪代码for each (unsorted) partition set first element as pivot storeIndex = pivotIndex + 1 for i = ...

算法与数据结构——快速排序

  • 2007年07月09日 20:18
  • 90KB
  • 下载

经典算法与数据结构的c++实现——快速排序

因为是经典的算法,所以网上描述一大把,直接上个图,直观些,给记性不好的菜鸟(如我)一点儿提示。 快速排序是冒泡排序的一种改进。通过轴值的选择方法不同,算法的速度也不一样。本文下面的代码采取选择最左...
  • y277an
  • y277an
  • 2016年03月22日 17:24
  • 454
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:数据结构基础 —— 快速排序 java 实现
举报原因:
原因补充:

(最多只允许输入30个字)