冒泡排序及优化

目录

一、思路

二、普通写法

三、模板写法

四、优化一

五、优化二

六、优化三


冒泡排序:(无序区,有序区)。从无序区通过交换找出最大元素放到有序区前端。

 

一、思路

1、比较相邻元素,如果第一个比第二个大,交换他们。

2、对每一对相邻元素做同样操作,从开始第一对倒最后一对。这步做完后,最后的元素是最大的。

3、针对所有元素重复以上步骤,除了最后一个。

4、持续每次对越来越少的元素重复以上步骤,直到没有一对数字需要比较。

 

二、普通写法

void BubbleSort(vector<int> &v)
{
    int len = v.size();
    for (int i = 0; i < len - 1; i++)   // 确定排序趟数
    {
        for (int j = 0; j < len - 1 - i; j++)   // 确定比较次数
        {
            if (v[j] > v[j + 1])
            {
                swap(v[j], v[j + 1]);
            }
        }
    }
}

 

 

三、模板写法

template<typename T>
void BubbleSort(T arr[], int len)
{
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < len - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                swap(arr[j], arr[j + 1])
            }            
        }        
    }    
}

 

 

四、优化一

    假设我们现在排序arr[]={1, 2, 3, 4, 5, 6, 7, 8, 10, 9}这组数据,按照上面排序方式,第一趟排序后将10和9交换已经有序,接下来的8趟排序就是多余的,什么也没有做。所以我们可以在交换的地方做一个标记,如果那一趟排序没有交换元素,说明这组数据已经有序,不用再继续下去。

void BubbleSort(vector<int> &v)
{
    int len = v.size();
    for (int i = 0; i < len - 1; i++)   // 排序趟数
    {
        int flag = 0;
        for (int j = 0; j < len - 1 - i; j++)
        {
            if (v[j] > v[j + 1])
            {
                swap(v[j], v[j + 1]);
                flag = 1;
            }
        }
        if (flag == 0)  // 如果没有交换过元素,则已经有序
        {
            return;
        }
    }
}

 

 

五、优化二

    优化一仅适用于连片有序而且整体无序的数据(如:1, 2, 3, 4,7, 6, 5)。但是对于前面大部分是无序而后边小半部分有序的数据(1, 2, 5, 7, 4, 3, 6, 8, 9, 10)排序效率也不客观。对于这种类型数据,我们可以继续优化。我们可以记下最后一次交换的位置,后边没有交换,必然是有序的,然后下一次排序从第一个比较到上次记录的位置结束即可。

void BubbleSort(vector<int> &v)
{
    int len = v.size();
    int lastChangePos = 0;
    int flag = 0;
    int k = len - 1;
    for (int i = 0; i < len - 1; i++)
    {
        lastChangePos = 0;
        flag = 0;
        for (j = 0; j < k; j++)
        {
            if (v[j] > v[j + 1])
            {
                swap(v[j], v[j + 1]);
                flag = 1;
                lastChangePos = 1;
            }
        }
        if (flag == 0)
        {
            return;
        }
        k = lastChangePos;
    }
}

 

 

六、优化三

    优化二的效率有很大提升,还有一种优化方法可以继续提高效率。大致思想就是一次排序可以确定两个值,正向扫描找到最大值交换到最后,反向扫描找到最小值交换到最前面。例如:排序数据1, 2, 3, 4, 5, 6, 0.

void BubbleSort(vector<int> &v)
{
    int len = v.size();
    int flag = 0;
    int lastChangePos = 0;
    int k = len - 1;
    int n = 0;  // 同时找到最大值和最小值需要两个下标遍历

    for (int i = 0; i < len - 1; i++)   // 确定排序趟数
    {
        lastChangePos = 0;
        flag = 0;
        // 正向查找最大值
        for (int j = n; j < k; j++) // 确定比较次数
        {
            if (v[j] > v[j + 1])
            {
                swap(v[j], v[j + 1]);
                flag = 1;
                lastChangePos = j;
            }
        }

        if (flag == 0) return;
        k = lastChangePos;  // 下一次比较到记录位置即可

        // 反向查找最小值
        for (j = k; j > n; j--)
        {
            swap(v[j], v[j - 1]);
            flag = 1;
        }
        n++;
        if (flag == 0) return;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幻欢子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值