根据学堂在线TsinghuaX: 30240184X 数据结构(2015秋)这门课的内容,对bubblesort做了一些总结。

1. bubblesort(起泡排序),原理来自这样一个观察规律:若序列有序,则任意一对相邻元素顺序。其逆否命题为:若存在相邻元素逆序,则序列无序。

2. 利用这一原理,bubblesort按照逐步消除逆序对的思路来实现整体有序。

3. 实现:对序列进行若干趟扫描,每遇到相邻逆序对,交换之,直至不再存在逆序对。

4. 算法的正确性分析:

(1)不变性(问题已求解的部分扩大):每一轮扫描交换,都会使当前未就位的元素中最大的那个就位(每次冒出一个最大的泡)

(2)单调性(问题未求解的规模递减):每一轮扫描交换,都会使有序序列长度增1,无序序列长度减1,问题规模也因而减1

5. 实现为如下代码:

 void swap(int& a,int& b){
int t=a;
a=b;
b=t;
} void bubblesort(int a[],int n){
bool sorted = false; //先假设尚未整体有序
while(!sorted){ //进入循环体
sorted=true; //假设现在前n项已有序
for(int i=; i<n-; i++){ //进行一趟扫描交换(从0一直到n-1,判断每组相邻元素)
if(a[i] > a[i+]){
swap(a[i],a[i+]);
sorted = false; //这一趟有交换则还需要再一趟扫描
}
}
n--;//一趟扫描交换必然会冒出一个泡~所以后面已就位的元素可以不在下次的扫描范围内了
}
}

6. 复杂度分析:

(1)基本语句为第12行的if(a[i]>a[i+1])

(2)初始时,必然会进入第9行的while循环,然后进入第11行的for循环,基本语句被执行n-1次。

(3)最好情况是输入完全有序,while循环只进入一次,for循环执行n-1轮,因此基本语句相应地执行n-1次,T(n) = n-1=Ω(n)

(4)最坏情况是输入完全逆序,while循环被执行n次;在第 i 轮while循环中,for循环执行 i 轮,基本语句也相应地执行 i 次。因此基本语句累加执行n(n-1)/2次,T(n)=n(n-1)/2=O(n2)

Vector一章,对bubblesort有两次常数优化。

函数原型是这样的:

  void bubble(Rank lo, Rank hi);

  void bubbleSort(Rank lo, Rank hi);

Rank即向量元素的秩,在此被定义为int型。lo和hi为待排序区间的左、右界桩。

外部通过调用 v.bubbleSort(lo, hi) 来给向量v的区间[lo,hi)排序,而bubbleSort调用bubble(lo,hi)实现对每个无序子区间的收缩。

最朴素的bubblesort大概是这样,最好最坏平均情况都为O(n^2)

 //最朴素版
void bubble(Rank lo, Rank hi) {
while (++lo < hi){//从左至右扫描,修正相邻逆序对
if (_elem[lo - ]>_elem[lo]){
swap(_elem[lo - ], _elem[lo]);
}
}
}
void bubbleSort(Rank lo, Rank hi){
while (lo < hi) bubble(lo, hi--);//右界桩每次向左挪一位
}

第一次改进后是这样,这种改进很常见,能使最好情况变为为O(n)。

 bool bubble(Rank lo, Rank hi) {
bool sorted=true;//增设sorted变量,记录此次扫描是否发生交换(未发生交换则sorted=true)
while (++lo < hi){
if (_elem[lo - ]>_elem[lo]){
sorted = false;
swap(_elem[lo - ], _elem[lo]);
}
}
return sorted;//返回是否已有序
}
void bubbleSort(Rank lo, Rank hi){
while (!bubble(lo, hi--));//一趟扫描没有发生交换(检测结果为sorted)则排序完成
}

第二次改进后是这样,可以跳跃式地收缩区间,降低了平均情况常数因子

 Rank bubble(Rank lo, Rank hi) {
Rank last=lo;//设置last变量,记录最后一次交换的位置
while (++lo < hi){;} swap(_elem[lo - ], _elem[lo]);
if (_elem[lo - ]>_elem[lo]){
last = lo
}
return last;//last及以后的元素都已就位,不必再进行扫描
}
void bubbleSort(Rank lo, Rank hi){
while (lo<(hi=bubble(lo, hi--)));//将右界桩挪到最后一次last位置
}

第二次改进可用下图来描述

