冒泡排序及其改进

冒泡排序:

基本思想:

        有需要排序的数组array[1......N]竖直排列,将每个元素array[i]看做是一个气泡,则重气泡下沉,轻气泡上升。每次比较相邻的两个气泡array[i]和array[i+1]。如果array[i]大于array[i+1],则交换两个气泡,否则继续比较array[i+1]和array[2]。重复上述步骤,直到所有的气泡都是升序排列的。

        假如有以下数组:

int a[6]={1,3,2,5,-1,6};

           第一趟:       

                 第一次冒泡:1 3 2 5 -1 6

                 第二次冒泡:1 2 3 5 -1 6

             第三次冒泡:1 2 3 5 -1 6

             第四次冒泡:1 2 3 -1 5 6

             第五次冒泡:1 2 3 -1 5 6

        这样子,就找到最重的气泡6,然后按照相同的方法找到第二重、第三重...气泡。从上面可以看出,实现这个排序需要两重循环,第一层控制趟数,第二层控制要排序的数据范围,若有n个数据,则:

         第0趟:比较第0到第n-1个,下标从0到n-2;

         第1趟:比较第0到第n-2个,下标从0到n-3;

         ...

         第 i 趟:比较第0到第n-i-1个,下标从0到n-i-2;

            ...

         第n-2趟:比较第0到第1个,下标从0到0。

         源码如下:

 

        

//冒泡排序
void bubblesort(int a [], int len){
	for (int i = 0; i < len; i++){
		for (int j = 1; j < len - i; j++){
			if (a[j]<a[j -1]){
				swap(a[j], a[j - 1]);
			}
		}
	}
}

 

//交换两个整数
void swap(int& a, int& b){
	int tmp = a;
	a = b;
	b = tmp;
}


        这种算法下,冒泡排序的最好、最坏情况,时间复杂度都是O(n^2),所以平均时间复杂度也是O(n^2)。

冒泡排序改进1:

          其实我们可以看出上述算法有一点问题,如果在某一趟排序中没有发生数据交换,那么说明待排序的无序区中的所有元素均是有序的,那么冒泡排序就可以在这一趟扫描之后就结束。比如,如果一组数据本身就是有序的,那么第一趟比较时未发生数据交换,那么冒泡排序就可以结束了。

       基于这种思想,我们设置一个标志位,在没有发生交换时,标志位设置为true,说明数据已经排好序,就不需要进行余下的循环;如果标志位为false,那么就进行余下的循环。

       源码如下:

 

      

//改进的冒泡排序1:不做无用功
void bubblesortmodify_1(int a [], int len){
	bool isSorted = false;
	for (int i = 0; i < len&&!isSorted; i++){		//在没有排序的情况下才会循环
		isSorted = true;										//设定排序标志
		for (int j = 1; j < len - i; j++){
			if (a[j]<a[j-1]){
				isSorted = false;							//如果没有排序,则重新设置排序标志
				swap(a[j], a[j - 1]);
			}
		}
	}
}

     

         从上面可以看出,如果数据(n个)的初始状态就是有序的,那么只需要进行1趟排序,n-1次比较,这是最好的情况。如果数据的初始状态是逆序的,那么就需要进行n-1趟排序,每趟要进行n-i次比较,总共要n(n-1)/2次比较。所以最好的情况时间复杂度是O(n),最坏的情况时间复杂度是O(n^2),平均下来还是O(n^2)。


冒泡排序改进2:

              我们可以发现,在每趟的排序中,最后一次交换发生的位置last之前的相邻数据已经是有序的,所以下一趟排序开始时,0到last已经是有序的,而只有last到n-1是无序的,所以需要尽可能缩小无序的范围。

         源码如下:

 

        

//改进的冒泡排序2:记录犯罪现场
void bubblesortmodify_2(int a [], int len){
	int k = len - 1;
	int i, j;
	while (k != 0){
		for (i = j = 0; j < k; j++){
			if (a[j]>a[j + 1]){
				swap(a[j], a[j + 1]);				i = j;
			}
		}
		k = i;
	}
}

          
          同样,如果数据(n个)的初始状态就是有序的,那么只需要进行1趟排序,n-1次比较,这是最好的情况。如果数据的初始状态是逆序的,那么就需要进行n-1趟排序,每趟要进行n-i次比较,总共要n(n-1)/2次比较。所以最好的情况时间复杂度是O(n),最坏的情况时间复杂度是O(n^2),平均下来还是O(n^2)。

 

 

           

     

           

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值