• 【C++】冒泡排序算法实现与性能优化


    参考:https://blog.csdn.net/pilipilipan/article/details/79702298

    简述

    重复进行相邻数组元素的两两比较,并按规则进行交换,直到没有元素再需要交换。最终使得大的元素逐渐沉到数列底部,相较小的元素浮现到数列前端。

    算法描述

    1 比较相邻两个元素,如果第一个比第二个大,就交换位置。
    2 从第一对开始,对数组中的每一对相邻的两个元素重复步骤1,使得最大的元素沉到数组底部。
    3 重复步骤2,除了底部已经排序好的元素。(每一趟都会多一个以排序好的元素)
    4 重复以上步骤直到排序完成

    算法分析

    最好:T(n)=O(n);数据全部正序
    最差:T(n)=O(n^2);数据全部反序
    平均:T(n)=O(n^2);

    基本实现

    配套设施一起奉上!

    #include<iostream>
    #include<vector>
    
    using namespace std;
    
    //冒泡算法原始
    void bubbleSort(vector<int> & a) {
        int n = a.size();
        for (int i = 0;i < n-1;++i) {
            for (int j = 0;j < n - i - 1;++j) {
                if (a[j] > a[j + 1]) {
                    swap(a[j], a[j + 1]);
                }
            }
        }
    }
    
    //打印数组
    void printVector(const vector<int>& a) {
        for (auto i : a) {
            cout << i << " ";
        }
        cout << endl;
    }
    
    int main() {
    
        vector<int> a{ 5,6,4,2,3 };
        bubbleSort(a);
        printVector(a);
    
        system("pause");
        return 0;
    }
    

    性能优化

    1、增加了反向冒泡。传统冒泡排序每一趟排序一次,找出一个最大值。改进后每一趟排序两次,正向冒泡,找出最大的元素;反向冒泡,找出最小元素,使得一次可以得到两个最终值。从而减少排序趟数。
    2、增加了标志点flag。目的在于记录每一趟最后一次交换的元素位置,即表示标志点之后或者之前的位置已经排好,后续无需再排,缩小排序区间,减少排序次数。

    #include<iostream>
    #include<vector>
    
    using namespace std;
    
    //冒泡算法原始
    void bubbleSort1(vector<int> & a) {
        int n = a.size();
    
        for (int i = 0;i < n - 1;++i) {
            for (int j = 0;j < n - i - 1;++j) {
                if (a[j] > a[j + 1]) {
                    swap(a[j], a[j + 1]);
                }
            }
        }    
    }
    
    //冒泡算法改进1-增加flag,减少不必要的循环
    void bubbleSort2(vector<int>& a) {
        int n = a.size();
        for (int i = 0;i < n - 1;++i) {
            bool sorted = true;
            for (int j = 0;j < n - i - 1;++j) {
                if (a[j] > a[j + 1]) {
                    swap(a[j], a[j + 1]);
                    sorted = false;//如果发生数据交换,说明数组无序
                }
            }
            if (sorted) {//数组有序
                break;
            }
        }
    }
    //冒泡算法改进2-采用双向冒泡,正向冒泡冒出最大值,反向冒泡冒出最小值
    void bubbleSort(vector<int> &a) {
        int n = a.size();
        int low = 0, high = n - 1;
        while (low < high) {//排序区间[low,high]
            int flag = 0;//标志点
            for (int i = low; i < high; ++i) {//第1次,正向冒泡
                if (a[i] > a[i + 1]) {
                    swap(a[i], a[i + 1]);
                    flag = i;
                }
            }
            high = flag;//表示标志点之后的元素已经排好,区间右值缩小
            for (int i = high; i > low; --i) {//第2次,反向冒泡
                if (a[i] < a[i - 1]) {
                    swap(a[i], a[i - 1]);
                    flag = i;
                }
            }
            low = flag;//表示断点之前的元素已经排好,区间左值缩小 
        }
    }
    
    
    //打印数组
    void printVector(const vector<int>& a) {
        for (auto i : a) {
            cout << i << " ";
        }
        cout << endl;
    }
    
    int main() {
    
        vector<int> a{ 5,6,4,2,3 };
        bubbleSort(a);
        printVector(a);
    
        system("pause");
        return 0;
    }
    
  • 相关阅读:
    高盛、沃尔玛 题做出来还挂了的吐槽
    amazon师兄debrief
    到所有人家距离之和最短的中点 296. Best Meeting Point
    问问题没人回答的情况怎么办终于有解了
    找名人 277. Find the Celebrity
    数组生存游戏 289. Game of Life
    547. Number of Provinces 省份数量
    428. Serialize and Deserialize Nary Tree 序列化、反序列化n叉树
    alias别名简介和使用
    面试官:线程池执行过程中遇到异常会发生什么,怎样处理? Vincent
  • 原文地址:https://www.cnblogs.com/dindin1995/p/13059111.html
Copyright © 2020-2023  润新知