堆: 堆逻辑上是一棵完全二叉树, 堆物理上是保存在数组中。满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆。反之,则是小堆,或者小根堆,或者最小堆。
向下调整,向上调整,建堆,代码实现
public class lx {
public static void adjustDown(int []array ,int size,int index){
while (true){
//左孩子的位置为index位置*2+1
int leftChild=2*index+1;
//判断是否为叶子节点 出口一
if(leftChild>=size){
return;
}
//找最小孩子
int rightChild=leftChild+1;
int minChild=leftChild;
//比较左右孩子的元素大小 小的放进minChild中
if(rightChild<size&&array[rightChild]<array[leftChild]){
minChild=rightChild;
}
//比较最小孩子(minChild)与index位置的值
if (array[index] <= array[minChild]) {
return;
}
// 4.程序 走到这说明不满足堆的性质 进行交换将index位置元素与minIndex位置的元素进行交换
int t = array[index];
array[index] = array[minChild];
array[minChild] = t;
// 5.循环 把最小的孩子视为 index,继续循环直到index位置满足堆的性质
index = minChild;
}
}
public static void adjustUp(int []array ,int size ,int index){
while (true){
// 出口 index位置为根位置
if(index==0){
break;
}
//找到Index位置的父亲位置 parentIndex
int parentIndex=(index-1)/2;
//出口 满足堆的性质 父亲的值小于左右孩子
if(array[parentIndex]<array[index]){
break;
}
// 不满足 交换index位置与parentIndex位置上的元素
int t=array[parentIndex];
array[parentIndex]=array[index];
array[index]=t;
}
}
public static void createHeap(int []array, int size){
//找到层序遍历最后一个结点的下标
int lastIndex=size-1;
//找到最后一个结点父节点下标
int parentIndex=lastIndex-1/2;
for (int i = parentIndex; i >=0; i--) {
adjustDown(array,size,i);
}
}
}
我自己实现的优先级队列(堆)add()remove() element() 方法 (以小堆为例) 需要注意的是:当进行add时要进行向上调整(adjust up)当进行remove时要删除优先级队列中第一个元素 并且把最后一个元素放到第一个元素上,然后在进行向下调整(adjust down)
优先级队列(堆):可以找出数组中最大值(大堆),最小值(小堆)
public class MyPriorityQueue {
private Integer[] array;
private int size;
public MyPriorityQueue(){
array=new Integer[100];
size=0;
}
public Integer element(){
if(size==0){
throw new RuntimeException("空了");
}
return array[0];
}
public Integer remove(){
if(size==0){
throw new RuntimeException("空了");
}
int e=array[0];
array[0]=array[size-1];
size--;
adjustDown(0);
return e;
}
public void add(Integer e){
array[size]=e;
size++;
adjustUp(size-1);
}
private void adjustDown(int index) {
while (true) {
int leftChildIndex = 2 * index + 1;
if (leftChildIndex >= size) {
return;
}
int rightChildIndex = leftChildIndex + 1;
int minChildIndex = leftChildIndex;
if (rightChildIndex < size && array[rightChildIndex] < array[leftChildIndex]) {
minChildIndex = rightChildIndex;
}
if (array[index] <= array[minChildIndex]) {
return;
}
int t = array[minChildIndex];
array[minChildIndex] = array[index];
array[index] = t;
index = minChildIndex;
}
}
private void adjustUp(int index){
while (true){
if(index==0){
return;
}
//找到Index位置的父亲位置 parentIndex
int parentIndex=(index-1)/2;
//出口 满足堆的性质 父亲的值小于左右孩子
if(array[parentIndex]<array[index]){
break;
}
// 不满足 交换index位置与parentIndex位置上的元素
int t=array[parentIndex];
array[parentIndex]=array[index];
array[index]=t;
}
}
}