冒泡排序以及改进
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]
!--?xml>!--?xml>!--?xml>
以上是关于冒泡排序以及改进的主要内容,如果未能解决你的问题,请参考以下文章