• 排序算法总结


    排序算法总结

    直接插入排序

    基本思想:将一个值插入到已经排好序中的相应位置。

        void InsertSort(std::vector<int>& arr) {
            for (size_t i = 1; i < arr.size(); i++) {
                if (arr[i] < arr[i-1]) {
                    size_t k = i;
                    int val = arr[k]; //保存下自己
                    arr[k] = arr[i-1];//向后移一位
                    while (val < arr[k-1] && k > 0) {
                        arr[k] = arr[k-1];
                        k--;
                    }
                    arr[k] = val;
                    printArray(i, arr);
                }
            }
        }
    

    冒泡排序

    基本思想:两两比较相邻纪录的关键字,如果是反序的则进行交换。

    // 普通排序
        void BubbleSort(std::vector<int>& arr) {
            size_t len = arr.size();
            for (size_t i = 0; i < len; i++) {
                //内层的每一次循环,都会将最大的数推向数组高层,也就是说i代表了高层中已经排好序的个数
                for (int j = 1; j < len-i; j++) {
                    if (arr[j-1] > arr[j]) { //两两比较
                        std::swap(arr[j-1], arr[j]);
                    }
                }
    
                printArray(i, arr);
            }
        }
    
        // 设置标记位,如果一次循环中没有移位,那么则表明接下来的值的顺序已经排好了
        void BubbleSort2(std::vector<int>& arr) {
            size_t len = arr.size();
    
            bool flag = true;
            size_t k = len;
            while (flag) {
                flag = false;
                for (int j = 1; j < k; j++) {
                    if (arr[j-1] > arr[j]) {
                        std::swap(arr[j-1], arr[j]);
                        flag = true;
                    }
                }
                k --;
            }
        }
    
        // 设置上次移动的位置,表明上次之前的位置已经拍好了序,接下来只需要排上次位置之前的即可
        void BubbleSort3(std::vector<int>& arr) {
            size_t len = arr.size();
            size_t flag = len;
            while (flag > 0) {
                size_t k =  flag;
                flag = 0;
                for (size_t j = 1; j < k; j++) {
                    if (arr[j-1] > arr[j]) { //两两比较
                        std::swap(arr[j-1], arr[j]);
                        flag = j;
                    }
                }
            }
        }
    
        // 双向冒泡排序,在之前的排序中,每次的内层循环只能找出一个最大值或者最小值
        // 现在双向排序后同时找出一个最大值和最小值
        void BubbleSort4(std::vector<int>& arr) {
            size_t low = 0, high = arr.size() - 1;
    
            while (low < high) {
                for (size_t i = low; i < high; i++) {
                    if (arr[i] > arr[i + 1]) {
                        std::swap(arr[i], arr[i + 1]);
                    }
                }
                high--;
                for (size_t i = high; i > low; i--) {
                    if (arr[i - 1] > arr[i]) {
                        std::swap(arr[i - 1], arr[i]);
                    }
                }
                low++;
            }
        }
    
    

    简单选择排序

    基本思想:从一个数组中选择一个最小(或者最大)的值和第一个位置进行交换,接着选择次的值和第二个位置交换,以此类推。

    void SelectSort(std::vector<int>& arr) {
            // 每次从指定的数组间隔中选择一个最小的
            auto selectMin = [&](size_t start) {
                size_t k = start;
                for (size_t i = start+1; i < arr.size(); i++) {
                    if (arr[i] < arr[k]) {
                        k = i;
                    }
                }
                std::cout << "min:" << arr[k] << std::endl;
                return k;
            };
    
            size_t len = arr.size();
            for (size_t i = 0; i < len; i++) {
                size_t idx = selectMin(i);
                if (idx != i) {
                    std::swap(arr[idx], arr[i]);
                }
                printArray(i, arr);
            }
        }
    
    

    快速排序

    基本思想:

    1. 选择一个基准元素,通常选择第一个或者最后一个元素;
    2. 通过一趟排序将待排序的纪录分割成两个部分,其中一个部分比基准元素的值都小,另一个部分比基准元素都要大;
    3. 此时基准元素在排好序的正确位置;
    4. 然后分别对这两部分用同样的方法进行排序,直到整个序列都有序;

    int partition(std::vector<int>& arr, int low, int high) {
            int key = arr[low];
            while (low < high) {
                while (low < high && arr[high] >= key) {
                    high--;
                }
                std::swap(arr[low], arr[high]);
                while (low < high && arr[low] <= arr[high]) {
                    low++;
                }
                std::swap(arr[low], arr[high]);
            }
            printArray(0, arr);
            return low;
        }
    
        void QuickSort(std::vector<int>& arr, int low, int high) {
            if (low < high) {
                int key = partition(arr, low, high);
                QuickSort(arr, low, key);
                QuickSort(arr, key+1, high);
            }
        }
    
        void printArray(size_t idx, const std::vector<int>& arr) {
            if (arr.empty()) {
                std::cout << "没有数据" << std::endl;
                return ;
            }
            std::cout << "第" << idx + 1 << "趟:";
            for (int i = 0; i < arr.size(); i++) {
                std::cout << arr[i] << " ";
            }
            std::cout << std::endl;
        }
        
    

    堆排序

    基本思想:首先创建最小堆,在取出堆顶的元素之后进行调整堆,将对堆顶移到数组后面从而实现删除的意思,使其依旧是一个最小堆,直到堆中的元素都取完。

    void buidlHeap(std::vector<int>& arr) {
            int len = arr.size();
            // 这里根据父亲结点(最多为数组一半的位置)进行调整
            for (int idx = len/2; idx >= 0; idx--) {
                adjustHeap(arr, idx, len);
            }
        }
    
        // heapsize是用来控制堆的大小
        void adjustHeap(std::vector<int>& arr, int idx, int heapsize) {
            int left_idx = idx * 2 + 1, right_idx = left_idx+1;
    
            int min_idx = idx;
            // 找结点idx中左子结点和右子结点较小的
            if (left_idx < heapsize && arr[idx] > arr[left_idx]) {
                min_idx = left_idx;
            }
    
            if (right_idx < heapsize && arr[min_idx] > arr[right_idx]) {
                min_idx = right_idx;
            }
    
            if (min_idx != idx) {
                std::swap(arr[min_idx], arr[idx]);
                adjustHeap(arr, min_idx, heapsize);
            }
        }
    
        void HeapSort(std::vector<int>& arr) {
            buidlHeap(arr);
            printArray(0, arr);
            int len = arr.size();
            // 每次取出堆顶后,把堆顶置换到后面,通过heapsize删除该元素
            for (int i = len-1; i >= 0; i--) {
                std::cout << arr[0] << std::endl;
                std::swap(arr[0], arr[i]);
                adjustHeap(arr, 0, i);
            }
        }
    
    

    打印数组

    void printArray(size_t idx, const std::vector<int>& arr) {
            if (arr.empty()) {
                std::cout << "没有数据" << std::endl;
                return ;
            }
            std::cout << "第" << idx + 1 << "趟:";
            for (int i = 0; i < arr.size(); i++) {
                std::cout << arr[i] << " ";
            }
            std::cout << std::endl;
        }
    
    

    比较

  • 相关阅读:
    grep 精确匹配
    @ARGV
    同时查看多个文件
    R画双y轴图
    R画饼图
    linux的sort排序
    $0
    QQ图
    Config::Std模块安装
    R语言做正态分布检验
  • 原文地址:https://www.cnblogs.com/George1994/p/6796785.html
Copyright © 2020-2023  润新知