快速排序与堆排序

一、快速排序

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 中国大陆许可协议进行许可。

posted @   夜满星河  阅读(489)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起