简单冒泡排序及优化

最简单排序实现
冒泡排序的思想其实很简单,它是一种简单的选择排序,在细节上有很多种优化的方法。
它的基本思想是:两两比较相邻记录的关键字,如果反序则进行交换。
首先先来看一段简单的冒泡排序:

//冒泡排序初级版
void Bubble(int* arr, int sz)
{
    int i, j;
    //从下标为0的第一个元素与后面的每一个元素进行比较
    for (i = 0; i < sz - 1; ++i)    
    {
        for (j = i+1; j < sz - i; ++j)
        {
            if (arr[i]>arr[j])
            {
                swap(arr[i], arr[j]);
            }
        }
     }
}

这个初级版的冒泡排序不算是真正意义上的冒泡排序,它的思路是让每一个数字都和它后面的数字进行比较
这里写图片描述
我们可以看出,当1和0、-1等进行比较了之后,需要进行交换,再与后面的数字进行比较均不需要进行交换,显然这种效率比较低
下面我们来看一个真正的冒泡排序

void Bubble1(int* arr, int sz)
{
    for (int i = 0; i < sz - 1; ++i)
    {
        for (int j = 0; j < sz - i; ++j)
        {
            if (arr[j]>arr[j + 1])
            {
                swap(arr[j], arr[j + 1]);

            }
        }
    }
}

这里写图片描述
我们可以看出,经过一趟冒泡排序之后(假设升序),最大的数一定被排在了最后面,并且不再当前位置的数字也越来越接近正确位置。但是我们试想一下,如果待排序的数字是{0,-1,1,2,3,4,5,6,7,8,9},除了0和-1需要交换之外,其它的数字均不需要交换,尽管不需要交换,但是用上述方法还是需要进行比较,这时我们可以增加标志位来减少不必要的比较。

//添加标志位的冒泡排序 
void Bubble2(int* arr, int sz)
{ 
    int  mark = 1;//用mark来做标记
    for (int i = 0; i < sz - 1&&mark; ++i)//
    {
        mark = 0;
        for (int j = 0; j < sz - i; ++j)
        {
            if (arr[j]>arr[j + 1])
            {
                swap(arr[j], arr[j + 1]);
                mark = 1;
            }
        }
    }
}

代码唯一的改动就是在for循环中增加了对mark的判断经过这样的改进,冒泡排序的性能有了一定的提升,避免了在有序情况下一些无意义的判断。
冒泡排序复杂度的分析
1.最好的情况,即数组有序,可以推断出就是n-1次的比较,时间复杂度为O(n)
2.当最坏的情况,即数组逆序,第一个数需要排n-1次,第二个数需要排n-2次,第3个数需要排n-3次……这样依次类推,最后一个数只需要排一次,加起来共需要排n(n-1)/2次,所以时间复杂度为O(O^2)

猜你喜欢

转载自blog.csdn.net/wyn126/article/details/78904822