title: 冒泡排序
date: 2020-12-07 14:37:27

tags:

冒泡排序最坏效率:O(N2)
冒泡排序平均效率:
冒泡排序最好效率:

冒泡排序步骤如下。

1. 指向数组中两个相邻的元素(最开始是数组的头两个元素),比较它们的大小。
2. 如果它们的顺序错了(即左边的值大于右边),就互换位置。如果顺序已经是正确的,那这一步就什么都不用做。  
3. 将两个指针右移一格。重复第(1)步和第(2)步,直至指针到达数组末尾。
4. 重复第(1)至(3)步,直至从头到尾都无须再做交换,这时数组就排好序了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class BubbleSort extends Sort {
sort(originalArray) {
// Flag that holds info about whether the swap has occur or not.
let swapped = false;
// Clone original array to prevent its modification.
const array = [...originalArray];

for (let i = 1; i < array.length; i += 1) {
swapped = false;

// Call visiting callback.
this.callbacks.visitingCallback(array[i]);

for (let j = 0; j < array.length - i; j += 1) {
// Call visiting callback.
this.callbacks.visitingCallback(array[j]);

// Swap elements if they are in wrong order.
if (this.comparator.lessThan(array[j + 1], array[j])) {
[array[j], array[j + 1]] = [array[j + 1], array[j]];

// Register the swap.
swapped = true;
}
}

// If there were no swaps then array is already sorted and there is
// no need to proceed.
if (!swapped) {
return array;
}
}

return array;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Sort {
constructor(originalCallbacks) {
this.callbacks = Sort.initSortingCallbacks(originalCallbacks);
this.comparator = new Comparator(this.callbacks.compareCallback);
}

/**
* @param {SorterCallbacks} originalCallbacks
* @returns {SorterCallbacks}
*/
static initSortingCallbacks(originalCallbacks) {
const callbacks = originalCallbacks || {};
const stubCallback = () => {};

callbacks.compareCallback = callbacks.compareCallback || undefined;
callbacks.visitingCallback = callbacks.visitingCallback || stubCallback;

return callbacks;
}

sort() {
throw new Error('sort method must be implemented');
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class Comparator {
/**
* @param {function(a: *, b: *)} [compareFunction] - It may be custom compare function that, let's
* say may compare custom objects together.
*/
constructor(compareFunction) {
this.compare = compareFunction || Comparator.defaultCompareFunction;
}

/**
* Default comparison function. It just assumes that "a" and "b" are strings or numbers.
* @param {(string|number)} a
* @param {(string|number)} b
* @returns {number}
*/
static defaultCompareFunction(a, b) {
if (a === b) {
return 0;
}

return a < b ? -1 : 1;
}

/**
* Checks if two variables are equal.
* @param {*} a
* @param {*} b
* @return {boolean}
*/
equal(a, b) {
return this.compare(a, b) === 0;
}

/**
* Checks if variable "a" is less than "b".
* @param {*} a
* @param {*} b
* @return {boolean}
*/
lessThan(a, b) {
return this.compare(a, b) < 0;
}

/**
* Checks if variable "a" is greater than "b".
* @param {*} a
* @param {*} b
* @return {boolean}
*/
greaterThan(a, b) {
return this.compare(a, b) > 0;
}

/**
* Checks if variable "a" is less than or equal to "b".
* @param {*} a
* @param {*} b
* @return {boolean}
*/
lessThanOrEqual(a, b) {
return this.lessThan(a, b) || this.equal(a, b);
}

/**
* Checks if variable "a" is greater than or equal to "b".
* @param {*} a
* @param {*} b
* @return {boolean}
*/
greaterThanOrEqual(a, b) {
return this.greaterThan(a, b) || this.equal(a, b);
}

/**
* Reverses the comparison order.
*/
reverse() {
const compareOriginal = this.compare;
this.compare = (a, b) => compareOriginal(b, a);
}
}