【DSA MOOC】起泡排序的原理及常数优化的更多相关文章

  1. 回调函数及数组中sort()方法实现排序的原理

    1.回调函数:把一个方法A当一个参数值传递到另外一个函数B中,在B执行的过程当中我们随时根据需求让A方法执行:   什么是回调 :它是异步编程基本的方法,需要异步处理的时候一般采用后续传递的方式,将后 ...

  2. Java基础知识强化之集合框架笔记47:Set集合之TreeSet保证元素唯一性和比较器排序的原理及代码实现(比较器排序:Comparator)

    1. 比较器排序(定制排序) 前面我们说到的TreeSet的自然排序是根据集合元素的大小,TreeSet将它们以升序排列. 但是如果需要实现定制排序,比如实现降序排序,则要通过比较器排序(定制排序)实 ...

  3. Java基础知识强化之集合框架笔记44:Set集合之TreeSet保证元素唯一性和自然排序的原理和图解

    1. TreeSet保证元素唯一性和自然排序的原理和图解 2. TreeSet唯一性以及有序性底层剖析: 通过观察TreeSet的add()方法,我们知道最终要看TreeMap的put()方法. 跟踪 ...

  4. 起泡排序(Bubble sort)

    局部有序和整体有序 在由一组整数组成的序列A[0, n-1]中,满足 $ A[i - 1] \leq A[i] $ 的相邻元素称为顺序的:否则是逆序的. 扫描交换 由有序序列的特征,我们可以通过不断改 ...

  5. 内部排序->交换排序->起泡排序

    文字描述 首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序(L.r[1].key>L.r[2].key),则将两个记录交换位置,然后比较第二个记录和第三个记录的关键字.依次类推,直 ...

  6. 连续线性空间排序 起泡排序(bubble sort),归并排序(merge sort)

    连续线性空间排序 起泡排序(bubble sort),归并排序(merge sort) 1,起泡排序(bubble sort),大致有三种算法 基本版,全扫描. 提前终止版,如果发现前区里没有发生交换 ...

  7. C语言 选择排序算法原理和实现 从数组中 找出最小的元素然后交换位置

    #include <stdio.h> int main(void) { /* 选择排序算法 原理:从数组中 找出最小的元素然后交换位置: */ int a[10] = {9,5,10,7, ...

  8. Python实现的选择排序算法原理与用法实例分析

    Python实现的选择排序算法原理与用法实例分析 这篇文章主要介绍了Python实现的选择排序算法,简单描述了选择排序的原理,并结合实例形式分析了Python实现与应用选择排序的具体操作技巧,需要的朋 ...

  9. php面试专题---Mysql索引原理及SQL优化

    php面试专题---Mysql索引原理及SQL优化 一.总结 一句话总结: 注意:只写精品 1.为表设置索引要付出代价 是什么? 存储空间:一是增加了数据库的存储空间 修改插入变动索引时间:二是在插入 ...

随机推荐

  1. SQL Server 索引的自动维护 <第十三篇>

    在有大量事务的数据库中,表和索引随着时间的推移而碎片化.因此,为了增进性能,应该定期检查表和索引的碎片,并对具有大量碎片的进行整理. 1.确定当前数据库中所有需要分析碎片的表. 2.确定所有表和索引的 ...

  2. cf479A Expression

    A. Expression time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  3. bzoj1643 [Usaco2007 Oct]Bessie's Secret Pasture 贝茜的秘密草坪

    Description 农夫约翰已经从他的牧场中取得了数不清块数的正方形草皮,草皮的边长总是整数(有时农夫约翰割草皮的刀法不合适,甚至切出了边长为0的正方形草皮),他已经把草皮放在了一个奶牛贝茜已经知 ...

  4. Eclipse设置分级折叠显示项目工程路径

    1.抛出问题现象 如下图,这种方式看项目中的代码简直痛苦的要死: 项目迭代越多,工程目录越庞大,可读性就越差. 2.设置分级折叠显示项目 第一步:在Package Explorer视图中找到它的缩放菜 ...

  5. UESTC_Sea Base Exploration CDOJ 409

    When the scientists explore the sea base, they use a kind of auto mobile robot, which has the missio ...

  6. 关于memcpy和memmove的一点说明

    今天看到书上降到memcpy和memmove的区别才突然发现原来两者之间有如此区别,以前只知道这两个函数是 实现同样的功能,没有接触到其不同. memcpy和memmove在MSDN的定义如下: 从两 ...

  7. Cocos2d-x 架构一个游戏的一般思路

    采用下面的步骤来实现游戏逻辑: 通过应用程序代理类来初始化第一个CCScene(即AppDelegate里面的第一个CCScene), CCScene里面实例化一个或者多个CCLayer,并把它们当作 ...

  8. GDB+GDBServer调试Linux应用程序

    参考:http://blog.csdn.net/shanghaiqianlun/article/details/7820401 一.gdb+gdbserver总体介绍 远程调试环境由宿主机GDB和目标 ...

  9. 分享几种Linux软件的安装方法

    Linux软件安装由于不同的Linux分支,安装方法也互不相同,介绍几种常见的安装方法. 1. 源码安装,     对于本身具有开源血统的Linux系统来说,几乎所有的开源软件都支持在Linux平台运 ...

  10. C#.Net前台线程与后台线程的区别

    本文来自:http://www.cnblogs.com/zfanlong1314/archive/2012/02/26/2390455.html .Net的公用语言运行时(Common Languag ...