zoukankan      html  css  js  c++  java
  • 细数那些我们熟悉的 排序!

    第一个 ,不得不说的 是 <冒泡排序>

          作为 一个非常经典,又差劲的算法 。

          计算过程如下:

        ->每次遍历数组,通过对比,使最大的冒上去,

               ->这样通过N次的轮循 ,可以使 排序的数组有序。

          优点:简单,适用性强。

      缺点:慢。

      适用性:数组,链表.

      性质:稳定性排序【打乱元素的稳定性,也就是 你不知道 这个元素 一开始是 3,3,3,排序后的 这个三是哪个三】。

      复杂度:平均 n^2,在有序的情况下,可以 O(N) ,

           代码: 不写

     二:归并排序:

       前言:归并排序,是利用分治的思想,

    也就是说 将一个大问题化为一些小问题,这样在解决小问题的情况下,

    在通过,合并操作,使以解决的小问题称以解决的大问题。

          计算过程如下:

        ->将一个数组递归的分解成俩断->四段->八段->直到分解称只有一个元素

               ->在一个元素的情况下,这断可以认为是有序的,进而满足解决了这个小问题

        ->对于合并,对于俩段有序的数组,只要在每个数组上打一个index每次取最小的那个元素不,知道元素取完毕就好。

          优点:稳定,效率一般(不断的SWAP)

      缺点:需要额外的内存。

      适用性:数组,链表(需要预先处理出分段,麻烦,一般可以认为不支持).

      性质:稳定性排序

      复杂度:平均 n*log(n)。

      代码:

    void mergeSort(int v[], int l, int r, int tmpArray[]) {
        if (l == r) {
            return;
        }
        int mid = l + (r - l) / 2;
        mergeSort(v , l, mid, tmpArray);
        mergeSort(v , mid + 1, r, tmpArray);
        for (int i = l, j = mid + 1, idx = l ; i <= mid || j <= r; ) {
            if (i <= mid) {
                if(j <= r) {
                    tmpArray[idx++] = v[i] <= v[j] ? v[i++] : v[j++];
                } else {
                    tmpArray[idx++] = v[i++];
                }
            }  else {
                tmpArray[idx++] = v[j++];
            }
        }
        for(int i = l; i <= r ; i ++) {
            v[i] = tmpArray[i];
        }
    }

    三:堆排序:

      堆排序,人如其名,利用堆来排序,原理有些类似于冒泡排序,都是每次找出最大值。

      盗图->

      简要的说一下堆,一般的堆都是指 二叉堆,也就是,上图是一个小顶堆,也就是说,父亲节点的元素值比他的儿子节点的元素的值都小。

      数组有一个很好的性质 

        对于  position = i 的元素 他的左儿子 可以表示为 i<<1(i*2) ,右儿子可以表示为i<<1|1 (i*2+1)

      也正是因此堆可以用老模拟数组的排序过程

      

    void build(int * a, int pos, int n) {
    
        while(true) {
            int lSon = pos << 1;
            int rSon = pos << 1 | 1;
            if (lSon > n) break;
            int target = rSon > n ? lSon : a[lSon] > a[rSon] ? lSon : rSon;
    
            if (a[pos] < a[target]) {
                swap(a[pos], a[target]);
                pos = target;
            } else {
                break;
            }
        }
    
    }
    void heapSort(int * a, int n) {
        for(int i = n ; i >= 1 ;--i) {
            build(a, i, n);
        }
        for(int i = n ; i > 1  ;--i) {
            swap(a[1], a[i]);
            build(a, 1, i - 1);
        }
    }

      过程:

        1.数组作为堆初始化成为大顶堆。这样堆顶元素是最大的

        2.把堆顶元素的值和最后一个位置元素的值做一个交换,同时堆的大小减一。 ->这样这个值,是所有元素中最大的且已经在最后面了。

        3.上边的操作就如同 删除堆顶元素的操作,只不过把堆顶元素放到了最后。

        4.删除堆顶元素后进行更新操作,递归向下,保持堆的性质

        5.重复2到4的操作,直到堆内没有元素。

          优点:稳定,效率一般(不断的SWAP)。

       缺点:稳定,同时中庸,比归并排序要快(个人见解)。

      适用性:数组,(链表不支持吧?)

      性质:非稳定性排序

      复杂度:平均 n*log(n)。

    四:快速排序:

      快排,为什么叫快排?因为他快, 这个排序,也算是分治的思想,

      和归并的相反,先计算在递归分解,  而归并是先递归分解,在合并。

      过程,

        1.在这断内选取出一个关键的key值,同时指定俩个指针(就是位置表示符号)一个起始,一个结束(这里先认为取左侧第一个,不是的可以,用swap来达到这个状态)

        2.先从左开始比较,如果都比他小OK左侧的指针右移,否则把这个元素的值丢给右侧指针(不用担心左侧这个值怎么办,提示:提取出来的KEY),然后从右边开始扫描(向左侧)

        3.同上,知道扫描到一个比这个小的OK在此交换俩个指针指向的元素。在此从左侧的指针开始扫描

        4.重复2,3直到俩个指针指向同一个位置,OK,本次扫描结束

        5.这样连个指针只想的位置赋值为KEY那么左侧都比他小, 右侧都比她大,

        6.数据根据指针的位置,查分为俩段 利用1-4这个过程,求解即可。

    代码:

      

    void sort(int * v, int l ,int r){
        if (l >= r) return;
        int key = v[l];
        int low = l, high = r;
        while(low < high) {
            while(low < high && v[high] >= key) high --;
            v[low] = v[high];
            while(low < high && v[low]  <= key) low ++;
            v[high] = v[low];
        }
        v[low] = key;
        sort(v, l, low - 1);
        sort(v, low + 1, r);
    }
    View Code

      

     优点:内存无额外消耗,平均而言了认为是最好的排序算法。

    性质,非稳定性排序。

    复杂度n* logn,最坏情况下会退化到n^2

    适用性,数组,链表。

    ,这个算法的关键在于寻找那个KEY,能让左右平衡一些(有三分写法),这个算法,扫描多余交换.

    有些代码我没写(想要写给你,夜深了)

  • 相关阅读:
    大数据和云计算如何实现视频行业更快速有效的智能分析?
    TSINGSEE青犀视频云边端架构流媒体平台的接口鉴权和接口保活是什么关系?
    TSINGSEE青犀视频和海康合作研发RTMP摄像头如何通过内存卡进行视频录像存储?
    RTMP视频推流功能组件EasyRTMP-HIK DEMO版本运行报错0xc000007b问题排查分析
    互联网视频直播&点播平台RTMP推流组件EasyRTMP如何获取当前推流状态 ?
    程序员修炼之道阅读笔记(一)
    周进度总结
    2020年秋季个人阅读计划
    周进度总结
    Java的Swing布局
  • 原文地址:https://www.cnblogs.com/shuly/p/6120043.html
Copyright © 2011-2022 走看看