冒泡排序及优化

谁说我不能喝 提交于 2019-11-26 17:08:09

基础写法

冒泡排序思想:泡泡一直向上冒,冒到不能冒的位置。即每次比较两个相邻元素,如果顺序不对就交换,这样一轮交换就能确定当前最大/小值。

假设数组array[1...n]array[1...n],按照从小到大排序,如果第1个元素大于第2个元素,则交换两个元素,一直到第n-1个元素和第n个元素比较,那么一轮结束,第n个元素一定是该数组的最大值,接下来第2轮对array[1...n1]array[1...n-1]进行相同操作,第n-1个元素一定是第2大元素。一共需要n-1轮比较。

以下代码全部按照从小到大排序。

void bubblesort(vector<int> &numbers)
{
    int len = numbers.size();
    if(len <= 0) return;
    int swapTmp;
    for(int i = 1; i < len; i++) //确定比较轮数
    {
        for(int j = 0; j < len-i; j++) //比较范围
        {
            if(numbers[j] > numbers[j+1])
            {
                swapTmp = numbers[j];
                numbers[j] = numbers[j+1];
                numbers[j+1] = swapTmp;
            }
        }
    }
}

优化

优化1

在排序过程中,可能不需要n-1轮就能排好序,比如0 1 2 3 4 5 8 6,只需要一轮就能结束。
加入一个标记变量,如果当前轮没有进行任何交换,就结束排序。

void bubblesort(vector<int> &numbers)
{
    int len = numbers.size();
    if(len <= 0) return;
    int swapTmp;
    int flag; //加入flag进行标记
    for(int i = 1; i < len; i++) 
    {
        flag = 0;
        for(int j = 0; j < len-i; j++) 
        {
            if(numbers[j] > numbers[j+1])
            {
                swapTmp = numbers[j];
                numbers[j] = numbers[j+1];
                numbers[j+1] = swapTmp;
                flag = 1;
            }
        }
        if(flag == 0) //说明没有任何交换,提前结束
            return;
    }
}

优化2

对于数组array[1...n]array[1...n],第一轮比较的范围是1 ~ n(第n-1个元素和第n个元素比较),第二轮比较的范围是1 ~ n-1,第三轮比较的范围是1~n-2……其实第k轮可能没必要从1到n-k+1。
引入一个变量nextpos,记录上轮排序最后交换的位置,下一轮排序只需要从1到nextpos即可。

void bubblesort(vector<int> &numbers)
{
    int len = numbers.size();
    if(len <= 0) return;
    int swapTmp;
    int flag;  //加入flag进行标记
    int nextpos = len-1, posTmp = len-1; //引入变量记录上次最后交换的位置
    for(int i = 1; i < len; i++) //确定比较轮数
    {
        flag = 0;
        if(i != 1)
            nextpos = posTmp;
        for(int j = 0; j < nextpos; j++) //比较范围
        {
            if(numbers[j] > numbers[j+1])
            {
                swapTmp = numbers[j];
                numbers[j] = numbers[j+1];
                numbers[j+1] = swapTmp;
                posTmp = j;
                flag = 1;
            }
        }
        if(flag == 0) //说明没有任何交换,提前结束
            return;
        nextpos = posTmp;
    }
}

优化3

基本思想是一轮排序确定两个值,正向扫描找到最大值交换到最后,反向扫描找到最小值交换到最前面。举例,下面是一轮排序的结果:

一个排序的例子
原始数组序列:1 2 3 4 5 6 0
正向扫描结束:1 2 3 4 5 0 6
反向扫描step1:1 2 3 4 0 5 6
反向扫描step2:1 2 3 0 4 5 6
反向扫描step3:1 2 0 3 4 5 6
反向扫描step4:1 0 2 3 4 5 6
反向扫描结束:0 1 2 3 4 5 6
void bubblesort(vector<int> &numbers)
{
    int len = numbers.size();
    if(len <= 0) return;
    int swapTmp;
    int flag; //加入flag进行标记
    int nextpos = len-1, posTmp = len-1;
    for(int i = 1; i < len; i++) //确定比较轮数
    {
        flag = 0;
        if(i != 1)
            nextpos = posTmp;
        for(int j = 0; j < nextpos; j++) //正向扫描
        {
            if(numbers[j] > numbers[j+1])
            {
                swapTmp = numbers[j];
                numbers[j] = numbers[j+1];
                numbers[j+1] = swapTmp;
                posTmp = j;
                flag = 1;
            }
        }
        if(flag == 0)
            return;
        for(int j = posTmp; j > 0; j--) //反向扫描
        {
            if(numbers[j] > numbers[j-1])
            {
                swapTmp = numbers[j];
                numbers[j] = numbers[j+1];
                numbers[j+1] = swapTmp;
                flag = 1;
            }
        }
        if(flag == 0)
            return;
        nextpos = posTmp;
    }
}

参考

[1] 冒泡排序以及三种优化

:很大程度上参考了这位同学的思想,同时结合评论讨论对原来代码中的一些错误做了修改。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!