排序算法-(7)堆排序
堆排序
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:
同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子
该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
详细步骤和原理可以看这篇:https://www.cnblogs.com/chengxiao/p/6129630.html
排序是一种选择排序,整体主要由构建初始堆+交换堆顶元素和末尾元素并重建堆两部分组成。其中构建初始堆经推导复杂度为O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质,[log2(n-1),log2(n-2)...1]逐步递减,近似为nlogn。所以堆排序时间复杂度一般认为就是O(nlogn)级。
堆排序属于选择排序算法,是不稳定的
代码实现
//重新调整为大顶堆 function _heapify(arr, size, index) { let largest = index; const left = 2 * index + 1; const right = 2 * index + 2; if (left < size && arr[left] > arr[largest]) { largest = left; } if (right < size && arr[right] > arr[largest]) { largest = right; } if (largest !== index) { [arr[index], arr[largest]] = [arr[largest], arr[index]]; _heapify(arr, size, largest); } } //这里的堆排序用的是最大堆 function heapSort(arr) { const result = arr.slice(0); const size = arr.length; for (let i = Math.floor(size / 2 - 1); i >= 0; i--) { _heapify(result, size, i); } for (let i = size - 1; i >= 0; i--) { [result[0], result[i]] = [result[i], result[0]]; _heapify(result, i, 0); } return result; }