冒泡排序以及改进

Posted linjunfu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冒泡排序以及改进相关的知识,希望对你有一定的参考价值。

关于排序术语:
内排序:排序数据放置在内存中,排序操作在内存中进行
外排序:排序数据放置在磁盘中,通过磁盘和内存进行的数据传输进行排序操作
 
时间复杂度:算法执行所消耗的时间
空间复杂度:运行完一个程序所需内存的大小
 
冒泡排序 
 1 function bubbleSort(arr) {
 2     // 记录传入数组的长度
 3     let len = arr.length
 4     let temp = 0
 5     // 外循环:
 6     for (let i = 0; i < len; i++) {
 7       // 内循环:
 8       for (let j = 0; j < len - 1 - i; j++) {
 9         // 相邻元素元素两两对比,如果前面的数大于后面的数,则进行位置互换
10         // 这里假定一个例子: 此刻 [..., 5, 3, ...]
11         // arr[j] = 5
12         // arr[j + 1] = 3
13         if (arr[j] > arr[j + 1]) {
14           // 位置互换
15 
16           // 临时变量,将arr[j + 1] 即3存储起来,temp = 3
17           temp = arr[j + 1]
18 
19           // 对arr[j + 1]进行赋值,变为前面的数值arr[j],即 arr[j + 1] = 5
20           arr[j + 1] = arr[j]
21 
22           // 最后将前面的arr[j]设置为临时变量存起来的数值3,arr[j] = 3
23           arr[j] = temp
24         }
25         // 此刻,数组变成: [..., 3, 5, ...]
26       }
27       // 关于上面 j < len - 1 - i
28       // 例子:
29       // [3, 2, 5, 9, 4], length = 5
30       // 外循环第一遍
31       // 开始[3, 2, 5, 9, 4], 第1次, j = 0, arr[j] = 3, arr[j+1] = 2, 3 > 2, true ,  变动 => [2, 3, 5, 9, 4]
32       // 开始[2, 3, 5, 9, 4], 第2次, j = 1, arr[j] = 3, arr[j+1] = 5, 3 > 5, false , 不变 => [2, 3, 5, 9, 4]
33       // 开始[2, 3, 5, 9, 4], 第3次, j = 2, arr[j] = 5, arr[j+1] = 9, 5 > 9, false , 不变 => [2, 3, 5, 9, 4]
34       // 开始[2, 3, 5, 9, 4], 第3次, j = 3, arr[j] = 9, arr[j+1] = 4, 9 > 4, true ,  变动 => [2, 3, 5, 4, 9]
35 
36       // 开始[2, 3, 5, 4, 9],第5次,j = 4, arr[j] = 9, arr[j + 1] = undefined,9 > ?
37       // 到达第5次,只有arr[j],但是没有arr[j + 1],所以这一步没有意义,因此这是len - 1 的理由
38 
39       // 可以看到,外循环第一遍之后,会把数组中的最大数即9,推到数组最后一位
40       // 因为外循环第二遍的时候,数组[2, 3, 5, 9, 4]已经没有必要把最后一位9加入排序操作
41       // i = 0 外循环第一遍还没有开始排序,所以可排序长度: - 0
42       // i = 1 外循环第二遍开始排序了一位,所以可排序长度: - 1
43       // 这便是len - 1 - i的理由
44     }
45     // 最后返回处理完的数组
46     return arr
47 }
48 let arr = [3, 2, 5, 9, 4]
49 console.log(bubbleSort(arr)) // [2, 3, 4, 5, 9]

 

