就JavaScript而言,Array对象有方法sort()可以对数组成员进行排序,默认是字典顺序。自定义排序规则需要给sort()方法提供一个函数。此函数本身有2个参数,表示进行比较的两个元素。如果返回值大于0,表示第1个元素在后面,其他情况下第1个元素在前面。
下面时其他排序算法的代码,扩充Array的排序功能。
时间复杂度是O(n2)
代码如下:
Array.prototype.bubbleSort = function() {
var len = this.length
var temp = 0
while (len) {
for (var i = 1; i < len; i++) {
if (this[i-1] > this[i]) { //升序排列
temp = this[i-1]
this[i-1] = this[i]
this[i] = temp
}
}
len--
}
}
时间复杂度是O(n2)
代码如下:
Array.prototype.insertionSort = function() {
var i, j, temp
var len = this.length
for (i = 1; i < len; i++) {
temp = this[i] //无序区的第一个元素
for (j = i - 1; j >= 0 && this[j] > temp; j--)
this[j+1] = this[j]
this[j+1] = temp
}
}
可以视为将数组分成两个区域:(有序区,无序区)
过程:把无序区的第一个元素插入到有序区的合适的位置。
操作:比较得少,换得多。
时间复杂度是O(n log n);需要O(n)额外空间
代码如下:
Array.prototype.mergeSort = function() {
//合并
var merge = function(left, right) {
var final = []
while (left.length && right.length)
final.push(left[0] <= right[0] ? left.shift() : right.shift())
return final.concat(left.concat(right))
}
//递归分块
var len = this.length
if (len < 2) return this
var mid = len >> 1
return merge(this.slice(0,mid).mergeSort(),this.slice(mid).mergeSort())
}
时间复杂度是O(n2)
代码如下:
Array.prototype.selectionSort = function() {
var i, j, min, temp
var len = this.length
for (i = 0; i < len - 1; i++) {
min = i
for (j = i + 1; j < len; j++)
if (this[min] > this[j]) min = j
temp = this[min]
this[min] = this[i]
this[i] = temp
}
}
将数组分为两个部分:(有序区,无序区)
过程:在无序区里找一个最小的元素跟在有序区的后面
操作:比较得多,换得少。
时间复杂度是O(n log2 n) (log n)的平方 略差于比较算法的 O(n log n)。
也称递减增量排序算法,是插入排序的一种更高效的改进版本,通过将待比较的元素分成几个区域来提升插入排序的性能。(插入排序对于接近排好的数据进行操作时效率很高,可达到线性)
→ 关键在于步长的选择。
代码如下:
Array.prototype.shellSort = function() {
var gap, i, j, temp
var len = this.length
for (gap = len >> 1; gap > 0; gap >>= 1) //步长折半
for (i = gap; i < len; i++) {
temp = this[i]
for (j = i - gap; j >= 0 && this[j] > temp; j -= gap)
this[j + gap] = this[j]
this[j + gap] = temp
}
}
时间复杂度为O(n log n)
代码如下:
Array.prototype.heapSort = function() {
var arr = this.slice(0)
function swap(i, j) {
//封装交换操作
var temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
function max_heapify(start, end) {
//最大堆调整。使得根节点为堆的最大值
var dad = start
var son = dad * 2 + 1
if (son >= end) return //递归终止条件
if (son + 1 < end && arr[son] < arr[son + 1]) son++ //选择左右子节点中的大者
if (arr[dad] <= arr[son]) {
swap(dad, son)
max_heapify(son, end)
}
}
var len = arr.length
//初始化,i从最后一个父节点开始往前调整。最终数组第一个元素为最大值
for (var i = (len >> 1) - 1; i >= 0; i--) max_heapify(i, len)
//把堆顶元素交换到末位(进入有序区),然后剩余元素再次进行调整,直至排序结束
for (var i = len - 1; i > 0; i--) {
swap(0, i)
max_heapify(0, i)
}
return arr
}
可把数组看作2部分:(最大堆,有序区)
过程:从堆顶把根卸出来放在有序区之前,然后在调整最大堆。
时间复杂度为平均O(n log n),最坏O(n2)。适合于大的、随机数列表。
代码如下:
Array.prototype.quickSort = function() {
var len = this.length
if (len <= 1) return this.slice(0)
var left = []
var right = []
var mid = [this[0]]
for (var i = 1; i < len; i++)
if (this[i] < mid[0])
left.push(this[i])
else
right.push(this[i])
return left.quickSort().concat(mid.concat(right.quickSort()))
}
参考:
排序算法 - 维基百科