【冒泡排序】

一、简介
冒泡排序时交换排序的一种;
它的总体思想是:从数列的第一个数开始,将数列的数字两两比较,使得大数在前,直到倒数第二个数和倒数第一个数作比较,然后使得大数在前;那么这一趟比较下来,就会把数列中最大的数冒泡到数列的最后面;下一趟冒泡只需要冒泡到倒数第二个,依次类推,直到某趟冒泡的元素剩下一个;冒泡完毕,排序完成
(1)普通写法
假设一个数组中有sz个元素,每趟冒泡会把1个元素放在正确的位置上,那么一共需要将sz-1个元素冒泡到正确的位置上,剩下的1个元素自然在正确的位置上;所以需要冒泡sz-1趟;排序就会完成;

每趟冒泡,会两两比较sz-i;

void BubbleSort(int* arr,int sz)//sz为数组的元数的个数 
{
    assert(arr);
    for (int i=1;i<sz;i++)//比较的趟数是元素个数-1
    {
        for(int j=0;j<sz-i;j++)//从0开始比较到最后倒数(sz-i)位置元素;
        {
           if (arr[j]>arr[j+1])
           {
               std::swap(arr[j],arr[j+1]);
           } 
        }
    }
}

(2)冒泡的优化—–
【添加标志信息设置标志位,避免对已经有序的剩余数列采取冒泡排序,减少比较次数和比较趟次,提高效率】

如果我们在冒泡时,遇到
1 2 3 4 5 8 9
那么经过一次冒泡之后变为
1 2 3 4 5 9 8
如果按照上面的写法还会继续冒泡5趟,
没趟两两比较,一共比较5+4+3+2+1=15次,但是这15次比较完全是多余的,因为经过第一趟排序以后,数组已经有序,这15次比较,完全没有起到冒泡的作用,纯属浪费时间,那么我们采用一种机制,设法每当一 趟冒泡完成以后,检测一下是不是现在的数组已经有序,如果有序,那么就直接退出冒泡的循环;排序结束;

所以加了一个标志位初始为0,当每一趟冒泡的时候,如果数组还没有完全有序,则一定会进行数据交换,这时我们将标志位设置为1,标志着数组还不是完全有序,可以继续进行冒泡,当一趟冒泡完成,出来之后,检查一下mark标志位,就会知道数组是否完全有序,是否还有必要进行下一趟冒泡;

但是这种添加标志位,有一个特点,就是当一趟冒泡完成以后,进行了最后一次交换之后,此时如果数组已经完成有序,但是由于进行过交换mark被置为1;
当接下来进行检测时,会以为数组还不是完全有序,还会在进行下一趟冒泡,在进行完下一趟冒泡之后,由于这次没有进行数据交换,所以mark=0;接下来才检测到数据有序,才有终止剩下的排序;
这就像时,冒泡已经有序,但是程序的反应会慢一拍,还会在进行一趟多余的冒泡;但是终究来说还是减少了后面很多趟不必要的冒泡;提高效率;

//冒泡排序优化1---设置标志位,避免对已经有序的剩余数列采取冒泡排序,减少比较次数和比较趟次,提高效率
void BubbleSort1(int* arr,int sz)//sz为数组的元数的个数 
{
    assert(arr);
    for (int i=1;i<sz;i++)//比较的趟数是元素个数-1
    {
        int mark=0;
        for(int j=0;j<sz-i;j++)//从0开始比较到最后倒数(sz-i)位置元素;
        {
            if (arr[j]>arr[j+1])
            {
                std::swap(arr[j],arr[j+1]);
                mark=1;
            } 
        }
        if (mark==0)
        {
            break;
        }
    }
}

(2)优化2
假设遇到这种情况(局部无序)
1 2 3 6 5 4 7 8 9
第一趟冒泡完成以后是、
1 2 3 5 4 6 7 8 9
如果按照上面的方法,第二趟排序会给倒数第二个位置放上正确的数组;但是这个正确的8已经在倒数第二个位置;第三趟也一样,正确的数字7也在对应的位置上;

所以第二趟和第三趟冒泡是多余的,冒泡完全没有意义;还进行了那么多次两两比较,影响程序效率;那么怎么能让第一趟冒泡之后的所有趟数冒泡都有意义;
可以定义一个位置变量,记录每一趟排序的时候最后一次进行数据交换后的数组位置;

等到下一趟冒泡的时候,直接冒泡到该置就结束;因为后面的数据已经排好序;
这样的话在加上设置的标志信息;就会使冒泡排序的冒泡趟数减少,而且冒泡的每一趟都会进行数据交换,都是有意义的一趟冒泡;提高程序效率;

void BubbleSort2(int* arr,int sz)//sz为数组个数
{
    assert(arr);
    int k=sz-1;//控制每趟冒泡的终止位置;
    int pos=0;//记录每趟冒泡时最后一次数据交换的元素下标;
    for (int i=1;i<sz;i++)//冒泡趟数为元素个数-1次;
    {
        int mark=0;
        for (int j=0;j<k;j++)
        {
            if (arr[j]>arr[j+1])
            {
                std::swap(arr[j],arr[j+1]);
                mark =1;
                pos=j;  
            }
        }
        if (mark==0)
        {
            break;
        }
        k=pos;
    }
}

END!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值