排序(3)

来源:互联网 发布:maven 书籍 推荐 知乎 编辑:程序博客网 时间:2024/06/16 16:22

level3,下面介绍几种稳定的排序方式,主要是两种,一个是堆排序(也叫做锦标赛排序),第二个就是我们经常用的二路归并排序,第三个就是多路归并排序(JDK)

当时在学校的时候觉得,快速排序真的是一个很好的想法,后来又看到了令人巧妙到让人不理解的一些思想。

下面说下堆排序,介绍原理,

其别名很形象,锦标赛,也就是一个二叉树状比赛,赢了就出去,下面继续打。

这个打的过程称做堆重构,赢的数字就是极值,这种比较和交换,绝对是超稳定的,因为只有两个点。

如下数字:64,96,19,52,85,71,64,48,1,78

 堆排序也是分治的一种,堆重构也是小方法体之一,巧妙在它对于一个数组的理解,把一个数组当作一个树来比较了。。

               64

         96        19

     52     85   71    64

  48  1  78  

这里假设四个变量 block 数组,start,end,哨兵p,start,end为数组位置,不是地址索引,即start=index+1,在java和c里面是如此的。

p开始初始化为数组第一个,block[start-1], 即是root

 它是怎么做的呢,首先,从i=start*2 开始,这里就是96,然后和19比较,如果96>10,那么和block[start-1]互换一下,保证

block[start-1]是堆的胜出点,

然后再判断i,这个是否到了尾部,如果不是,那么当前i=i*2,刚才的i是2,所以现在的i=4了,52和84比较,小,pass,

前进直到找到最大,85,block[i-1],下面是同理,

最后返回这个堆极值点。

堆重构:private static void HeapAdjust(int arr[], int start, int end) {  int temp = arr[start - 1];  for (int i =  start<<1; i <= end; i = i<<1) {   if (i < end && (arr[i - 1] < arr[i]))    i++;   if (temp >= arr[i - 1])    break;   arr[start - 1] = arr[i - 1];   start = i;  }  arr[start - 1] = temp; }

好了。。。
下面定义大方法体,
相当简单,将构造的堆的胜者一个一个放在数组后面。。

代码如下: public static void HeapSort(int arr[]) {  int temp;  int len = arr.length;  for (int i = len >>1; i > 0; i--)   HeapAdjust(arr, i, len);  for (int j = len; j > 1; j--) {   temp = arr[0];   arr[0] = arr[j - 1];   arr[j - 1] = temp;   HeapAdjust(arr, 1, j - 1);  } }

测试一下:

       100*10000   ,execute time:250

       1000*10000 ,execute time:2735

 发现在运行的时候好像有点慢,其实这是因为构建堆的时候是比较耗资源的,

为了突出其稳定性,再执行几次。

      1000*10000 ,execute time:2750

     1000*10000 , execute time:2859

     1000*10000,  execute time:2687

                          execute time:2735

首先快速是在数量级中等时是比较适合的,1000W级别并不很适合。

 然后快速在100W级别的时间,看看其稳定性:

      1. execute time:8141

      2. execute time:8360

      3.execute time:8469

      4.execute time:8250

首先,这两个是不在一个数量级,但是1000W能精确到200ms左右,而quickSort 100W是在300ms浮动,

还有稳定会带一定的好处就是,减少交换的次数,这点在这两者之间体现的相当明显。

原创粉丝点击