啊哈!算法之快速排序与桶排序

啊哈!算法之快速排序与桶排序

1.快速排序算法

快速排序由 C. A. R. Hoare(东尼·霍尔,Charles Antony Richard Hoare)在1960 年提出,之后又有许多人做了进一步的优化。
在数列种随机找出一个基准数,因为数列是杂乱的,所以取首项为基准数。
从后往前找到比基准数大的位置,再从前往后找到比基准数小的位置,交换元素;
右游标向前移动与左游标向后移动,它们相遇时用基准数的位置与相遇的位置交换。
此时原来数列以相遇的位置被划分为了两个需要排序的数列,再次执行上述过程;
当左游标在右游标的相同位置或右侧时,表示数列中只有一个元素或已没有需要排序的元素。
当所有的数列排序结束时,快速排序结束。

更多疑问可以参考《啊哈!算法》的『第1 章 一大波数正在靠近——排序』。

2.快速排序代码

代码如下:

package yuki.algorithm.sort;

import java.util.Random;

public class QuicksortDemo {

    public static void main(String[] args) {
        int[] a = new int[8];
        Random random = new Random();
        for(int i = 0; i < a.length; ++i)
            a[i] = random.nextInt(10);

        print(a);
        quicksort(a);
        print(a);
    }

    private static void quicksort(int[] a) {
        quicksort(a, 0, a.length - 1);
    }

    private static void quicksort(int[] a, int left, int right) {
        if(left >= right)
            return;
        int i = left;
        int j = right;
        int temp = a[left];
        while(i != j){
            while(a[j] >= temp && i < j)
                --j;
            while(a[i] <= temp && i < j)
                ++i;
            if(i < j)
                swap(a, i, j);
        }
        swap(a, left, i);
        quicksort(a, left, i-1);
        quicksort(a, i+1, right);
    }

    private static void swap(int[] a, int i, int j) {
        if(i == j || a[i] == a[j])
            return;
        System.out.println("[" + a[i] + "(" + i + "), " + a[j] + "(" + j + ")]");
        a[i] ^= a[j];
        a[j] ^= a[i];
        a[i] ^= a[j];
        print(a);
    }

    private static void print(int[] a) {
        for (int i = 0; i < a.length - 1; ++i)
            System.out.print(a[i] + "\t");
        System.out.println(a[a.length - 1]);
    }
}

运行结果如下:

6	9	0	8	5	4	6	5
[9(1), 5(7)]
6	5	0	8	5	4	6	9
[8(3), 4(5)]
6	5	0	4	5	8	6	9
[6(0), 5(4)]
5	5	0	4	6	8	6	9
[5(0), 4(3)]
4	5	0	5	6	8	6	9
[5(1), 0(2)]
4	0	5	5	6	8	6	9
[4(0), 0(1)]
0	4	5	5	6	8	6	9
[8(5), 6(6)]
0	4	5	5	6	6	8	9
0	4	5	5	6	6	8	9

3.桶排序算法

找到数列中的最大值,新建一个以这个最大值为长度的数组。
其下标用来存放待排序数组的数值,其值用来存放待排序数组的元素存放个数。
依次从按桶的顺序取出待排序数组的元素,并放回到原数列中,排序结束。

代码如下:

package yuki.algorithm.sort;

import java.util.Random;

public class BucketsortTest {

    public static void main(String[] args) {
        int[] a = new int[8];
        Random random = new Random();
        for(int i = 0; i < a.length; ++i)
            a[i] = random.nextInt(10);

        print(a);
        bucketsort(a);
        print(a);
    }

    private static void bucketsort(int[] a) {
        int max = 0;
        for (int i = 0; i < a.length; i++)
            if(max < a[i])
                max = a[i];

        int[] b = new int[max + 1];
        for (int i = 0; i < a.length; i++)
            ++b[a[i]];
        print(b);

        for (int i = 0, j = 0; j < b.length; ){
            if(b[j] == 0)
                ++j;
            else if(--b[j] >= 0)
                a[i++] = j;
        }
        print(b);
    }

    private static void print(int[] a) {
        for (int i = 0; i < a.length - 1; ++i)
            System.out.print(a[i] + "\t");
        System.out.println(a[a.length - 1]);
    }
}

运行结果如下:

7	4	9	4	8	7	3	3
0	0	0	2	2	0	0	2	1	1
0	0	0	0	0	0	0	0	0	0
3	3	4	4	7	7	8	9

