第十二章 Caché 算法与数据结构 冒泡排序

文章目录

  • 第十二章 Caché 算法与数据结构 冒泡排序
  • 思想
  • 实例
    • 第一轮
    • 第二轮
    • 第三轮
    • 第四轮
    • 第五轮
    • 第六轮
    • 第七轮
  • 代码实现
    • 第一版
    • 第二版
      • 优化
    • 第三版
      • 优化

第十二章 Caché 算法与数据结构 冒泡排序

它是一种基础的交换排序。

思想

把相邻的元素两两比较,当一个元素大于右侧相邻元素时,交换他们的位置:当一个元素小于或等于右侧相邻元素时,位置不变。

实例

数列如下排序:

{5,8,6,3,9,2,1,7}

第一轮

  • 第一次 5 和 8 比较 5 比 8 小 不变。
{5,8,6,3,9,2,1,7}
  • 第二次 8 和 6 比较 8 比 6 大 交换位置。
{5,6,8,3,9,2,1,7}
  • 第三次 8 和 3 比较 8 比 3 大 交换位置。
{5,6,3,8,9,2,1,7}
  • 第四次 8 和 9 比较 8 比 9 小 不变。
{5,6,3,8,9,2,1,7}
  • 第五次 9 和 2 比较 9 比 2 大 交换位置。
{5,6,3,8,2,9,1,7}
  • 第六次 9 和 1 比较 9 比 1 大 交换位置。
{5,6,3,8,2,1,9,7}
  • 第七次 9 和 7 比较 9 比 7 大 交换位置。
{5,6,3,8,2,1,7,9}

第二轮

  • 第一次 5 和 6 比较 5 比 6 小 不变。
{5,6,3,8,2,1,7,9}
  • 第二次 6 和 3 比较 6 比 3 大 交换位置。
{5,3,6,8,2,1,7,9}
  • 第三次 6 和 8 比较 6 比 8 小 不变。
{5,3,6,8,2,1,7,9}
  • 第四次 8 和 2 比较 8 比 2 大 交换位置。
{5,3,6,2,8,1,7,9}
  • 第五次 8 和 1 比较 8 比 1 大 交换位置。
{5,3,6,2,1,8,7,9}
  • 第六次 8 和 7 比较 8 比 7 大 交换位置。
{5,3,6,2,1,7,8,9}
  • 第七次 8 和 9 比较 8 比 9小 不变。
{5,3,6,2,1,7,8,9}

第三轮

{3,5,2,1,6,7,8,9}

第四轮

{3,2,1,5,6,7,8,9}

第五轮

{2,1,3,5,6,7,8,9}

第六轮

{1,2,3,5,6,7,8,9}

第七轮

{1,2,3,5,6,7,8,9}

冒泡排序是一种稳定排序,值相等的元素并不会打乱原本的顺序。由于改排序排序算法每一轮都要遍历所有元素,总共遍历(元素数量-1)轮,所以平均时间复杂度是O(n^2)

代码实现

第一版

/// d ##class(PHA.YX.Arithmetic).BubbleSortFirst()
ClassMethod BubbleSortFirst()
{
	 s array = $lb(5,8,6,3,9,2,1,7)
	 
	 f i = 1 : 1 : $ll(array) - 1 d
	 .f j = 1 : 1 : $ll(array) - i d
	 ..s tmp = 0
	 ..i ($li(array, j) > $li(array, j + 1)) d
	 ...s tmp = $li(array, j)
	 ...s $li(array, j) = $li(array, j + 1)
	 ...s $li(array, j + 1) = tmp
	 zw array
}
DHC-APP> d ##class(PHA.YX.Arithmetic).BubbleSortFirst()
array=$lb(1,2,3,5,6,7,8,9)

第二版

优化

当数列 {5,8,6,3,9,2,1,7} 排序到第六轮,第七轮时

  • 第六轮
{1,2,3,5,6,7,8,9}
  • 第七轮
{1,2,3,5,6,7,8,9}

经过六轮排序后,整个数列已然是有序的了。可是算法还是进行到了第七轮。

在这种情况下,如果能判断出数列已经有序,那么剩下的几轮排序就不比执行。

我们增加quitFlag来标记退出循环 sortFlag标记来标记是否有交换的数据。

代码如下:

/// d ##class(PHA.YX.Arithmetic).BubbleSortSecond()
ClassMethod BubbleSortSecond()
{
	 s array = $lb(5,8,6,3,9,2,1,7)
	 /* 循环退出标志 */
	 s quitFlag = 1
	
	 f i = 1 : 1 : $ll(array) -1  q:quitFlag=0  d
	 .s sortFlag = 1    /* 有序标志,每一轮的初始值都是true */
	 .f j = 1 : 1 : $ll(array) - i  d
	 ..s tmp = 0
	 ..i ($li(array, j) > $li(array, j + 1)) d
	 ...s tmp = $li(array, j)
	 ...s $li(array, j) = $li(array, j + 1)
	 ...s $li(array, j + 1) = tmp
	 ...s sortFlag = 0  /* 因为有元素进行交换,所以不是有序的,标记变为false */
	 .i sortFlag = 1  s quitFlag = 0
	 .zw array
}

