Java数据结构之堆(优先队列)的实现

Java 数据结构之堆(优先队列)的实现

什么是堆(优先队列)

堆(Heap)是一种数据结构,使用数组实现。堆分为小根堆和大根堆,大根堆满足父节点值大于子节点,小根堆则相反。堆通常被用来实现优先队列(Priority Queue)。

优先队列(Priority Queue)是一个能够让用户迅速查找到队列中最小值(或最大值)的抽象数据类型(ADT)。优先队列通常用堆来实现。

在Java中,堆的实现主要有两种方式:一种是使用Collections的PriorityQueue,一种是手动实现堆。

java.util.PriorityQueue实现

Java中自带的PriorityQueue是一种实现了优先队列的数据结构,底层是一个小根堆。它的具体实现是数组,也可以用数组表达式来看待这个堆 。Java中的PriorityQueue提供了数据结构基本操作的方法:插入、删除、获取队首元素、堆大小等。

下面是Java实现PriorityQueue的示例代码:

import java.util.PriorityQueue;
public class Main {
    public static void main(String[] args) {
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        pq.add(3);
        pq.add(1);
        pq.add(2);
        System.out.println(pq);
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        System.out.println(pq.poll());
    }
}

输出结果:

[1, 3, 2]
1
2
3

上面的示例代码首先创建了一个PriorityQueue对象pq,然后通过add()方法插入元素。最后三个poll()方法依次弹出元素。这里需要注意的是,PriorityQueue是小根堆,poll()方法会弹出堆中的最小元素。

手动实现堆

手动实现堆的方式在工程实践中不常用,但是可以增加对堆的深刻理解。

下面是手动实现堆的示例代码:

public class Heap {
    private int[] heap;
    private int size;
    private int maxSize;

    public Heap(int maxSize) {
        this.maxSize = maxSize;
        this.size = 0;
        this.heap = new int[this.maxSize + 1];
        this.heap[0] = Integer.MIN_VALUE;
    }

    private int parent(int i) {
        return i / 2;
    }

    private int leftChild(int i) {
        return i * 2;
    }

    private int rightChild(int i) {
        return (i * 2) + 1;
    }

    private boolean isLeaf(int i) {
        if (i > size / 2 && i <= size) {
            return true;
        }
        return false;
    }

    private void swap(int i, int j) {
        int temp = this.heap[i];
        this.heap[i] = this.heap[j];
        this.heap[j] = temp;
    }

    public void insert(int element) {
        if (size >= maxSize) {
            return;
        }
        this.heap[++size] = element;
        int current = size;
        while (this.heap[current] < this.heap[parent(current)]) {
            swap(current, parent(current));
            current = parent(current);
        }
    }

    public int remove() {
        int popped = this.heap[1];
        this.heap[1] = this.heap[size--];
        heapify(1);
        return popped;
    }

    public void heapify(int i) {
        if (!isLeaf(i)) {
            if (this.heap[i] > this.heap[leftChild(i)] || this.heap[i] > this.heap[rightChild(i)]) {
                if (this.heap[leftChild(i)] < this.heap[rightChild(i)]) {
                    swap(i, leftChild(i));
                    heapify(leftChild(i));
                } else {
                    swap(i, rightChild(i));
                    heapify(rightChild(i));
                }
            }
        }
    }

    public void print() {
        for (int i = 1; i <= size / 2; i++) {
            System.out.print(" PARENT : " + heap[i] + " LEFT CHILD : " + heap[2 * i]
                    + " RIGHT CHILD :" + heap[2 * i + 1]);
            System.out.println();
        }
    }

    public static void main(String[] args) {
        Heap Heap = new Heap(15);
        Heap.insert(5);
        Heap.insert(3);
        Heap.insert(17);
        Heap.insert(10);
        Heap.insert(84);
        Heap.insert(19);
        Heap.insert(6);
        Heap.insert(22);
        Heap.insert(9);

        Heap.print();

        System.out.println("The Min val is " + Heap.remove());
    }
}

输出结果:

 PARENT : 3 LEFT CHILD : 5 RIGHT CHILD :17
 PARENT : 5 LEFT CHILD : 10 RIGHT CHILD :84
 PARENT : 17 LEFT CHILD : 6 RIGHT CHILD :19
 PARENT : 10 LEFT CHILD : 22 RIGHT CHILD :9
The Min val is 3