改进冒泡一:通过记录交换位置排序

 1 function bubbleSortByPos(arr) {
 2     // 初始时的长度需要 - 1,
 3     // 比如数组有5个数据 for循环对比时 arr[4]即是最后一个数据
 4     // 没有对比的需要,所以需要长度 - 1, 使得最后一次是a[3]与a[4]对比
 5     let len = arr.length - 1
 6     let temp = 0
 7     // while循环
 8     while(len > 0) {
 9         // 每次循环,交换位置初始值都是从0开始
10         let pos = 0
11         // 内循环
12         for (let j = 0; j < len; j++) {
13             // 相邻元素两两对比,如果前面的数大于后面的数,则位置进行互换
14             // 这里假定一个例子:此刻[..., 5, 3, ...]
15             // arr[j] = 5
16             // aarr[j+1] = 3
17             if (arr[j] > arr[j+1]) {
18                 // 当满足前面的数大于后面的数这个条件时,记录下当前的交换位置
19                 pos = j
20 
21                 // 位置交互
22                 // 声明一个temp临时变量,将后面的数arr[j+1]即3存起来:temp=3
23                 temp = arr[j+1]
24 
25                 // 对后面的数arr[j+1]进行赋值,变为前面的数值arr[j]: arr[j+1] = 5
26                 arr[j+1] = arr[j]
27 
28                 // 最后将前面的数值arr[j]设置为临时变量存储起来的数值5: arr[j] = 3
29                 arr[j] = temp
30             }
31             // 此刻,数组变成:[..., 3, 5, ...]
32         }
33         // 本次for循环之后,可以得到本次for循环最终的交换位置pos,
34         // 该交换位置(不包含该位置)后面的都是排序好的,
35         // 所以该pos的值即是下一个for循环开始时,
36         // 该数组的截断点,截断点之前的数据都要再一次参与排序
37         len = pos
38 
39         // 例子:
40         // [5, 4, 6, 2, 7, 8, 9], length = 7
41         // while循环
42         // for循环
43         // 开始[5, 4, 6, 2, 7, 8, 9], 第1次, j = 0, arr[j] = 5, arr[j+1] = 4, 5 > 4, true , 变动 => [4, 5, 6, 2, 7, 8, 9]  pos = j = 0
44         // 开始[4, 5, 6, 2, 7, 8, 9], 第2次, j = 1, arr[j] = 5, arr[j+1] = 6, 5 > 6, false, 不变 => [4, 5, 6, 2, 7, 8, 9]  pos = j = 0
45         // 开始[4, 5, 6, 2, 7, 8, 9], 第3次, j = 2, arr[j] = 6, arr[j+1] = 2, 6 > 2, true , 变动 => [4, 5, 2, 6, 7, 8, 9]  pos = j = 2
46         // 开始[4, 5, 2, 6, 7, 8, 9], 第4次, j = 3, arr[j] = 6, arr[j+1] = 7, 6 > 7, false, 不变 => [4, 5, 2, 6, 7, 8, 9]  pos = j = 0
47         // 开始[4, 5, 2, 6, 7, 8, 9], 第5次, j = 4, arr[j] = 7, arr[j+1] = 8, 7 > 8, false, 不变 => [4, 5, 2, 6, 7, 8, 9]  pos = j = 0
48         // 开始[4, 5, 2, 6, 7, 8, 9], 第6次, j = 5, arr[j] = 8, arr[j+1] = 9, 8 > 9, false, 不变 => [4, 5, 2, 6, 7, 8, 9]  pos = j = 0
49 
50         // 可以看到本次for循环最终交换位置为数组下标序号2,下标2后面的数据都是排序好的,所以下标2(包含)前面的数据要进入下一次排序操作
51     }
52     // 最后返回处理完的数组
53     return arr
54 }
55 let arr = [5, 4, 6, 2, 7, 8, 9]
56 console.log(bubbleSortByPos(arr)) // [2, 4, 5, 6, 7, 8, 9]

 