我们把数组 改成s array = $lb(2,1,3,4,5,6,7,8)并增加 一些w i j sortFlag 看他们的值

/// d ##class(PHA.YX.Arithmetic).BubbleSortSecond()
ClassMethod BubbleSortSecond()
{

	 s array = $lb(2,1,3,4,5,6,7,8)
	 s quitFlag = 1
	
	 f i = 1 : 1 : $ll(array) -1  q:quitFlag=0  d
	 .w "i:"_i,!
	 .s sortFlag = 1
	 .f j = 1 : 1 : $ll(array) - i  d
	 ..w "j:"_j,!
	 ..s tmp = 0
	 ..i ($li(array, j) > $li(array, j + 1)) d
	 ...s tmp = $li(array, j)
	 ...s $li(array, j) = $li(array, j + 1)
	 ...s $li(array, j + 1) = tmp
	 ...s sortFlag = 0
	 .i sortFlag = 1  s quitFlag = 0
	 .w "sortFlag:"_sortFlag,!
	 .zw array
}

运行结果发现:2轮就停止排序了,因为数组已经成为有序数列。

DHC-APP>d ##class(PHA.YX.Arithmetic).BubbleSortSecond()
i:1
j:1
j:2
j:3
j:4
j:5
j:6
j:7
sortFlag:0
array=$lb(1,2,3,4,5,6,7,8)
i:2
j:1
j:2
j:3
j:4
j:5
j:6
sortFlag:1
array=$lb(1,2,3,4,5,6,7,8)

第三版

优化

为了说明这个问题,我们以一个新的数列为例:s array = $lb(3,4,2,1,5,6,7,8)

这个数列的特点是前半部分(3,4,2,1)无序,后半部分的元素(5,6,7,8)按升序排列。

第一轮:

  • 第一次 3 和 4 比较 3 比 4 小 不变。
(3,4,2,1,5,6,7,8)
  • 第二次 4 和 2 比较 4 比 2 大 交换位置。
(3,2,4,1,5,6,7,8)
  • 第三次 4 和 1 比较 4 比 1 大 交换位置。
(3,2,1,4,5,6,7,8)

后面一次比较发现依然有序,但是还是进行了N次比较。后面的多次元素比较是没有意义的。

我们发现最后一次交换之前的是无序边界,之后是有序边界。所以我们增加lastExchangeIndex来记录最后的交换位置

/// d ##class(PHA.YX.Arithmetic).BubbleSortThird()
ClassMethod BubbleSortThird()
{
	 s array = $lb(3,4,2,1,5,6,7,8)
	 s quitFlag = 1
	 /* 记录最后一次交换的位置 */
	 s lastExchangeIndex = 0
	 /* 无序数列的边界,每次比较只需要比到这里为止 */
	 s sortBorder = $ll(array) -1  
	
	 f i = 1 : 1 : $ll(array) -1  q:quitFlag=0  d
	 .w "i:"_i,!
	 .s sortFlag = 1
	 .f j = 1 : 1 : sortBorder  d
	 ..w "j:"_j,!
	 ..s tmp = 0
	 ..i ($li(array, j) > $li(array, j + 1)) d
	 ...s tmp = $li(array, j)
	 ...s $li(array, j) = $li(array, j + 1)
	 ...s $li(array, j + 1) = tmp
	 ...s sortFlag = 0
	 ...s lastExchangeIndex = j  /* 更新为最后一次交换元素的位置 */
	 ...w "lastExchangeIndex  "_lastExchangeIndex,!
	 .s sortBorder = lastExchangeIndex
	 .i sortFlag = 1  s quitFlag = 0
	 .zw array
}

运行我们看一下结果

DHC-APP>d ##class(PHA.YX.Arithmetic).BubbleSortThird()
i:1
j:1
j:2
lastExchangeIndex  2
j:3
lastExchangeIndex  3
j:4
j:5
j:6
j:7
array=$lb(3,2,1,4,5,6,7,8)
i:2
j:1
lastExchangeIndex  1
j:2
lastExchangeIndex  2
j:3
array=$lb(2,1,3,4,5,6,7,8)
i:3
j:1
lastExchangeIndex  1
j:2
array=$lb(1,2,3,4,5,6,7,8)
i:4
j:1
array=$lb(1,2,3,4,5,6,7,8)

在第三版代码中sortBorder就是无序数列的边界,每一轮排序中,处于sortBorder之后的元素就不需要在进行比较了。肯定是有序的。

你可能感兴趣的:(Caché,算法与数据结构,Caché,算法,数据结构,冒泡排序,排序)