热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

冒泡算法的改进具体实现

这篇文章主要介绍了冒泡算法的改进具体实现,有需要的朋友可以参考一下

冒泡排序算法的思想:

首先将第一个记录的关键字和第二个关键字进行比较,若为逆序则将两个记录进行交换。
然后比较第二个记录和第三个记录的关键字,直至第n-1个记录和第n个记录进行比较为止,一趟过后最大的元素会沉入最底部。
然后进行第二趟排序,对前 n-1 个记录进行同样1、2的操作,结果就是关键字次大的记录被安排到n-1位置上。
依次进行第 i 趟排序,对前 n-i 个记录进行同样的1、2的操作,直到一趟没有进行过任何比较的操作,排序结束。
先看一下基础冒泡算法:

代码如下:

int BubbleSort(MergeType* L)
{
 int i, j;
 for (i = 0; i <= L->len-1; i++)
 {  
  for (j = 0; j len-1-i; j++)
  {
   if (L->elem[j+1] elem[j])
   {
    SWAP(L->elem[j+1], L->elem[j] ); 
   }
  } 
 }

 return 0;
}

这里的MergeType类型如下:

代码如下:

typedef struct _SQLIST{
    int* elem;
    int len;   //实际长度
    int size;  //分配空间
}SqList, *pSqList;

typedef _SQLIST MergeType;

核心思想是每次选出最大的数沉入底部,直至没有数据可比较。

首先计算一下它的时间复杂度,这里以最坏的情况来计算的话:

(n-1)+(n-2)+……+ 1 + 0 = n*(n-1)/ 2  = O(n^2)

最好的情况就是已经排序好,不需要进行比较
首先看到其不足之一:就是频繁交换元素。如何避免,可以存放在一个合适的位置,精简算法一:

代码如下:

int BubbleSortEx(MergeType* L)
{
 int i = 0, j = 0;
 int max, temp;
 for (i = 0; i <= L->len-1; i++)
 {  
  temp = L->elem[0];
  max = 0;
  for (j = 1; j len-i; j++)
  {   
   if (L->elem[j] > temp)
   {
    temp = L->elem[j];
    max = j;
   }
  }
  //printf("%d:%d \n", max, temp);
  swap(L->elem[L->len-1-i], L->elem[max] );   
 }

 return 0;
}

看到这里每次仍然需要频繁的进行赋值操作,当然只是微不足道的,但是赋值也会增加cpu执行的时间,所以精简算法二:

代码如下:

int BubbleSortEx(MergeType* L)
{
 int i, j , max;
 for (int i = 0; i <= L->len-1; i++)
 {  
  max = 0;
  for (j = 1; j len-i; j++)
  {   
   if (L->elem[j] > L->elem[max])
   {
    max = j;
   }
  }
  //printf("%d:%d \n", max, L->elem[max]);
  swap(L->elem[L->len-1-i], L->elem[max] );   
 }

 return 0;
}

这里的两个swap是不一样的,当然也可以使用一样的,看如下具体的实现:

代码如下:

#define SWAP(a, b) \
{                 \
 int temp = (a); \
 (a) = (b);        \
 (b) = temp;     \
}

代码如下:

inline void swap(int& a, int& b)
{
 int temp = a;
 a = b;
 b = temp;
}

第一个是采用宏替换,当然主要是增加预处理的时间,主要是用宏会出现意想不到的错误
第二个是函数,这里使用了引用,可以减少指针使用的形参变量副本的创建,但是这里使用了inline,所以还是替换

测试程序:

代码如下:

int PrintList(MergeType *L);
int ScanfList(MergeType *L, const int nScanfType = -1);

int SortTest()
{
 printf("--- %s ---\n", __FUNCTION__);
 MergeType pList;
 MergeType pT; 

 pList.elem = (int*)malloc(sizeof(int)*10);
 pList.len  = 10;
 pList.size  = 10;

 ScanfList(&pList); /*输入数据*/

 BubbleSortEx(&pList);/*冒泡排序*/

 PrintList(&pList);/*输出数据*/

 free(pList.elem);
 pList.elem = NULL;

 return 0;
}

数据输入:

代码如下:

int ScanfList(MergeType *L, const int nScanfType)
{
 if (!L->elem)
 {
  return -1;
 }

 printf("Old List\t: ");

 for (int i = 0; i <= L->len; i++ )
 {
  if( i == L->len )
  {
   printf("\n");
   break;
  }
  switch (nScanfType)
  {
  case 0:
   {
    break;
   }
  default:
   L->elem[i] = 11 * i - i * i;
   break;
  }  
  printf("%d ", L->elem[i]);
 }
 return 0;
}

数据输出:

代码如下:

int PrintList(MergeType *L)

 if (!L->elem)
 {
  return -1;
 }

 printf("Sort List\t: ");

 for (int i = 0; i <= L->len; i++ )
 {
  if (i == L->len)
  {
   printf("\n");

   break;
  }
  printf("%d ", L->elem[i]);
 }
 return 0;
}


推荐阅读
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文介绍了adg架构设置在企业数据治理中的应用。随着信息技术的发展,企业IT系统的快速发展使得数据成为企业业务增长的新动力,但同时也带来了数据冗余、数据难发现、效率低下、资源消耗等问题。本文讨论了企业面临的几类尖锐问题,并提出了解决方案,包括确保库表结构与系统测试版本一致、避免数据冗余、快速定位问题等。此外,本文还探讨了adg架构在大版本升级、上云服务和微服务治理方面的应用。通过本文的介绍,读者可以了解到adg架构设置的重要性及其在企业数据治理中的应用。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • MyBatis错题分析解析及注意事项
    本文对MyBatis的错题进行了分析和解析,同时介绍了使用MyBatis时需要注意的一些事项,如resultMap的使用、SqlSession和SqlSessionFactory的获取方式、动态SQL中的else元素和when元素的使用、resource属性和url属性的配置方式、typeAliases的使用方法等。同时还指出了在属性名与查询字段名不一致时需要使用resultMap进行结果映射,而不能使用resultType。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
author-avatar
Y死一般的痛过
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有