zoukankan      html  css  js  c++  java
  • 常用的排序

    常用排序算法

    我们通常说的排序都是内部排序,就是数据在内存中进行排序

    一种是比较排序,时间复杂度O(nlogn) ~ O(n^2),主要有:冒泡排序选择排序插入排序归并排序堆排序快速排序等。

    另一种是非比较排序,时间复杂度可以达到O(n),主要有:计数排序基数排序桶排序等。

    特殊记法:

      平均时间复杂度:军训教练说快些nlog2n的速度归队,  就是快些归队快排,希尔,归并,堆排)nlog2n  

      其他的都是O(n2),有个特殊的是基数排序

      稳定性:考研复习痛苦啊,情绪不稳定, 快些选一堆好友聊天(快排,希尔,选择,堆)

      空间复杂度:快排是O(nlog2n),归并是O(n)基数是O(n+k), 其他都是O(1)

    常用排序的比较

    算法复杂度

    冒泡排序

    冒泡排序可以说是最简单的一种排序了,我们学习的第一种排序算法,

    排序思想:

    1. 比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
    3. 针对所有的元素重复以上的步骤,除了最后一个。
    4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

    代码:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 void print(int arr[], int n)
     5 {
     6     for (int i = 0; i < n; i++)
     7     {
     8         cout << arr[i]<<" ";
     9     }
    10     cout << endl;
    11 }
    12 
    13 void Swap(int *a, int *b)
    14 {
    15     int t;
    16     t  = *a;
    17     *a = *b;
    18     *b = t;
    19 }
    20 
    21 void maoSort(int arr[], int n)
    22 {
    23     int i, j;
    24     for(i = 0; i < n; i++)
    25     {
    26         for(j = 0; j < n-1-i; j++)
    27         {
    28             if (arr[j] > arr[j+1])
    29             {
    30                 Swap(&arr[j], &arr[j+1]);
    31             }
    32         }
    33     }
    34 
    35 }
    36 
    37 int main() {
    38     int arr[10] = {1,3,5,7,9,2,4,6,0,-5};
    39     maoSort(arr, 10);
    40     print(arr, 10);
    41     return 0;
    42 }
    冒泡排序
    稳定性:稳定排序。
    
    时间复杂度: O(n)至O(n2),平均时间复杂度为O(n2)。
    
    最好的情况:如果待排序数据序列为正序,则一趟冒泡就可完成排序,排序码的比较次数为n-1次,且没有移动,时间复杂度为O(n)。
    
    最坏的情况:如果待排序数据序列为逆序,则冒泡排序需要n-1次趟起泡,每趟进行n-i次排序码的比较和移动,即比较和移动次数均达到最大值: 
    比较次数:Cmax=∑i=1n−1(n−i)=n(n−1)/2=O(n2) 
    移动次数等于比较次数,因此最坏时间复杂度为O(n2)。

    插入排序

    插入排序是将一个记录插入到已经有序的序列中,得到一个新的元素加一的有序序列, 实际上即将第一个元素看成一个有序的序列,

    从第二个元素开始逐个插入得到一个完整的有序序列,插入过程如下: 

    #include <iostream>
    using namespace std;
    
    // 平均时间复杂度 ---- O(n^2)
    // 所需辅助空间 ------ O(1)
    // 稳定性 ------------ 稳定
    
    // 思路:每一趟将一个待排序的记录,按照其关键字的大小插入到已经拍好序的一组数据中,
    // 将第一个看成已经排好序的,然后每次来一个,与前面排好序的进行比较,然后插入。
    // 就像打牌一样,每次来一张牌,比较后然后插入进去。
    void InsertSort(int arr[], int n)
    {
        for (int i = 1; i < n; i++)   // 类似扑克牌 排序
        {
            int get = arr[i];  //  右手拿到一张牌
            int j = i - 1;    //   左手上的牌总是排序好的,
    
            while (get < arr[j] && j >= 0)  // 将右手的牌与左手的牌 从右向左比较
            {
                arr[j+1] = arr[j];   // 如果左手的牌比抓到的大,将其右移动
                j--;
            }
            arr[j+1] = get;    // 直到左手牌比抓到的牌小(或二者相等),将抓到的牌插入到左手牌右边
                               // (相等元素的相对次序未变,所以插入排序是稳定的)
        }
    }
    
    void print(int arr[], int n);
    int main() {
        int arr[10] = {1,3,5,7,9,2,4,6,0,-5};
        InsertSort(arr, 10);
        print(arr, 10);
        return 0;
    }
    
    void print(int arr[], int n)
    {
        for (int i = 0; i < n; i++)
        {
            cout << arr[i]<<" ";
        }
        cout << endl;
    }
    直接插入排序

    https://www.cnblogs.com/eniac12/p/5329396.html

    快速排序

    该方法的基本思想是:

    1.先从数列中取出一个数作为基准数。

    2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

    3.再对左右区间重复第二步,直到各区间只有一个数

    自己总结的快排思想:

    // 思路:先找一个基准(挖坑),然后从后向前找比他小的,然后把这个数填那个(坑)
    // 在从前往后找个比他大的,把这个数填进上一个坑,
    // 循环一轮后,这个基准就是最终的位置(基准左边都比他小,右边比他大)

    推荐博客

    https://blog.csdn.net/morewindows/article/details/6684558

    #include <iostream>
    #include <vector>
    using namespace std;
    class Solution
    {
        // 思路:先找一个基准(挖坑),然后从后向前找比他小的,然后把这个数填那个(坑)
        // 在从前往后找个比他大的,把这个数填进上一个坑,
        // 循环一轮后,这个基准就是最终的位置(基准左边都比他小,右边比他大)
    public:
        int quick_sort(vector<int>&vec, int left, int right)
        {
            int i = left, j = right;
            int temp;
            if (left < right)
            {
                temp = vec[left];
                // 这个循环完成一趟排序,小于temp的数在左边,大于的在右边
                while(i < j)
                {
                    // 从后向前找比temp小的
                    while(i < j && vec[j] >= temp)
                                --j;
                    if (i < j)
                        vec[i++] = vec[j]; //找到那个比他小的了,把他填在前面坑里
    
    
                    // 从前向后找比temp大的
                    while(i < j && vec[i] < temp)
                                ++i;
                    // 找到那个比temp大的数,让他填到后面的坑
                    if (i < j)
                        vec[j--] = vec[i];
                }
    
                vec[i] = temp;   // 把temp放在最终的位置
    
                // 此时i的位置就是temp的位置
                quick_sort(vec, left, i-1); // 对temp左边递归调用
                quick_sort(vec, i+1, right); //对temp右边递归调用
    
            }
        }
    };
    int main()
    {
        vector<int> vec = {3,5,6,32,35,56,3};
        Solution s;
        s.quick_sort(vec,0, vec.size()-1);
        for(int i = 0; i< vec.size(); i++)
            cout << vec[i] << " ";
        return 0;
    }
    View Code

    感觉代码乱,这是核心代码

     1 int quick_sort(vector<int>&vec, int left, int right)
     2     {
     3         if (left < right)
     4         {
     5             int i = left, j = right;
     6             int temp = vec[i];
     7             while(i < j)
     8             {
     9                 // 从后向前找比temp小的
    10                 while(i < j && vec[j] >= temp)
    11                             --j;
    12                 if (i < j)
    13                     vec[i++] = vec[j];
    14 
    15                 // 从前向后找比temp大的
    16                 while(i < j && vec[i] < temp)
    17                             ++i;
    18                 if (i < j)
    19                     vec[j--] = vec[i];
    20             }
    21 
    22             vec[i] = temp;   // 把temp放在最终的位置
    23             quick_sort(vec, left, i-1); // 对temp左边递归调用
    24             quick_sort(vec, i+1, right); //对temp右边递归调用
    25 
    26         }
    27     }
    View Code
  • 相关阅读:
    使用Yeoman搭建 AngularJS 应用 (9) —— 让我们搭建一个网页应用
    advance shading——菲涅耳现象
    现代编译原理--第六章(中间树 IR Tree 含源码)
    现代编译原理--第五章(活动记录)
    现代编译原理--第四章(语义分析以及源码)
    现代编译原理--第三章(抽象语法树以及源码)
    现代编译原理--第二章(语法分析之LL(K))
    现代编译原理--第一章(词法分析)
    advance shading--BRDF
    个人作业——软件工程实践总结作业
  • 原文地址:https://www.cnblogs.com/xiaokang01/p/9782259.html
Copyright © 2011-2022 走看看