堆排序

作者: zxRay | 来源:发表于2023-12-29 23:27 被阅读0次

堆定义

大顶堆:根节点比左右节点都大
小顶堆:根节点比左右节点都小
堆是一颗完全二叉树,所以可以用数组表示。

堆调整

堆调整从父节点开始一直到叶子节点,如:



算法的时间复杂度为O(lgn)

void heapify(int a[], int parent, int heapSize) {
   int left = 2 * parent + 1;
   while(left < heapSize) {
        int maxIdx = parent;
        int right = left + 1;
        if(left < heapSize && a[left] > a[maxIdx]) {
            maxIdx = left;
        }
        if(right < heapSize && a[right] > a[maxIdx]) {
            maxIdx = right;
        }

        if(maxIdx == parent) break;

        int tmp = a[maxIdx];
        a[maxIdx] = a[parent];
        a[parent] = tmp;
    
        parent = maxIdx;
        left = 2 * parent + 1;
   }
}

建堆

如果数组元素已经固定,那么可以基于heapify方法将数组调整为堆结构。过程就是从最右的非叶节点一直heapify根节点即可,复杂度O(n)

void buildMaxHeap(int a[]) {
   if(a == null || a.length <= 1) return;
   int heapSize = a.length;
   for(int i = heapSize / 2; i >= 0; i--) {
       heapify(a, i, heapSize);
   }
}

堆排序

堆排序(从小到大)的规程就是:

  1. 将数组调整为大顶堆
  2. 将堆对元素同最后一个元素交换
  3. 去掉最后一个元素,然后将剩余数组继续调整为大顶堆


  static void heapSort(int a[]) {
        int heapSize = a.length;
        for(int i = heapSize / 2; i >= 0; i--) {
            heapify(a, i, heapSize);
        }
        for(int i = heapSize - 1; i >= 0; i--) {
            int temp = a[i];
            a[i] = a[0];
            a[0] = temp;
            heapify(a, 0, i);
        }
    }

第K大数

https://leetcode.cn/problems/kth-largest-element-in-an-array/

    // O(nlgn)
    static int findKthLargest(int[] nums, int k) {
        if(nums == null || nums.length <= k) return -1;
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((a, b) -> {return b - a;});
        for(int i = 0; i < nums.length; i++) {
            priorityQueue.add(nums[i]);
        }
        for(int i = 0; i < k - 1; i++) {
            priorityQueue.poll();
        }
        return priorityQueue.poll();
    }

    // O(nlgk)
    static int findKthLargest2(int[] nums, int k) {
        if(nums == null || nums.length <= k) return -1;
        // 维护一个大小为k的小顶堆
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
        for(int i = 0; i < nums.length; i++) {
            if(priorityQueue.size() < k) {
                priorityQueue.add(nums[i]);
            } else {
                if(nums[i] > priorityQueue.peek()) {
                    priorityQueue.poll();
                    priorityQueue.add(nums[i]);
                }
            }
        }
        return priorityQueue.poll();
    }

合并 K 个升序链表

https://leetcode.cn/problems/kth-largest-element-in-an-array/solutions/307351/shu-zu-zhong-de-di-kge-zui-da-yuan-su-by-leetcode-/
两个有序链表归并只需要用pq两个指针即可,一个指向链表1,一个指向链表2,然后选择pq中较小的一个往后滑动即可。K个链表归并那就需要大小为k小顶堆来输出最小元素即可

    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null) return null;
        ListNode dummy = new ListNode();
        ListNode p = dummy;

        PriorityQueue<ListNode> queue = new PriorityQueue<ListNode>((a, b) -> {
            return a.val - b.val;
        });
        for(ListNode node : lists) {
            if(node != null) {
                queue.add(node);
            }
        }
        while(!queue.isEmpty()) {
            ListNode node = queue.poll();
            p.next = node;
            p = p.next;
            if(node.next != null) {
                queue.add(node.next);
            }
        }
        return dummy.next;
    }

相关文章

  • 堆排序

    目录 1.堆排序介绍 2.堆排序图文说明 3.堆排序的时间复杂度和稳定性 4.堆排序实现 堆排序介绍 堆排序(He...

  • 堆排序---基础篇

    本文主要介绍堆排序的一些基本过程和分析。 大纲 堆排序简介 堆排序代码实现 1. 堆排序简介 1.1 堆排序的存储...

  • 堆和堆排序

    最小K个数 堆排序 堆排序

  • JS实现堆排序

    原理 堆排序原理 实现 说明 堆排序对大文件很有效 堆排序是不稳定排序

  • iOS算法总结-堆排序

    iOS算法总结-堆排序 iOS算法总结-堆排序

  • 堆排序

    转载:图解排序算法(三)之堆排序 预备知识 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选...

  • 排序

    原创 堆排序: 使用visit数组从本质出发获取大顶堆排序。

  • 堆排序

    堆排序

  • C++基础入门之模板堆排序(上):模板上的list的创造与操作

    整段源码链接C++的模板元堆排序 要点 组建数据结构list 组建对list的各种基本操作 堆排序中组建堆排序个个...

  • 3.2-选择排序-堆排序

    参考链接 选择排序:堆排序(Heap Sort) 白话经典算法系列之七 堆与堆排序 堆排序与快速排序,归并排序一样...

网友评论

      本文标题:堆排序

      本文链接:https://www.haomeiwen.com/subject/vlmsndtx.html