使用JAVA直观感受快速排序与冒泡排序的性能差异

初学算法,肯定会编写排序算法

其中两个最为有名的就是冒泡排序和快速排序

理论上冒泡排序的时间复杂度为O(N^2),快速排序的时间复杂度为O(NlogN)

下面本门使用JAVA,分别编写三段排序程序

  1. 对十万个0-9999的整数进行一次冒泡排序
  2. 对十万个0-9999的整数进行1000次快速排序,使用递归完成
  3. 对十万个0-9999的整数进行1000次快速排序,使用堆栈完成

对十万个0-9999的整数进行一次冒泡排序:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

package sort;

import java.util.Date;

public class PopSort {

    public static void main(String[] args){

        int N=100000;

        int[] array=new int[N];

        for(int i=0;i<N;i++)

            array[i]=(int) (Math.random()*9999);

        

        Date begin=new Date();

        

        for(int i=N-1;i>1;i--){

            for(int j=0;j<i;j++){

                if(array[j]>array[j+1]){

                    int tmp=array[j];

                    array[j]=array[j+1];

                    array[j+1]=tmp;

                }

            }

        }

        

        Date end=new Date();

        System.out.println("使用冒泡排序,对 " +N+ "个整数进行排序,用时:" +String.valueOf(end.getTime()-begin.getTime())+ "毫秒");

        for(int i=0;i<100;i++)

            System.out.print(array[i]+" ");

    }

}

执行结果:

下面是使用递归方法的快速排序:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

package sort;

import java.util.Date;

public class QuickSort {

    public static void main(String[] args){

        int K=1000;

        int N=100000;

        Date begin = new Date();

        

        for(int num=0;num<K;num++){

            int[] array=new int[N];

    

            for(int i=0;i<N;i++)

                array[i]=(int) (Math.random()*9999);

            

            

            

            sort(array,0,array.length-1);

            

        }

        Date end=new Date();

        long time=end.getTime()-begin.getTime();

        System.out.println("使用递归方式进行快速排序,对 " +N+ "个整数进行排序 " +K+ "次,用时:" +String.valueOf(time)+ "毫秒\n平均用时:"+time/K+"毫秒");

    }

    

    private static void sort(int[] array,int begin,int end){

        int right=end,left=begin;

        while(right!=left){

            for(;right>left;right--){

                if(array[begin]>=array[right])

                    break;

            }

            for(;left<right;left++){

                if(array[begin]<array[left])

                    break;

            }

            

            if(left!=right){

                int tmp=array[left];

                array[left]=array[right];

                array[right]=tmp;

            }else if(right!=begin){

                int tmp=array[begin];

                array[begin]=array[left];

                array[left]=tmp;

            }

        }

        

        if(left-1>begin)

            sort(array,begin,left-1);

        if(right+1<end)

            sort(array,right+1,end);

    }

}

执行结果:

最后一段程序是使用数据结构栈来实现的非递归快速排序算法:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

package sort;

import java.util.Date;

import java.util.Stack;

/**

 * 使用栈而不是递归来实现快排

 * @author [email protected]

 * Time : 2016年1月8日 下午9:51:49

 */

public class QuickSort2 {

    public static void main(String[] args) {

        Date begin = new Date();

        Date end=null;

        int K=1000;

        int N=100000;

        

        for(int num=0;num<K;num++){

            int[] array=new int[N];

            for(int i=0;i<N;i++)

                array[i]=(int) (Math.random()*9999);

            Stack<Node> stack=new Stack<Node>();

            stack.add(new Node(0,N-1));

            

            while(!stack.isEmpty()){

                Node node=stack.pop();

                int right=node.end , left=node.begin;

                while(right!=left){

                    for(;right>left;right--)

                        if(array[node.begin]>=array[right])

                            break;

                    for(;left<right;left++)

                        if(array[node.begin]<array[left])

                            break;

                    

                    if(left!=right){

                        int tmp=array[left];

                        array[left]=array[right];

                        array[right]=tmp;

                    }else if(right!=node.begin){

                        int tmp=array[node.begin];

                        array[node.begin]=array[right];

                        array[right]=tmp;

                    }

                }

                

                if(left-1>node.begin)

                    stack.push(new Node(node.begin,left-1));

                if(node.end>right+1)

                    stack.push(new Node(right+1,node.end));

            }

            

            

        }

        end=new Date();

        long time=end.getTime()-begin.getTime();

        System.out.println("使用数据结构栈进行快速排序,对 " +N+ "个整数进行排序 " +K+ "次,用时:" +String.valueOf(time)+ "毫秒\n平均用时:"+time/K+"毫秒");

    }

}

class Node{

    public int begin;

    public int end;