4.冒泡排序代码

代码如下:

package yuki.algorithm.sort;

import java.util.Random;

public class BubblesortTest {

    public static void main(String[] args) {
        int[] a = new int[8];
        Random random = new Random();
        for(int i = 0; i < a.length; ++i)
            a[i] = random.nextInt(10);

        print(a);
        bubblesort(a);
        print(a);
    }

    private static void bubblesort(int[] a) {
        for(int i = a.length - 1; i > 0; --i)
            for(int j = 0; j < i; ++j)
                if(a[j] > a[j+1]){
                    System.out.println("[" + a[j] + "(" + j + "), " + a[j+1] + "(" + (j+1) + ")]");
                    a[j] ^= a[j+1];
                    a[j+1] ^= a[j];
                    a[j] ^= a[j+1];
                    print(a);
                }
    }

    private static void print(int[] a) {
        for (int i = 0; i < a.length - 1; ++i)
            System.out.print(a[i] + "\t");
        System.out.println(a[a.length - 1]);
    }
}

运行结果如下:

8	3	9	4	9	6	5	0
[8(0), 3(1)]
3	8	9	4	9	6	5	0
[9(2), 4(3)]
3	8	4	9	9	6	5	0
[9(4), 6(5)]
3	8	4	9	6	9	5	0
[9(5), 5(6)]
3	8	4	9	6	5	9	0
[9(6), 0(7)]
3	8	4	9	6	5	0	9
[8(1), 4(2)]
3	4	8	9	6	5	0	9
[9(3), 6(4)]
3	4	8	6	9	5	0	9
[9(4), 5(5)]
3	4	8	6	5	9	0	9
[9(5), 0(6)]
3	4	8	6	5	0	9	9
[8(2), 6(3)]
3	4	6	8	5	0	9	9
[8(3), 5(4)]
3	4	6	5	8	0	9	9
[8(4), 0(5)]
3	4	6	5	0	8	9	9
[6(2), 5(3)]
3	4	5	6	0	8	9	9
[6(3), 0(4)]
3	4	5	0	6	8	9	9
[5(2), 0(3)]
3	4	0	5	6	8	9	9
[4(1), 0(2)]
3	0	4	5	6	8	9	9
[3(0), 0(1)]
0	3	4	5	6	8	9	9
0	3	4	5	6	8	9	9

