快速排序与堆排序
一、快速排序
1.快速排序是利用递归思想的一个分治排序算法,时间复杂度为O(n * logn)。对数组nums[l......r]进行快速排序的方法如下:
(1)确认基准点。一般为nums[l]或nums[r],确定左右端点后,从其相反方向寻找不满足条件的数字。
(2)如为升序排列,比基准点小的数字要放在左边,比基准点大的数字要放在右边。
(3)直到左右指针重叠时,交换基准点和当前左指针数字,即确定了基准点数字在数组nums[l......r]的最终位置,设为q。
(4)对nums[l......q]和nums[q......r]分别进行递归排序。
2.代码实现:
void quickSort(int[] nums, int l, int r){ //左右指针重叠时,退出排序 if(l >= r) return; //返回已确定最终位置的元素索引 int index = partition(nums, l, r); //左右递归 quickSort(nums, l, index - 1); quickSort(nums, index + 1, r); } int partition(int[] nums, int l, int r){ //设置左指针元素为基准元素 int temp = nums[l]; while(l < r){ //从右开始判断,遇到小于基准数的元素退出循环 while(l < r && nums[r] > temp){ r--; }
//修改当前左指针元素,左指针右移一位
if(l < r){
nums[l++] = nums[r];
}
//再从左开始寻找第一个大于基准数的数字 while(l < r && nums[l] < temp){ l++; } //修改当前右指针元素,右指针左移一位 if(l < r){ nums[r--] = nums[l]; } } //最后交换基准数和左指针对应元素,确定了基准数的最终位置 nums[l] = temp; return l; }
二、堆排序
1.堆(heap)排序是使用名为堆的类似完全二叉树的数据结构进行排序的算法,分为极大堆(降序)和极小堆(升序)。使用极大堆对数组进行降序排序的过程如下:
(1)使用原数组构造极大堆:
①一般来说可将原数组直接视为完全二叉树结构,索引为i的父节点拥有索引为2 * i + 1的左子节点和索引为2 * i + 2的右子节点。因此时尚未形成极大堆,要对原数组进行操作。
②从最后一个非叶子节点开始,从下往上重构数组,即从左子节点和右子节点中选取较大值和当前节点比较,若当前节点值更大则无需操作,否则交换当前节点和较大节点值。若发生上述交换,重构子节点极大堆。确定最后一个非叶子节点也无需其他操作,其索引即为数组长度 / 2 - 1。数组重构到根节点后,极大堆就构造完成了。
(2)若要得到数组的降序排列,即每次把数组的最大值输出即可。已知极大堆的根节点为最大值节点,可进行如下过程:
①交换根节点和尾节点,以此把最大值节点摘除(此时已在尾部)。
②重构极大堆。
2.代码如下:
//交换nums[i]、nums[j] void swap(int[] nums, int i, int j){ int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } //构建极大堆 void buildMaxHeap(int[] nums, int heapSize){ for(int i = heapSize / 2 - 1; i >= 0; i--){ maxHeapify(nums, i, heapSize); } } //对nums[i]及其左右节点进行重构 void maxHeapify(int[] nums, int i, int heapSize){ int left = i * 2 + 1, right = i * 2 + 2, largest = i; if(left < heapSize && nums[left] > nums[largest]){ largest = left; } if(right < heapSize && nums[right] > nums[largest]){ largest = right; } if(largest != i){ swap(nums, i, largest); maxHeapify(nums, largest, heapSize); } } //堆排序 void heapSort(int[] nums){ int heapSize = nums.length; buildMaxHeap(nums, heapSize); int i = heapSize - 1; while(i > 1){ //交换首尾元素 swap(nums, 0, i); //此处可以对nums[i]进行操作了,因为接下来不会对他进行操作 System.out.println(nums[i]); //对剩余的从nums[0]到nums[i]的极大堆进行重构 maxHeapify(nums, 0, i); i--; } }
三、练习
Leetcode 215. 数组中的第K个最大元素,链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/。
本文作者:夜满星河
本文链接:https://www.cnblogs.com/ThXin/p/16209839.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步