    public Node(int begin,int end){

        this.begin=begin;

        this.end=end;

    }

}

执行结果:

综上所述,可以直观的看出来

  1. 复杂度为O(N^2)的冒泡排序速度相当慢,一次排序就要18秒,而复杂度为O(NlogN)的快速排序基本上20毫秒内就搞定,这就是算法的力量啊。
  2. 递归函数在这里并不会影响性能,直观,简洁的递归算法是相当实用的,除非动态规划算法一定要将递归转变成循环,否则大多数情况下并不需要改变递归方法,而非递归算法因为会引入其他数据结构,有可能导致程序还会稍稍有些额外开支。

本文来自:http://www.hexcode.cn/article/4090/show

时间: 2024-10-12 18:31:38

使用JAVA直观感受快速排序与冒泡排序的性能差异的相关文章

视觉直观感受7种常用排序算法

视觉直观感受若干常用排序算法 1 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 "基准"(pivo

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

快速排序和冒泡排序相似,都是通过多次比较和交换来实现排序. 具体流程如下: 1.首先设定一个分界值,通过分界值将数组分成左右两部分,将大于等于分界值的数据交换集中到右侧数组,将小于分界值的数据交换集中到左侧数组: 2.然后,左侧数组和右侧数组可以独立排序.对于左侧数组可以取一个分界值,将左侧数组分成左右两个部分,同样将左边放置小于分界值的数据,右侧放置大于等于分界值的数据.对右侧数组做类似处理. 3.重复上述过程,其实就是递归.通过递归将左侧数组排好序后,再递归处理右侧数据.当左.右两部分数据都

快速排序、冒泡排序

我目前最常用的两种排序:冒泡排序和快速排序 比较一下他们的性能: 1 #include<stdio.h> 2 3 void QuickSort(int * a,int left,int right) 4 { 5 if(left>right) 6 { 7 return; 8 } 9 int stand=a[left]; 10 int i=left; 11 int j=right; 12 //得到基准数位置 13 while(i!=j) 14 { 15 while(i<j&&a

php实现快速排序和冒泡排序

<?php $arr = array(9,4,12,34,1,43,23,7,3,4,5,6,33,22,12,21,15,62,1222,21,322,432,31,54,64); //$sorted_arr = quickSort($arr); $sorted_arr = bublleSort($arr); var_dump($sorted_arr); // 快速排序算法 function quickSort($arr){ if(count($arr)>1){ $k=$arr[0]; $x

Java IO和Java NIO在文件拷贝上的性能差异分析 (转)

1.       在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取 到用户空间的缓冲区.参看read(byte b[])方法的源码,可知,它会在内部再调用readBytes(b, 0, b.length)方法,而且readBytes(b, 0, b.length)方法是一个native方法(即本地方法),最终通过这个本地方法来发起一次系统调用,即调用系统内核的read()

David MacKay:用信息论解释 &#39;快速排序&#39;、&#39;堆排序&#39; 本质与差异

这篇文章是David MacKay利用信息论,来对快排.堆排的本质差异导致的性能差异进行的比较. 信息论是非常强大的,它并不只是一个用来分析理论最优决策的工具. 从信息论的角度来分析算法效率是一件很有趣的事,它给我们分析排序算法带来了一种新的思路. 运用了信息论的概念,我们很容易理解为什么快排的速度那么快,以及它的缺陷在哪里. 由于个人能力不足,对于本文的理解可能还是有点偏差. 而且因为翻译的困难,这篇译文有很多地方并没有翻译出来,还是使用了原文的句子. 所以建议大家还是阅读原文Heapsort

90 % Java 程序员被误导的一个性能优化策略

我们经常看到一些 Java 性能优化的书或者理念,说不要在循环内定义变量,这样会占用过多的内存影响性能,而要在循环外面定义.接触 Java 这么久以来,相信很多 Java 程序员都被这种代码性能优化策略所误导. 看下面两个示例,示例1在循环外定义变量,示例2是在循环内定义变量. /** * 循环外定义变量 */ private static void outer() { Javastack javastack = null; for (int i = 0; i < 10; i++) { java

几种排序方式的java实现(01:插入排序,冒泡排序,选择排序,快速排序)

以下为集中排序的java代码实现(部分是在引用别人代码): 插入排序(InsertSort): //代码原理 public static void iSort(int[] a){ for(int i = 1;i < a.length; i++){ if(a[i] < a[i-1]){ int temp = a[i]; while(temp < a[i-1]){ a[i] = a[i-1]; if(i-1 > 0){ i--; }else{ break; } } a[i-1] = t

视觉直观感受 7 种常用的排序算法

1. 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 "基准"(pivot), 重新排序数列,所有元