友情链接:)
[快速排序(Quicksort)的Javascript实现](http://www.ruanyifeng.com/blog/2011/04/quicksort_in_javascript.html)
[可视化对比十多种排序算法](http://blog.jobbole.com/72850/)
[啊哈!算法](http://www.amazon.cn/%E5%95%8A%E5%93%88-%E7%AE%97%E6%B3%95-%E5%95%8A%E5%93%88%E7%A3%8A/dp/B00KSWT268/)

如果你觉得本文对你有帮助,请点击右下方的推荐按钮,这样就可以让更多的小伙伴看到它了。

本文地址:http://www.cnblogs.com/kodoyang/p/AhaAlgorithm_Quicksort_Bucketsort.html

雨木阳子
2015年9月13日

时间: 2024-10-23 10:17:49

啊哈!算法之快速排序与桶排序的相关文章

排序算法&lt;No.2&gt;【桶排序】

算法,是永恒的技能,今天继续算法篇,将研究桶排序. 算法思想: 桶排序,其思想非常简单易懂,就是是将一个数据表分割成许多小数据集,每个数据集对应于一个新的集合(也就是所谓的桶bucket),然后每个bucket各自排序,或用不同的排序算法,或者递归的使用bucket sort算法,往往采用快速排序.是一个典型的divide-and-conquer分而治之的策略. 其中核心思想在于如何将原始待排序的数据划分到不同的桶中,也就是数据映射过程f(x)的定义,这个f(x)关乎桶数据的平衡性(各个桶内的数

复习数据结构:排序算法(七)——桶排序

桶排序是一种稳定的排序方法,也是一种外排序. 桶排序的时间复杂度:最坏情况运行时间:当分布不均匀时,全部元素都分到一个桶中,则O(n^2),当然[算法导论8.4-2]也可以将插入排序换成堆排序.快速排序等,这样最坏情况就是O(nlgn).最好情况运行时间:O(n). 也就说,前面介绍的排序算法要么是O(n^2),要么是O(nlogn),只有桶排序是可能实现O(n)排序的,但是对数据是有要求的. 基本思想:是将阵列分到有限数量的桶子里.每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续

排序算法(一)-桶排序

桶排序,顾名思义,为要拍排序数组分配一些的”桶“来排序,什么意思呢?假如你有一个数组,其中包含10个元素,其中最大的数字是90,你就分配个90个以上的桶(假如定义一个int a[101]),你可以看到,10个数定义一个含100个元素的数组用来排序(当然,a[100]随便啦,你定义int a[100],a[193]都可以,只要这个元素的个数多于要排序数组的最大数,这都是你估计的,所以你尽量数组往大里面定义,原因你看排序过程即可),很费空间,但是很省时间.下面说一个排序过程. 假如你第一个数字是3,

【C#】1.算法温故而知新 - 简单的桶排序

缺点: 1.不适用于小数 2.当数值过多,太浪费空间,比如数值范围为0~99999,那需申请100000个变量,也就是要写成a[1000000]. 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { public class Program { public static void Main(strin

排序算法之快速排序(Quicksort)解析

一.快速排序算法的优点,为什么称之为快排? Quicksort是对归并排序算法的优化,继承了归并排序的优点,同样应用了分治思想. 所谓的分治思想就是对一个问题“分而治之”,用分治思想来解决问题需要两个步骤: 1.如何“分”?(如何缩小问题的规模) 2.如何“治”?(如何解决子问题) 快排的前身是归并,而正是因为归并存在不可忽视的缺点,才产生了快排.归并的最大问题是需要额外的存储空间,并且由于合并过程不确定,致使每个元素在序列中的最终位置上不可预知的.针对这一点,快速排序提出了新的思路:把更多的时

最快最简单的排序算法:桶排序

在我们生活的这个世界中到处都是被排序过的.站队的时候会按照身高排序,考试的名次需要按照分数排序,网上购物的时候会按照价格排序,电子邮箱中的邮件按照时间排序……总之很多东西都需要排序,可以说排序是无处不在.现在我们举个具体的例子来介绍一下排序算法. 首先出场的我们的主人公小哼,上面这个可爱的娃就是啦.期末考试完了老师要将同学们的分数按照从高到低排序.小哼的班上只有5个同学,这5个同学分别考了5分.3分.5分.2分和8分,哎考的真是惨不忍睹(满分是10分).接下来将分数进行从大到小排序,排序后是8

排序算法之快速排序Java实现

排序算法之快速排序 舞蹈演示排序: 冒泡排序: http://t.cn/hrf58M 希尔排序:http://t.cn/hrosvb  选择排序:http://t.cn/hros6e  插入排序:http://t.cn/hros0W  快速排序:http://t.cn/ScTA1d  归并排序:http://t.cn/Sc1cGZ 快速排序是一个就地排序,分而治之,大规模递归的算法.从本质上来说,它是归并排序的就地版本. 1.快速排序可以由下面四步组成:(1) 如果不多于1个数据,直接返回.(2

【啊哈!算法】最快最简单的排序——桶排序

转自:http://bbs.ahalei.com/thread-4399-1-1.html 最快最简单的排序——桶排序 在我们生活的这个世界中到处都是被排序过的.站队的时候会按照身高排序,考试的名次需要按照分数排序,网上购物的时候会按照价格排序,电子邮箱中的邮件按照时间排序……总之很多东西都需要排序,可以说排序是无处不在.现在我们举个具体的例子来介绍一下排序算法. 首先出场的我们的主人公小哼,上面这个可爱的娃就是啦.期末考试完了老师要将同学们的分数按照从高到低排序.小哼的班上只有5个同学,这5个

桶排序和基数排序

桶排序的基本思想 假设有一组长度为N的待排关键字序列K[1....n].首先将这个序列划分成M个的子区间(桶) .然后基于某种映射函数 ,将待排序列的关键字k映射到第i个桶中(即桶数组B的下标 i) ,那么该关键字k就作为B[i]中的元素(每个桶B[i]都是一组大小为N/M的序列).接着对每个桶B[i]中的所有元素进行比较排序(可以使用快排).然后依次枚举输出B[0]....B[M]中的全部内容即是一个有序序列. 假如待排序列K= {49. 38 . 35. 97 . 76. 73 . 27.