一段简单高效的冒泡排序代码

这段代码思路是一个朋友在群里分享的,我简单看了下,发现思路真的很好。
下面是我的简化版,先给贴出代码。

void bubble_sort(vector<int> &vec)
{
	int i = 0;
	while (i < vec.size() - 1)
	{
         if (vec[i] > vec[i + 1])
         {
             swap(vec[i], vec[i + 1]);
             if (i > 0)
                 --i;
         }
         else
             ++i;
	}
}

代码很简单。
对于冒泡排序,一个比较常见的作法就是,从第一个位置,把当前位置的元素和后一个位置的元素比较,如果比后面的元素大,就交换,这里假设升序排序,这样,第一趟下来,最大的元素就到最后了,就像泡泡往上冒一样,第二趟还是一样,但是就不用比较到最后一个元素了, 因为最后一个元素在第一趟的时候就已经是最大了。这样N-1 趟,就可以实现排序
比如 2 3 1 0
第一趟
2 3 1 0 --》 2 1 3 0 -》 2 1 0 3
第二趟
1 2 0 3 -> 1 0 2 3
第三趟
0 1 2 3
有序

但是这种做法,很多无用的操作,比如后面的元素基本有序了,
2 0 1 4 5 6 7 8 9
第一趟就有很多无用的操作。所以这种做法不管有序无序,比较次数都是 N*(N-1)/2

现在我们来看看上面的代码,
当发现要交换的时候,交换完,没有接着往后比较,而是 --i ,我们举个例子
比如
3 2 0
开始 i = 0, 2 和 3 交换之后 , i = 1
2 3 0 这个时候交换 2 0 3 i 还是为 0
这一步之后 --i 了, 为的时候,检查 0 之前的元素,是否有比 0 大的,有的话,就把 0 往 前移。
就相当与给 0 找个最合适靠前的位置。
这样又比较 0 和 2 就交换了, 0 2 3 ,此时 i 为 2 ,在比较最后一次,就接受了。
这种排序的好处就是, 当后面基本有序的时候,i 一次往前移动的位置就比较多,当后面有一个逆序数,又要往回退,但是这个逆序数找到合适位置后,后面遍历又很顺了。
总结:这种操作大部分有序时,比较次数较少
逆序数较多时,效率和普通的冒泡操作差不多。

下面是我优化的一段代码,针对,回退比较完之后快速回到之前冒泡最远的地方。

void bubble_sort2(vector<int> &vec)
{
	int i = 0;
	int mpos = 0;
	while (i < vec.size() - 1)
	{
		if (vec[i] > vec[i + 1])
		{
			mpos = max(i + 1, mpos);
			swap(vec[i], vec[i + 1]);
			if (i > 0)
				--i;
		}
		else
		{
			mpos = max(i + 1, mpos);
			i = mpos;
		}
	}
}
发布了37 篇原创文章 · 获赞 14 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/xiaod_szu/article/details/104326728
今日推荐