优先队列原来不难!带你手写一个 (2)

节点和父节点比较大小(父节点索引为其二分之一)。如果该节点比父节点更小,则交换数据,一直到不能交换为止,这个过程不用担心不合法,因为父节点更小的话更满足比孩子节点更小。

在这里插入图片描述

在这里插入图片描述

删除pop流程(小根堆为例):

pop删除操作取优先队列内最小的元素,而这个元素肯定就是堆顶元素了,取完之后,这个堆的其他部分还是满足堆的结构但是缺少堆顶。

为了不影响整个结构,我们将末尾的那个元素移到堆顶,此时堆需要调整使其满足堆的性质条件。

交换的这个节点和左右孩子进行比较,如果需要交换则交换,交换后再次考虑交换子节点是否需要交换,一直到不交换为止。最坏情况是交换到根节点,这个复杂度每次为O(logn).

在这里插入图片描述

在这里插入图片描述

代码实现

我想到这里,优先队列的内部流程思想你已经掌握了,但是懂优先队列原理和手写优先队列是两个概念,为了更深入的学习优先队列,在这里就带你手写一个简易型的优先队列。

在代码的具体实现方面,最主要的就是pop()和add()两个函数了。在pop()函数具体实现的时候,将最后一个元素移到堆头考虑和其他孩子节点交换的时候,用while进行操作的时候计算孩子下标的时候要确保不越界。我们用的是数组存储数据,优先队列的长度不一定等于这个数组的长度

而在实现add()函数的时候,这里简单的考虑了一下扩容。

具体实现的代码为:

import java.util.Arrays; public class priQueue { private int size;//优先队列的大小 private int capacity;//数组的容量 private int value[];//储存的值 public priQueue() { this.capacity = 10; this.value = new int[capacity]; this.size=0; } public priQueue(int capacity) { this.capacity = capacity; this.value = new int[capacity]; this.size=0; } /** * 插入元素 * @param number */ public void add(int number) { if(size==capacity)//扩容 { capacity*=1.5; value= Arrays.copyOf(value,capacity); } value[size++]=number;//先加到末尾 int index=size-1; while (index>=1) {//进行交换 if(value[index]<value[index/2]) { swap(index,index/2,value); index=index/2; } else//不需要交换即停止 break; } } public int peek() { return value[0]; } /** * 抛出队头 * @return */ public int pop() { int val=value[0];//呆返回数据额 value[0]=value[--size];//将最后一个元素赋值在堆头 int index=0,leftChild=0,rightChild=0; while (true) { leftChild=index*2+1; rightChild=index*2+2; if(leftChild>=size)//左孩子必须满足在条件内 break; else if(rightChild<size&&value[rightChild]<value[index]&&value[rightChild]<value[leftChild]) {//右孩子更小 swap(index,rightChild,value); index=rightChild; } else if(value[leftChild]<value[index]) {//左孩子更小 swap(index,leftChild,value); index=leftChild; } else //不需要 它自己最小 break; } return val; } //交换两个元素 public void swap(int i,int j,int arr[]) { int team=arr[i]; arr[i]=arr[j]; arr[j]=team; } public int size() { return size; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzpyj.html