• 常用排序算法c/c++



    前言

    列举了常用排序算法,并给出代码
    对算法的核心思想进行了简明扼要地说明


    选择排序

    从数组中选出最小的元素,将其与前面的元素互换

    #include <cstdio>
    
    void select_sort(int *arr, size_t arr_size)
    {
        for (int i=0; i<arr_size; ++i){
            for (int j=i+1; j<arr_size; ++j){
                if (arr[j] < arr[i]){
                    int tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                }
            }
        }
    }
    
    int main()
    {
        int arr[]= {56,7,8,8,0,1};
        select_sort(arr, sizeof(arr)/sizeof(arr[0]));
        for (auto c: arr) std::printf("%d ", c);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    时间复杂度:O(n^2)
    n-1+n-2+······+1+0 ~ n^2

    空间复杂度:O(1)
    占用常量空间

    冒泡排序

    比较相邻的两元素,确定是否互换,经过一边遍历后最大/小的元素像泡泡一样冒出来,经过多次遍历后完成排序

    void bubble_sort(int *arr, size_t arr_size)
    {
        for (int i=0; i<arr_size; ++i){
            for (int j=1; j<arr_size-i; ++j){
                if (arr[j-1] > arr[j]){
                    int tmp = arr[j-1];
                    arr[j-1] = arr[j];
                    arr[j] = tmp;
                }
            }
        }
    }
    
    int main()
    {
        int arr[]= {56,7,8,8,0,1};
        bubble_sort(arr, sizeof(arr)/sizeof(arr[0]));
        for (auto c: arr) std::printf("%d ", c);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 时间复杂度:O(n^2)

        n-1+n-2+······+1+0 ~ n^2

    • 空间复杂度:O(1)

        占用常量空间

    优化版

    void bubble_sort(int *arr, size_t arr_size)
    {
        for (int i=0; i<arr_size; ++i){
        	bool flag = true;
            for (int j=1; j<arr_size-i; ++j){
                if (arr[j-1] > arr[j]){
                    int tmp = arr[j-1];
                    arr[j-1] = arr[j];
                    arr[j] = tmp;
                    flag = false;
                }
            }
            if ( flag) break;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    堆排序

    堆是用数组存储的完全二叉树,并且父节点比孩子节点小(小顶堆)/大(大顶堆)
    可用于解决topK问题

    leftchild = 2\*parent + 1
    rightchild = 2\*parent +2
    parent = [ (leftchld - 1) / 2]
    parent = [ (rightchild- 1) / 2]
    
    • 1
    • 2
    • 3
    • 4
    #include <cstdio>
    
    void shift_below(int *arr, int parent, int end )
    {
        int child = 2*parent + 1;
        while (child < end){
            if ( child+1 < end && arr[child] < arr[child+1]){
                ++child;
            }
            if (arr[parent] < arr[child]){
                int tmp = arr[parent];
                arr[parent] = arr[child];
                arr[child] = tmp;
                parent = child;
                child = 2*parent + 1;
            } else {
                break;
            }      
        }
    }
    
    void create_heap(int *arr, int arr_size)
    {
        int parent = (arr_size - 1 - 1) / 2;
        for (int i=parent; i>=0; --i){
            shift_below(arr, i, arr_size);
        }
    }
    
    void heap_sort(int *arr, int arr_size)
    {
        create_heap(arr, arr_size);
        for (int i=arr_size-1; i>0; --i){
            int tmp = arr[0];
            arr[0] = arr[i];
            arr[i] = tmp;
            shift_below(arr, 0, i);
        }
    }
    
    int main()
    {
        int arr[]= {56,7,8,8,0,1};
        heap_sort(arr, sizeof(arr)/sizeof(arr[0]));
        for (auto c: arr) std::printf("%d ", c);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 时间复杂度: O(n * logN)
           2*(logn + logn-1 + logn-2 ······ log 1)
    • 空间复杂度: O(1)

    快速排序

    分治思想:将大问题简化为小问题,解决每个小问题,从而大问题得到解决
    减治思想:将大问题简化为小问题,解决一个小问题,从而大问题得到解决

    // 选择第一个作为基准,它左边的都比他小(<=),右边的都比他大(>=)
    // 返回这个基准的索引
    // 左右两边都能取到
    int partition(int *arr, int start, int end)
    {
        int base = arr[start];
        while (start < end)
        {
            while (start < end && arr[end] >= base){
                --end;
            }
            arr[start] = arr[end];
            while (start < end && arr[start] <= base){
                ++start;
            }
            arr[end] = arr[start];
        }
        arr[start] = base;
        return start;
    }
    
    void quick_sort(int *arr, int start, int end)
    {
        if (start >= end) return ;
        int i = partition(arr, start, end);
        quick_sort(arr, start, i-1);
        quick_sort(arr, i+1, end);
    }
    
    int main()
    {
        int arr[]= {7,2,6,4,5,1,7,8,9};
        // 左右两边都能取到
        quick_sort(arr, 0, sizeof(arr)/sizeof(arr[0])-1  );
        for (auto c : arr)
            std::printf("%d ", c);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    归并排序

    将一个无序数组递归的的分成两个数组,将仅有两个元素的数组排序。将两个有序的数组合并成一个。

    核心代码是将两个有序的数组合并成一个有序的数组

    #include <cstdio>
    // 左边取得到,右边取不到
    void merge_sort(int *arr, int start, int mid, int end)
    {
        int p1 = start;
        int p2 = mid;
        int tmp[end-start] = {0};
        int point = 0;
        while (1){
            if ( p1 >= mid){
                while (point < end-start && p2<end){
                    tmp[point++] = arr[p2++];
                }
                break;
            }
            if ( p2 >= end){
                while (point < end-start && p1<mid){
                    tmp[point++] = arr[p1++];
                }
                break;
            }
            if (arr[p1] < arr[p2]){
                tmp[point++] = arr[p1++];
            } else {
                tmp[point++] = arr[p2++];
            }
        }
        for (int c:tmp){
            arr[start++] = c;
        }
    }
    
    void m_sort(int *arr, int start, int end)
    {
        if (start >= end) return ;
        if (end - start == 1){
            if (arr[start] > arr[end]){
                int tmp = arr[start];
                arr[start] = arr[end];
                arr[end] = tmp;
            }
            return ;
        }
        int mid = (start+end) / 2;
        m_sort(arr, start, mid);
        m_sort(arr, mid, end);
        merge_sort(arr, start, mid, end);
    }
    
    int main()
    {
        int arr[] = {5,7,6,9,1,5,0,9,8,7,3,7};
        m_sort(arr, 0, sizeof(arr)/sizeof(arr[0]) );
        for (int c: arr){
            std::printf("%d ", c);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 时间复杂度: O(N * logN)
    • 空间复杂度:O(N)
    • 稳定性: 稳定
  • 相关阅读:
    Objective-C对象dealloc过程
    js Fetch返回数据res.json()报错问题
    30个CSS选择器
    搜索引擎中的相关性模型
    python+requests接口自动化测试框架实例详解教程
    NC20583 [SDOI2016]齿轮
    java写一个自动爬取统计局公开数据的程序
    [UUCTF 2022 新生赛]ezpop - 反序列化+字符串逃逸【***】
    LeetCode | 225. 用队列实现栈
    管理员模式运行cmd或则bat文件的时候,出现路径错误的问题
  • 原文地址:https://blog.csdn.net/surfaceyan/article/details/125433733