冒泡排序,插入排序,选择排序的C++实现-创新互联

tags: DSA Sort C++ 写在前面

总结一下经典的排序算法, 这次是基本排序算法, 冒泡插入和选择, 加上自己的理解与C++实现.

成都创新互联公司秉承实现全网价值营销的理念,以专业定制企业官网,网站制作、成都网站设计,小程序开发,网页设计制作,成都手机网站制作网络营销推广帮助传统企业实现“互联网+”转型升级专业定制企业官网,公司注重人才、技术和管理,汇聚了一批优秀的互联网技术人才,对客户都以感恩的心态奉献自己的专业和所长。辅助代码

这里给出了输出数组的函数, 通过STL的vector来完成.

#include#includeusing namespace std;
void printArray(const vector& arr) {for (size_t i = 0; i< arr.size(); ++i) cout<< arr[i]<< " ";
    cout<< endl;
}
冒泡

最为经典的排序算法, 虽然时间复杂度也相当高, 应该是很多同学入门编程语言学到的第一个排序算法.

思路很简单, 就是通过每次比较相邻两数的大小, 保证较大的那个值在后面, 如此进行n轮(数组长度), 即可得到排序好的数组.

void BubbleSort(vector& arr) {int n = arr.size();
    for (int i = n; i >0; --i) {// 每一轮都标记是否进行过交换
        bool exchanged = false;
        for (int j = 1; j< i; ++j)
            if (arr[j - 1] >arr[j]) {swap(arr[j - 1], arr[j]);
                exchanged = true;
            }
        if (!exchanged) break;
    }
}

另一种写法:

void BubbleSort(vector& arr) {int n = arr.size();
    for (int i = 1; i< n; ++i) {bool exchanged = false;
        for (int j = 0; j< n - i; ++j)
            if (arr[j] >arr[j + 1]) {swap(arr[j], arr[j + 1]);
                exchanged = true;
            }
        if (!exchanged) break;
    }
}
插入

按照算法导论上面的比喻, 插入排序就是从桌上扣过来的未排序的扑克牌中依次向手上的已排好序的扑克牌中插入.

void InsertionSort(vector&arr) {int n = arr.size();
    // 左边为已排序区,右边是待排序区
    for (int j = 1; j< n; ++j) {int i = j - 1, tmp = arr[j]; // tmp:待插入元素
        // 往后挪元素,腾出来位置留给tmp
        while (i >= 0 && arr[i] >tmp) {arr[i + 1] = arr[i];
            --i;
        }
        // 上面的这个while循环可以用for一行完成:
        // for (; i >= 0 && arr[i] >tmp; --i) arr[i + 1] = arr[i];
        // 最后插入tmp
        arr[i + 1] = tmp;
    }
}

但是这里我就有一个困惑了, 为什么不能用从前向后的遍历方式呢?

后来我写了个前向遍历, 才发现了问题所在.

void InsertionSort(vector&arr) {int n = arr.size();
    // 遍历待插入元素
    for (int i = 1; i< n; ++i) {int tmp = arr[i], j{};
        // 从前往后遍历, 寻找插入位置(遍历已排好序的元素)
        while (j< i && arr[j]<= tmp) ++j;
        if (j == i) continue;
        int idx = j;
        // 下面两种for循环, 结果是一样的
        // for (; i >idx; --i) arr[i] = arr[i - 1];
        for (int k{}; k<= i - idx; ++k) arr[i - k] = arr[i - 1 - k];
        arr[idx] = tmp;
    }
}

前向遍历需要先找到待插入的位置, 然后往后移动腾出来待插入元素要放置的位置, 相当于在遍历未排序部分的内部套了两个循环, 而不是像后往前遍历那样直接在寻找到要插入的位置之后就直接进行挪元素了, 省去了一重循环, 并且写起来方便很多.

选择

通过每次遍历数组的未排序部分, 找到大值(或者最小值)放在已排序数组的末尾, 即可.

void SelectSort(vector&arr) {int n = arr.size(), i{};
    while (i< n) {int min1 = i;
        for (int j = i + 1; j< n; ++j)
            if (arr[min1] >arr[j]) min1 = j;
        if (min1 != i) swap(arr[min1], arr[i]);
        i++;
    }
}

或者for写法:

void SelectSort(vector&arr) {int n = arr.size();
    for (int i{}; i< n; ++i) {int min1 = i;
        for (int j = i + 1; j< n; ++j)
            if (arr[min1] >arr[j]) min1 = j;
        if (min1 != i) swap(arr[min1], arr[i]);
    }
}
总结

这三种都是比较经典的原地排序算法, 但是时间复杂度都比较高, 其中蕴含的思路可以为之后的快排等算法打基础.

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


本文标题:冒泡排序,插入排序,选择排序的C++实现-创新互联
转载注明:http://pwwzsj.com/article/dpophs.html