• 【基础向】冒泡排序详解



    冒泡排序

    冒泡排序是一种简单的排序思想,即通过比较和交换,使较小(或较大)的数据逐渐向一端移动。


    算法原理

    以从小到大排序为例:
    1.遍历数据(除了最后一个)。
    2.使被遍历的数据与其后一个数据作比较,若比后一个大,则交换。
    3.重复 1,2 直到排序完成(优化)。


     算法可视化


    图片来自http://sc.chinaz.com/jiaobendemo.aspx?downloadid=8201830910379
    每次遍历总会使得某一个数据被安排在正确的位置上。
    那么我们只要遍历 “n - 1” 次即可完成排序。


    实现


     简单实现

    • 详细注释:
    //===============冒泡排序简单实现
    void BubbleSort(int* array,int count)
    //array为欲排序数组的指针,通过这个指针可以直接操作传入的数组
    //count为数组元素个数
    {
    	int i, j, temp;//temp在交换数据时作为第三方变量使用
    	for (j = 0; j < count - 1; j++)
    	{
    	//j < count - 1外层循环进行了 “count - 2” 次
    	//使得前 “count - 1” 个数据排在了正确的位置上,那么剩下一个数据当然也在正确的位置上
    		for (i = 0; i < count - 1 - j; i++)
    		{
    		//对于 i < count - 1 - j
    		//每次内层循环总会把一个数据放置得尽可能靠后,也就是说靠后的 j 个数据已经排好序,没必要继续遍历
    			if (array[i] > array[i+1] 
    			{//如果当前数据比后面的数据大
    							//交换数据
    				//这是三个语句,为了简洁就写在一起了
    				temp = array[i+1]; array[i+1] = array[i]; array[i] = temp;
    			}
    		}
    	}
    }
    
    • 去掉注释:
    //===============冒泡排序简单实现
    void BubbleSort(int* array,int count)
    {
    	int i, j, temp;
    	for (j = 0; j < count - 1; j++)
    	{
    		for (i = 0; i < count - 1 j; i++)
    		{
    			if (array[i] > array[i + 1])
    			{
    				temp = array[i + 1]; array[i + 1] = array[i]; array[i] = temp;
    			}
    		}
    	}
    }
    

     优化

      对于上述算法,我们知道:外层循环每循环一次,就会把一个数据排在正确的位置,那么如果有一个或多个数据本来就在正确的位置上呢?
      思考,如果向我们刚才研究的 BubbleSort() 函数中传入这样一组数据:

    2 1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

      我们发现,排序实际上在第一次外层循环结束时就已经完成了。
      而外层循环却保证自身会循环 “count - 1” 次,所以即使排序已经完成,算法依然会傻傻地运行下去:

    for (j = 0; j < count - 1; j++){}
    

      为了解决这个问题,我们只要判断某次外层循环是否发生过数据交换即可。
      如果本次没有发生交换,那么说明排序已经结束,可以直接输出结果。
      那么我们可以定义一个标志位来实现这样的算法:

      int flag;
    
    • 代码如下:
    //===============冒泡排序优化版本
    void BubbleSort_adv(int * a,int count)
    {
    	int i, j, temp, flag;//标志,0 为未发生交换,1 为发生过交换
    	for (j = 0; flag == 1; j++)
    	{//外层循环条件变为 “已发生交换” 
    		flag = 0;//内层循环开始时,我们认为还未发生交换
    		for (i = 0; i < count - 1 - j; i++)
    		{
    			if (a[i] > a[i + 1])
    			{
    				temp = a[i + 1]; a[i + 1] = a[i]; a[i] = temp;
    				flag = 1;//发生交换,flag置 1
    			}
    		}
    	}
    }
    
    • 去掉注释:
    //===============冒泡排序优化版本
    void BubbleSort_adv(int * a,int count)
    {
    	int i, j, temp, flag;
    	for (j = 0; flag == 1; j++)
    	{
    		flag = 0;
    		for (i = 0; i < count - 1 - j; i++)
    		{
    			if (a[i] > a[i + 1])
    			{
    				temp = a[i + 1]; a[i + 1] = a[i]; a[i] = temp;
    				flag = 1;
    			}
    		}
    	}
    }
    

      使用clock()函数,比较算法的运行效率:

    • 代码:
    //重复跑一千万次
    ......
    	start = clock();
    	for ( i = 1; i <= 10000000; i++)
    	{
    		BubbleSort(a.array,9);//为了方便对排序序列的初始化,这里是将数组包装在了结构体中。
    		a = b;//结构体可以直接赋值。
    		//关于结构体赋值,这里存在一些问题,不过不会影响本次的结果,我们下次再讨论。
    	}
    	printf("优化前:%lfs
    ",(double) (clock() - start)/CLK_TCK);
    
    
    	start = clock();
    	for ( i = 1; i <= 10000000; i++)
    	{
    		BubbleSort_adv(a.array,9);
    		a = b;
    	}
    	printf("优化后:%lfs
    ",(double) (clock() - start)/CLK_TCK);
    ......
    
    • 输出:
      在这里插入图片描述

    反向

      以上给出的算法均与算法可视化一致,为从小到大排列。
      若想改变排序方向,只需要做一个微小的改动

    //===============冒泡排序优化版本(从大到小)
    void BubbleSort_adv(int * a,int count)
    {
    	int i, j, temp, flag;
    	for (j = 0; flag == 1; j++)
    	{
    		flag = 0;
    		for (i = 0; i < count - 1 - j; i++)
    		{
    			if (a[i] < a[i + 1])//改动这里的符号
    			{
    				temp = a[i + 1]; a[i + 1] = a[i]; a[i] = temp;
    				flag = 1;
    			}
    		}
    	}
    }
    

  • 相关阅读:
    Linux环境部署项目引起Out of Memory Error: PermGen Space的解决方案
    手动上传图片到nginx下可访问,程序上传后访问图片报403
    Spring的断言工具类Assert的基本使用
    前后台分离部署时,Niginx上的部署
    GDAL VS2010 win7(64位)安装、使用说明(图文解析)
    转:libc6-dbg libc库调试的时候需要安装该库获得debug information 才能step into
    转:详解linux中的strings命令简介
    转:浮点数环境 cfenv(fenv.h)
    转:C语言中关于float、double、long double精度及数值范围理解
    转:linux中fork()函数详解
  • 原文地址:https://www.cnblogs.com/gaolihai/p/13149772.html
Copyright © 2020-2023  润新知