初等排序之冒泡排序

   在看到第二章的排序算法,一直在纠结要不要写成博客,因为本来想着排序算法比较简单,而且真正的比赛时不会自己排序,都有封装的类库函数供自己使用,所以一开始不打算写成博客,可是我这个人有点追求完整,说的高大上一点就是追求完美,同时也想着学习也不仅仅是为了比赛和应付考试,所以还是打算写下这篇博客,之后的几篇博客也会围绕着排序算法来写。好了不多废话,开始~

   冒泡排序又叫起泡排序,是交换排序中最简单的排序方法,基本思想就是两两相邻的记录比较,在反序(指排列顺序与最终所需要的排序顺序相反)时则交换,正序则不变化。其余的也不多说,以一个例子进行形象的介绍:

初始数列:                                                   50 13 55 97 27 38 49 65

第一次比较:50>13 交换   ---------        50 13 55 97 27 38 49 65

第二次比较:50<=55 不交换 ---------    13 50 55 97 27 38 49 65

第三次比较:55<=97 不交换 ---------    13 50 55 97 27 38 49 65

第四次比较:97>27 交换 ---------          13 50 55 97 27 38 49 65

第五次比较:97>38 交换 ---------          13 50 55 27 97 38 49 65

第六次比较:97>49 交换 ---------          13 50 55 27 38 97 49 65

第七次比较:97>65 交换 ---------          13 50 55 27 38 49 97 65

第一趟比较结束,最终结果为                13 50 55 27 38 49 65 97


这里我们就可以看出冒泡排序的过程了,97在数列中最大,就像一个大气泡一样一路“过关斩将”,最终排到队列末尾,在第一趟结束后,也就使得使得有序区有了一个元素。

以下是每趟结果后数列的排序情况,在中括号中为无序区,中括号外为有序区:

初始数列:                                                        [50 13 55 97 27 38 49 65]

第一趟排序后:                                            [13 50 55 27 38 49 65] 97

第二趟排序后:                                             [13 50 27 38 49 55] 65 97

第三趟排序后:                                             [13 27 38 49 50] 55 65 97

第四趟排序后:                                             [13 27 38 49] 50 55 65 97

第五趟排序后:                                             [13 27 38] 49 50 55 65 97

第六趟排序后:                                             [13 27] 38 49 50 55 65 97

第七趟排序后:                                             [13] 27 38 49 50 55 65 97


在第七趟排序后,无序区只剩一个元素且在数列开头,这样整个数列就已经排序完成

接下来附上我的源码:

#include<stdio.h>
void Bubble_Sort1(int A[],int N)
{
	for(int i=1;i<N;i++)
	{
	  for(int j=0;j<N-i;j++)
	    if(A[j]>A[j+1])
	    {
	    	int temp=A[j+1];
	    	A[j+1]=A[j];
	    	A[j]=temp;
	    }
	}
}
int main()
{
	int N;
	int A[100];
	
	scanf("%d",&N);
	for(int i=0;i<N;i++)
	scanf("%d",&A[i]);
	
	Bubble_Sort1(A,N);
	
	for(int i=0;i<N;i++)
	printf("%d  ",A[i]);
	return 0;
} 


思考:

   对于冒泡排序算法,有没有优化的地方呢,在上面第三趟之后,其实数列就已经是排序好的数列了,之后的每趟其实都没有在进行交换。

基于这点我们可以想到用一个变量记录exchange每趟最后一次交换,这个变量之后的数据已经排序好了,也就是有序区。

比如上面的第一趟排序后结果为[13 50 55 27 38 49 65] 97,在进行第二趟排序时,55分别与27,38,49进行交换,在遇到65时不进行交换,就变

成了第二趟的结果:[13 50 27 38 49 55] 65 97,如果我们这时用exchange记录最后一次交换,即55与49的交换,具体的记录方法是exchange为交换后的

49的下标,这时在包括下标为exchange+1的元素都是已经排序好的,也就是有序区55 65 97,因为之后没有交换,说明A[i]<=A[i+1](i=exchange+1,exchange+2.....n-1),

那么下趟的排序范围就从下标为0到exchange.

   下面为改进后的冒泡排序的数列每趟的结果:

初始数列:                                                        [50 13 55 97 27 38 49 65]    exchange=n-1=7,指向65

第一趟排序后:                                            [13 50 55 27 38 49 65] 97     exchange=6,指向65

第二趟排序后:                                             [13 50 27 38 49] 55 65 97    exchange=4,指向65

第三趟排序后:                                             [13 27 38 49 ]50 55 65 97      exchange=3,指向49

第四趟排序后:                                              13 27 38 49 50 55 65 97        exchange=0,结束

    同时我们可以看到,使用了这种方法后,在第二趟排序后,有序区比使用第一种方法多了一个元素,并且这种优势在第四趟体现的更加明显,直接排序完成。

以下是我的源码:

#include<stdio.h>
void Bubble_Sort2(int A[],int N)
{
	int exchange=N-1;
	while(exchange)
	{
		int end=exchange;            //end为无序区最后一个元素的下标 
		exchange=0;
		for(int i=0;i<end;i++)
		{
			if(A[i]>A[i+1])
			{
				int temp=A[i+1];
	    	    A[i+1]=A[i];
	    	    A[i]=temp;          //exchange记录下最后一次交换中的前一个数的下标,之后都不交换,
	    	    exchange=i;         //exchange不会发生变化,说明包括exchange+1之后的已经排序好了 。 
			}
		}
	}
}
int main()
{
	int N;
	int A[100];
	
	scanf("%d",&N);
	for(int i=0;i<N;i++)
	scanf("%d",&A[i]);
	
	Bubble_Sort2(A,N);
	
	for(int i=0;i<N;i++)
	printf("%d  ",A[i]);
	return 0;
} 


PS:个人感觉写博客的时候把内容从头理了一边,挺好的,切勿急躁~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值