上面的代码实现了手动创建堆和一些基本操作的方法,例如:insert()、remove()、heapify()以及print()操作。我们可以看到,输出的结果是小根堆的形式,remove()方法会返回堆中的最小元素。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java数据结构之堆(优先队列)的实现 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • JavaScript数据结构之链表的实现

    JavaScript数据结构之链表的实现 什么是链表 链表是一种线性数据结构,其中的元素在内存中不连续地存储,每个元素通常由一个存储元素本身的节点和一个指向下一个元素的引用组成。相比较于数组,链表具有如下优缺点: 优点:动态地添加或删除元素时,无需移动其它元素。(数组则需要移动其它元素) 缺点:不能随机地访问某个元素,必须从头开始顺序遍历。(而数组可以通过索…

    数据结构 2023年5月17日
    00
  • InputStream数据结构示例解析

    InputStream数据结构示例解析 InputStream是Java中一个重要的数据结构,它表示可以从其中读取数据的输入流。通常情况下,它表示的是用来读取字节流数据的输入流。在本篇攻略中,我们将会详细解释如何使用InputStream数据结构来读取字节流数据,并且给出两条具体的读取示例。 InputStream类的继承结构 InputStream类是一个…

    数据结构 2023年5月17日
    00
  • 详解如何在Go语言中循环数据结构

    请看下面的完整攻略。 如何在Go语言中循环数据结构 在Go语言中,常见的数据结构包括数组、切片、映射、通道、链表等。循环数据结构是编程中常见的操作之一,下面我们将介绍如何在Go语言中循环不同的数据结构。 使用for循环遍历数组 数组是一种拥有固定大小的数据结构,如果我们想要遍历一个数组,可以使用for循环实现。以下是一个数组遍历示例: package mai…

    数据结构 2023年5月17日
    00
  • 集合框架及背后的数据结构

    集合框架及背后的数据结构 集合框架是Java编程语言中的一组接口和实现类,用于存储数据的集合。集合框架中提供了许多不同类型的集合,包括List、Set、Map等。背后的数据结构是实现集合框架的关键,不同的数据结构适用于不同的集合类型和场景。 集合框架中的接口和实现类 Java中的集合框架定义了一些接口以及这些接口的实现类,在使用Java集合的时候,主要是使用…

    数据结构 2023年5月17日
    00
  • MySQL数据库体系架构详情

    MySQL数据库体系架构是MySQL数据库自身的发展和演变过程中逐渐形成的一个庞大的体系。这个体系由多个组件构成,包括连接器、查询缓存、解析器、优化器、执行器、存储引擎等多个部分,其中存储引擎是其中最具有代表性的组件之一。在这篇攻略中,我们将详细讲解MySQL数据库体系架构的各个部分,介绍它们各自的功能和作用。 连接器 MySQL的连接器负责与客户端建立连接…

    数据结构 2023年5月17日
    00
  • C语言数据结构中定位函数Index的使用方法

    C语言的数据结构中,定位函数Index的使用方法主要涉及到数组和指针的相关操作。Index函数的作用是在数组中查找对应的元素,返回该元素的索引位置。以下是详细攻略: 一、Index函数的用法 Index函数的原型如下: void *index(const void *s, int c, size_t n); 其中,参数含义如下: s: 要查找的数组 c: 要…

    数据结构 2023年5月17日
    00
  • Java实题演练二叉搜索树与双向链表分析

    Java实题演练二叉搜索树与双向链表分析 题目描述 给定一个二叉搜索树,将它转换成一个排序的双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。 思路分析 对于一颗二叉搜索树,有以下性质: 若左子树不为空,则左子树上所有结点的值均小于它的根结点的值; 若右子树不为空,则右子树上所有结点的值均大于它的根结点的值; 左右子树也为二叉搜索树。 我们考虑…

    数据结构 2023年5月17日
    00
  • C语言实题讲解快速掌握单链表上

    C语言实题讲解快速掌握单链表 什么是单链表? 单链表是一种链式存储的线性数据结构,它由一系列称为节点的组成。每个节点都包括两个部分:数据域和指针域。指针域指示了下一个节点的地址,因此,我们可以通过遍历链表的方式访问所有节点。 单链表的操作 创建一个单链表 我们可以通过以下步骤来创建一个单链表:1. 定义单链表的节点结构体,包括数据域和指针域。2. 定义一个指…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部