排序(3)

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浮动,

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值