@前端常用算法—堆排序-最大堆的添加与删除
堆排序的实现流程
堆排序
- 时间复杂度: O(nlogN)
- 空间复杂度: O(n)
我们以面向对象的方式对堆排序进行分析与实现
// 最大堆的添加 删除 排序
function swap(arr, index1, index2) {
var temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
class Heap {
constructor() {
this.data = [null] //堆顶元素的index为1
}
getData() {
console.log('堆', this.data)
return this.data;
}
heapify(arr) {
arr.unshift(null);
this.data = arr;
// 获取到最后一个非叶子节点的索引
var lastIndex = parseInt((this.data.length - 1) / 2)
for (var i = lastIndex; i > 0; i--) {
this.shiftDown(i); //向下冒泡
}
}
// 添加
insert(num) {
this.data.push(num);
// 维持最大堆
this.shiftUp(this.data.length - 1);
}
shiftUp(currentIndex) {
// 为了维持最大堆向上冒泡是一个递归的过程
while (currentIndex > 1 && this.data[currentIndex] > this.data[parseInt(currentIndex / 2)]) {
// 交换位置
swap(this.data, currentIndex, parseInt(currentIndex / 2));
currentIndex = parseInt(currentIndex / 2);
}
}
// 删除
extractMax() {
// 将堆顶的元素和最后一位进行交换
if (this.data.length > 1) {
swap(this.data, 1, this.data.length - 1);
// 删除最后一位----最大值
var result = this.data.pop();
//向下冒泡,维持最大堆
this.shiftDown(1);
return result;
}
}
shiftDown(currentIndex) {
while (this.data[currentIndex * 2] > this.data[currentIndex] || this.data[currentIndex * 2 + 1] > this.data[currentIndex]) {
if (this.data[currentIndex * 2] < this.data[currentIndex * 2 + 1]) {
// 左子节点大于右子节点
swap(this.data, currentIndex, currentIndex * 2 + 1);
currentIndex = currentIndex * 2 + 1;
} else {
swap(this.data, currentIndex, currentIndex * 2);
currentIndex = currentIndex * 2;
}
}
}
}
var newHeap = new Heap();
newHeap.insert(7)
newHeap.insert(8)
newHeap.insert(9)
newHeap.insert(4)
newHeap.insert(3)
newHeap.insert(2)
newHeap.getData();
newHeap.extractMax() //删除堆顶元素
newHeap.getData()
// 堆排序
var initArr2 = [11, 20, 40, 1, 3, 7, 4]; // 测试数据
//不断的从最大堆的堆顶进行最大值的读取,就等同于进行数据的排序
function heapSort(arr) {
var heapData = new Heap();
var resultArr = [];
// 有没有可能一次性完成最大堆的创建
arr.forEach(val => {
heapData.insert(val);
});
console.log('123', heapData.getData())
// 不断的取出堆顶的元素
for (var i = 0; i < arr.length; i++) {
var result = heapData.extractMax();
resultArr.unshift(result);
}
console.log(resultArr)
return resultArr;
}
heapSort(initArr2)
var heapData2 = new Heap()
heapData2.heapify(initArr2);
heapData2.getData()
总结
对于时间复杂度为O(nlogN)的算法还有很多,比如归并排序,快速排序等,加深对算法的学习和理解,对以后应对更复杂的业务场景和优化算法的时间复杂度有很大的帮助。