冒泡排序及其优化

声明:本文是对 xuetangx 清华大学 丁俊晖 老师 数据结构 课程的个人总结。

冒泡排序的原理很简单:

每一次扫描,遇到相邻逆序队就交换,这样,每一趟扫描下来,当前区间最大值都被交换到区间最后位置,而问题规模相应的 -1。

算法复杂度是 O(n^2) 的,毫无疑问。算法正确性也毫无疑问。

考虑如何优化:

对于我们尚未确定最终位置的左边的无序区间,有可能含有一部分甚至是所有的元素都是有序的。

如下图:

我们如何提前判断结束这个算法呢?

实际上,我们这里判断有序的依据是:相邻元素都是顺序的。

由此得出一个改进策略:

每一趟扫描交换,都记录下是否存在逆序元素。

存在的情况是,当且仅当做过交换。

如果没有做过扫描交换,我们即可判断整个区间有序。

实现如下:

时间复杂度前后对比如图:

继续考虑改进:

考虑这样一个例子:

初始区间很大的后缀部分已然有序,而无序部分都集中在区间很小的一个前缀区间内。

即便大后缀已经有序,有序每次前缀中都存在交换,所以依然我们每次会依次扫描到整个区间末尾。

而需要扫描 前缀长度 r 趟,即直到前缀有序。

整个算法复杂度是 O(n*r) 的。

我们发现,上例中多余出来的时间消耗就是对已就位后缀的扫描。而显然对这些元素的扫描都是不必的。

改进应运而生:即每趟扫描记录最后一次进行交换的位置。

那么记录位置的后缀就都是已经就位了的。

实现:

不同点就在于 last 记录位置。

这种一次性将有序区间扩大很多而不是每次只将有序区间扩大一个位置的情况,

可能就出现在某趟扫描交换后,而不仅仅是第一次扫描后。

即我们每次都会聪明的找到最大的有序后缀。

时间对比:

这个多个梯形的面积和,至少是不大于上面那一个梯形的面积的。

当然,以上改进,在最坏的情况下,依然是于事无补的,依然是 O(n^2) 的时间。

综合评价:

if 条件中是 严格 > 而不是 >=,所以保证了稳定性。

然而,有太多跟冒泡排序复杂度在数量级上存在差别的排序算法,但这种一步一步优化的过程,或者说思维,值得探究。

时间: 2024-12-28 10:52:50

冒泡排序及其优化的相关文章

冒泡排序的优化

//冒泡排序的优化          int array10[] = {9, 7, 3, 8, 4};     BOOL flag1 = YES;     for (int i = 0; i < 5 - 1 && flag1; i++) {         flag = NO;//假设本趟循环没有做交换         for (int j = 0; j < 5 - 1 - i; j++) {             if (array10[j] > array10[j

冒泡排序以及冒泡排序的优化

说明:很简答的优化,却有很多人容易在面试时候栽在这个简单的问题上. “冒泡排序”在面试中是很容易被问到的排序算法,也是最简单的排序算法,当被问到,“冒泡排序怎么优化?”,很多人就懵了,冒泡还能优化?答案是可以的. 1. 这是一般的冒泡排序. 1 /// <summary> 2 /// 通俗冒泡 3 /// </summary> 4 public static void BubbleSortCommon(int[] arr) 5 { 6 int temp; 7 int len = a

排序之冒泡排序(优化)-PHP

1 <?php 2 //设置请求头 3 header("content-type:text/html;charset=utf-8"); 4 5 //对冒泡排序进行优化:如果数组在传进来或者遍历一次两次后 6 //就已经排好了 就不再进行排序操作 7 8 //例子: 9 $arr = array(1,2,3,6,4,12,1,85,1,3); //待排序数组 10 // $arr = range(1, 10000); 11 12 function my_bubble_sort(&a

java冒泡排序及优化

java冒泡排序及优化 import java.util.Arrays; public class TestBubbleSort3 { public static void main(String[] args) { int[] a = {23,45,2,86,56,34,234,54,342}; getBubbleSortResult(a); } public static void getBubbleSortResult(int[] a) { for(int j =0;j<a.length-

好程序员Java学习路线分享冒泡排序及优化

? 好程序员Java学习路线分享冒泡排序及优化,冒泡排序是一定典型的交换排序,如排序规则是升序,有如下数列: ? A[0] A[1] A[2] A[3] ...... A[n] ? 将A[0]和A[1]比较,如果A[0]>A[1] ,则交换两个元素的位置,否则不变, 再继续比较A[1]和A[2],直到A[n-1]和A[n].即比较相邻的两个元素,如果前一个大,就交换(否则不交换),再继续比较后面的元素,每一轮比较之后,最大的元素会移动到最后(完成一轮冒泡):再开始第二轮冒泡,本次会选出第二大的元

排序算法入门之冒泡排序及其优化(java实现)

冒泡排序思想(从小到大): 比较相邻两个元素,如果第一个元素比第二个元素大,就交换他们的位置.第一趟,从第一个元素开始,第一个元素和第二个元素比较,如果第一个元素比第二个元素大,则交换位置:接下来比较第二.第三个元素,大的放后面,以此类推,直到最后两个.第一趟比较结束后,最大的元素放到了最后一个位置.接下来进行第二趟排序,从第一个元素到倒数第二个元素(因为最后一个已经是最大的了)执行上面步骤.依次执行下去. 此时的最优最差平均时间复杂度为O(n^2). 优化:加一个标志位,当交换元素时为true

冒泡排序的优化与误区

冒泡排序(Bubble Sort)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端. 冒泡排序算法的运作如下: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有的元素重复以上的步

冒泡排序和优化

冒泡思想:两两比较相邻记录,内循环将最小的数通过交换浮上来. 优化思想:设置flag,对已经有序的序列就不继续判断了 冒泡排序的实现: package Bubble_Sort; //冒泡算法和改进算法,正序,从小到大(从1开始) public class BubbleSort { public int[] a=new int[11]; public int size; public int count; public boolean flag=true; public BubbleSort(in

冒泡排序及优化

冒泡排序: 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位.当i次遍历的时候将找到 第i+1大(小)的数放到倒数第i+1的位置.代码如下: void bubbleSort(int* arr, int size) { if(arr == NULL) return; for(int i=0; i<size; i++) { for(int j=0; j<size-i-1; j++) { if(arr[j]>arr[j+