堆排序:高效稳定的大数据排序法
堆排序的基本概念
堆排序是一种基于二叉堆数据结构的比较排序算法。它利用堆这种数据结构的特性来进行排序,分为大顶堆和小顶堆。大顶堆的每个节点值都大于或等于其子节点值,小顶堆则相反。堆排序通常使用大顶堆进行升序排序。
堆排序的实现步骤
构建初始堆:将无序数组构建成一个大顶堆。构建过程从最后一个非叶子节点开始,依次向上调整,确保每个节点满足堆的性质。
排序过程:将堆顶元素(最大值)与数组末尾元素交换,此时末尾元素为最大值。将剩余元素重新调整为大顶堆,重复交换和调整过程,直到整个数组有序。
堆排序的代码实现
function heapSort(arr) {let len = arr.length;// 构建大顶堆for (let i = Math.floor(len / 2) - 1; i >= 0; i--) {heapify(arr, len, i);}// 交换堆顶和末尾元素,并调整堆for (let i = len - 1; i > 0; i--) {[arr[0], arr[i]] = [arr[i], arr[0]];heapify(arr, i, 0);}return arr;
}function heapify(arr, len, i) {let largest = i;let left = 2 * i + 1;let right = 2 * i + 2;if (left < len && arr[left] > arr[largest]) {largest = left;}if (right < len && arr[right] > arr[largest]) {largest = right;}if (largest !== i) {[arr[i], arr[largest]] = [arr[largest], arr[i]];heapify(arr, len, largest);}
}
堆排序的时间复杂度
堆排序的时间复杂度为 O(nlogn)O(n \log n)O(nlogn)。构建堆的过程时间复杂度为 O(n)O(n)O(n),每次调整堆的时间复杂度为 O(logn)O(\log n)O(logn),共进行 n−1n-1n−1 次调整。
堆排序的空间复杂度
堆排序是原地排序算法,不需要额外的存储空间,空间复杂度为 O(1)O(1)O(1)。
堆排序的稳定性
堆排序不是稳定的排序算法。在交换堆顶和末尾元素的过程中,可能会改变相同元素的相对顺序。
堆排序的应用场景
堆排序适用于数据量较大的场景,尤其是需要部分排序或优先队列的场景。由于堆排序的时间复杂度稳定且空间复杂度低,适合处理大数据集。
堆排序的优缺点
优点:时间复杂度稳定为 O(nlogn)O(n \log n)O(nlogn),空间复杂度低,适合大数据集排序。
缺点:不是稳定排序,实现相对复杂,缓存不友好,因为堆的调整过程涉及不连续的内存访问。
//堆排序->完全平衡二叉树
//大顶堆->每个节点值大于等于其子节点,升序
//过程:构建初始化堆,从最后一排非叶子节点,依次向上调整,保证堆//调整,堆顶元素和微末元素调整function hearpify(arr,len,i){let left=2*i+1;let right=2*i+2;let largest=i;for(left<len&&arr[left]>arr[largest]){largest=left;}for(right<len&&arr[right]>arr[largest]){largest=right;}if(largest!==i){[arr[largest],arr[i]]=[arr[i],arr[largest]];heapify(arr,len,largest);}
}
function heapSort(arr){let len=arr.length;for(let i=Math.floor(len/2)-1;i>=0;i--){heapfy(arr,len,i);}for(let j=len-1;j>0;j--){[arr[0],arr[j]]=[arr[j],arr[0]];heapify(arr,j,0);}return arr;
}