改进冒泡二:正反方向串行排序

 1 function bubbleSortByLowAndHigh(arr) {
 2     // 初始最小序号值
 3     let low = 0
 4     // 初始时的长度需要 - 1,
 5     // 比如数组有5个数据 for循环对比时 arr[4]即是最后一个数据
 6     // 没有对比的需要,所以需要长度 - 1, 使得最后一次是a[3]与a[4]对比
 7     let high = arr.length - 1
 8 
 9     let temp, j
10     // while循环, 当最小序号值小于最大序号值,才继续循环,否则说明已经排序完毕
11     while(low < high) {
12         // 从上一次排序好的最小序号位置开始,从上一次排序好的最大的序号值结束,找到最大值
13         for (j = low; j < high; j++) {
14             // 相邻元素两两对比,如果前面的数大于后面的数,则位置进行互换
15             // 这里假定一个例子:此刻[..., 5, 3, ...]
16             // arr[j] = 5
17             // aarr[j+1] = 3
18             if (arr[j] > arr[j+1]) {
19                 // 位置交互
20                 // 将后面的数arr[j+1]即3存起来:temp=3
21                 temp = arr[j+1]
22                 // 对后面的数arr[j+1]进行赋值,变为前面的数值arr[j]: arr[j+1] = 5
23                 arr[j+1] = arr[j]
24                 // 最后将前面的数值arr[j]设置为临时变量存储起来的数值3: arr[j] = 3
25                 arr[j] = temp
26             }
27         }
28         // 本次for循环找到最大值,并被置换到相应的排序好后的位置,arr数组可排序数组最大序号值减1
29         high--
30 
31         // 从上一次排序好的最大序号位置开始,从上一次排序好的最小的序号值结束,找到最小值
32         for (j = high; j > low; j--) {
33             // 相邻元素两两对比,如果前面的数大于后面的数,则位置进行互换
34             // 这里假定一个例子:此刻[..., 5, 3, ...]
35             // arr[j-1] = 5
36             // aarr[j] = 3
37             if (arr[j-1] > arr[j]) {
38                 // 位置交互
39                 // 将后面的数arr[j]即3存起来:temp=3
40                 temp = arr[j]
41                 // 对后面的数arr[j]进行赋值,变为前面的数值arr[j-1]: arr[j] = 5
42                 arr[j] = arr[j-1]
43                 // 最后将前面的数值arr[j-1]设置为临时变量存储起来的数值3: arr[j] = 3
44                 arr[j-1] = temp
45             }
46         }
47         // 本次for循环找到最小值,并被置换到相应的排序好后的位置,arr数组可排序数组最小序号值加1
48         low++
49 
50         // 例子:
51         // [5, 4, 6, 2, 7, 9, 8], length = 7  high = length - 1 = 6
52         // while循环
53         // 第一个for循环
54         // 开始[5, 4, 6, 2, 7, 9, 8], 第1次, j = 0, arr[j] = 5, arr[j+1] = 4, 5 > 4, true , 变动 => [4, 5, 6, 2, 7, 9, 8]
55         // 开始[4, 5, 6, 2, 7, 9, 8], 第2次, j = 1, arr[j] = 5, arr[j+1] = 6, 5 > 6, false, 不变 => [4, 5, 6, 2, 7, 9, 8]
56         // 开始[4, 5, 6, 2, 7, 9, 8], 第3次, j = 2, arr[j] = 6, arr[j+1] = 2, 6 > 2, true , 变动 => [4, 5, 2, 6, 7, 9, 8]
57         // 开始[4, 5, 2, 6, 7, 9, 8], 第4次, j = 3, arr[j] = 6, arr[j+1] = 7, 6 > 7, false, 不变 => [4, 5, 2, 6, 7, 9, 8]
58         // 开始[4, 5, 2, 6, 7, 9, 8], 第5次, j = 4, arr[j] = 7, arr[j+1] = 9, 7 > 9, false, 不变 => [4, 5, 2, 6, 7, 9, 8]
59         // 开始[4, 5, 2, 6, 7, 9, 8], 第6次, j = 5, arr[j] = 9, arr[j+1] = 8, 9 > 8, true,  变动 => [4, 5, 2, 6, 7, 8, 9]
60         // 可以看到本次for循环得到最大值为9,最大序号为high = 6
61         // 此时序号为6的值为最大值,不必进入下一次排序操作,high需要减1,可排序数组数据减少一位, high--
62 
63         // [4, 5, 2, 6, 7, 8], low = 0 high = 5        
64         // 第二个for循环
65         // 开始[4, 5, 2, 6, 7, 8], 第1次, j = 5, arr[j-1] = 7, arr[j] = 8, 7 > 8, false, 不变 => [4, 5, 2, 6, 7, 8]
66         // 开始[4, 5, 2, 6, 7, 8], 第2次, j = 4, arr[j-1] = 6, arr[j] = 7, 6 > 7, false, 不变 => [4, 5, 2, 6, 7, 8]
67         // 开始[4, 5, 2, 6, 7, 8], 第3次, j = 3, arr[j-1] = 2, arr[j] = 6, 2 > 6, false, 不变 => [4, 5, 2, 6, 7, 8]
68         // 开始[4, 5, 2, 6, 7, 8], 第4次, j = 2, arr[j-1] = 5, arr[j] = 2, 5 > 2, true , 变动 => [4, 2, 5, 6, 7, 8]
69         // 开始[4, 2, 5, 6, 7, 8], 第5次, j = 1, arr[j-1] = 4, arr[j] = 2, 4 > 2, true , 变动 => [2, 4, 5, 6, 7, 8]
70 
71         // 可以看到本次for循环得到最小值为2,最小序号为low = 0
72         // 此时序号为0的值为最小值,不必进入下一次排序操作,low需要加1,可排序数组数据减少一位, low++
73 
74         // 进入下一次while循环
75     }
76     // 最后返回处理完的数组
77     return arr
78 }
79 let arr = [3,55,38,5,87,15,34,14,27,2,46,3,25,50,28]
80 console.log(bubbleSortByLowAndHigh(arr)) // [2, 3, 3, 5, 14, 15, 25, 27, 28, 34, 38, 46, 50, 55, 87]

 

以上是关于冒泡排序以及改进的主要内容,如果未能解决你的问题,请参考以下文章

改进冒泡排序的运行时间分析

数据结构之--冒泡排序算法及改进

排序算法之冒泡排序

冒泡排序的改进:鸡尾酒排序

冒泡排序改进版(java)

快速排序的介绍以及代码实现