zoukankan      html  css  js  c++  java
  • 归并排序及几个常用排序比较

     1 void merge(int arr[], int l, int m,int r)
     2 {
     3     int i = 0, j = 0, k =l;
     4     int n1 = m - l + 1;        //左边步长
     5     int n2 = r - m;            //右边步长
     6     std::vector<int> vec_l(&arr[l], &arr[m+1]);
     7     std::vector<int> vec_r(&arr[m+1], &arr[r+1]);
     8     while (i < n1&&j < n2)
     9     {
    10         if (vec_l[i] <= vec_r[j])
    11         {
    12             arr[k] = vec_l[i];
    13             i++;
    14         }
    15         else
    16         {
    17             arr[k] = vec_r[j];
    18             j++;
    19         }
    20         k++;
    21     }
    22         while (i<n1)
    23         {
    24             arr[k]= vec_l[i];
    25             i++;
    26             k++;
    27         }
    28 
    29         while (j<n2)
    30         {
    31             arr[k] = vec_r[j];
    32             j++;
    33             k++;
    34         }
    35     
    36 
    37 }
    38 
    39 void mergeSort(int arr[], int l, int r)
    40 {
    41     if (l < r)
    42     {
    43         int m = l + (r - l) / 2;
    44 
    45         mergeSort(arr, l, m);
    46         mergeSort(arr, m + 1, r);
    47 
    48         merge(arr, l, m, r);
    49     }
    50 }

    再贴张排序的时间与空间复杂度的图

    总结: 

    为什么堆排序的时间复杂度理想却很少被采用:

    作者:qinzp
    链接:https://www.zhihu.com/question/23873747/answer/327295185
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    -------------------------------------------------------------------
    堆排序下,数据读取的开销变大。在计算机进行运算的时候,数据不一定会从内存读取出来,而是从一种叫cache的存储单位读取。原因是cache相比内存,读取速度非常快,所以cache会把一部分我们经常读取的数据暂时储存起来,以便下一次读取的时候,可以不必跑到内存去读,而是直接在cache里面找。
    一般认为读取数据遵从两个原则:temporal locality,也就是不久前读取过的一个数据,在之后很可能还会被读取一遍;另一个叫spatial locality,也就是说读取一个数据,在它周围内存地址存储的数据也很有可能被读取到。因此,在读取一个单位的数据(比如1个word)之后,不光单个word会被存入cache,与之内存地址相邻的几个word,都会以一个block为单位存入cache中。另外,cache相比内存小得多,当cache满了之后,会将旧的数据剔除,将新的数据覆盖上去。
    在进行堆排序的过程中,由于我们要比较一个数组前一半和后一半的数字的大小,而当数组比较长的时候,这前一半和后一半的数据相隔比较远,这就导致了经常在cache里面找不到要读取的数据,需要从内存中读出来,而当cache满了之后,以前读取的数据又要被剔除。
    简而言之快排和堆排读取arr[i]这个元素的平均时间是不一样的。
     
    ----------------------------------------------------------------------
    快速排序最优的情况就是每一次取到的元素都刚好平分整个数组,最优的情况下时间复杂度为:O( nlogn )

      最差的情况就是每一次取到的元素就是数组中最小/最大的,这种情况其实就是冒泡排序了(每一次都排好一个元素的顺序),快速排序最差的情况下时间复杂度为:O( n^2 )

         最优的情况下空间复杂度为:O(logn)  ;每一次都平分数组的情况
         最差的情况下空间复杂度为:O( n )      ;退化为冒泡排序的情况(用来存储哨兵变量的临时值)
    ----------------------------------------------------------------------------

    快排数据越无序越快(加入随机化后基本不会退化),平均常数最小,不需要额外空间,不稳定排序。
    归排速度稳定,常数比快排略大,需要额外空间(还有个东西叫多路归并),稳定排序。(归并排序需要额外空间记录子数组的值)

    ------------------------------------------------------------------------

    实际问题中归并排序并不比快排应用少。快排需要递归,就这一点基就可以在许多大数据应用场景把它枪毙了。而归并排序的scale能力比快排好很多,可以分布式处理,其实很受欢迎的

  • 相关阅读:
    python从可迭代对象中取值
    python中可迭代对象和列表
    python中字典生成式
    Redis源码解析之跳跃表(一)
    Redis高可用集群
    Redis主从&哨兵集群搭建
    Java并发之ThreadPoolExecutor源码解析(三)
    Java并发之ThreadPoolExecutor源码解析(二)
    Java并发之ThreadPoolExecutor源码解析(一)
    并发编程之JMM&Volatile(三)
  • 原文地址:https://www.cnblogs.com/wangshaowei/p/11379469.html
Copyright © 2011-2022 走看看