一 : 堆
什么是堆?
堆可以理解成一个完全二叉树
只不过堆是以数组的形式表现出来的
满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆4. 反之,则是小堆,或者小根堆,或者最小堆。
大堆与小堆可以用于筛选数组之中最大值或是最小值,
比如在千万级别的数据中找到前五个最大的值,那么就要建立一个有五个元素的小堆,每一次筛选,如果筛选的元素比堆顶就找到堆顶最小的元素将其换下来
那么怎么进行堆的排序呢?
有向上调整和向下调整
如果是一个不规则的堆,那么就要从最后一个非叶子节点向下调整
这里以大堆举例
public static void shiftDownBig(int[] arr, int sz, int parent){
int child = 2 * parent + 1; // left child
// 从parent节点开始,一直调整到叶子节点结束
while(child < sz){
//right child : child + 1 从两个孩子节点中选一个最大的
if(child + 1 < sz && arr[child + 1] > arr[child]){
++child;
}
if(arr[child] > arr[parent]){
//如果child 大于 parent, 向下调整,交换值
swap(arr, child, parent);
//更新,继续向下调整
parent = child;
child = 2 * parent + 1;
}
else{
//不需要调整
break;
}
}
}
这只是一次调整,在建堆的时候要进行好几次,直到根部节点
建堆:
public static void creatHeapBig(int[] arr){
//从最后U一个非叶子节点开始向下调整
for(int i = (arr.length - 2) / 2; i >= 0; --i){
shiftDownBig(arr, arr.length, i);
}
}
而小堆的向下调整和建堆,只需要把条件换一下就好了
//小堆的向下调整
public static void shiftDownSmall(int[] arr, int sz, int parent){
int child = 2 * parent + 1; // left child
// 从parent节点开始,一直调整到叶子节点结束
while(child < sz){
//right child : child + 1 从两个孩子节点中选一个最小的
if(child + 1 < sz && arr[child + 1] < arr[child]){
++child;
}
if(arr[child] < arr[parent]){
//如果child 大于 parent, 向下调整,交换值
swap(arr, chi, parent);
//更新,继续向下调整
parent = child;
child = 2 * parent + 1;
}
else{
//不需要调整
break;
}
}
}
public static void creatHeapSmall(int[] arr){
//从最后U一个非叶子节点开始向下调整
for(int i = (arr.length - 2) / 2; i >= 0; --i){
shiftDownSmall(arr, arr.length, i);
}
}
二 ,优先级队列
在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理
次高的对象。最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电
话。
在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。
这种数据结构就是优先级队列(Priority Queue)
主要还是用堆来进行完成
入队操作就是尾插到最后一个位置,然后从最后一个位置,然后向上调整
private int[] arr = new int[10];
private int sz;
//入队
public void offer(int value){
if(sz == arr.length){
arr = Arrays.copyOf(arr, arr.length * 2);
}
// 1. 尾插
// 2. 向上调整
arr[sz++] = value;
MHeap.shiftUpSmall(arr, sz, sz - 1);
}
poll的话是将根部元素与最后一个元素进行互换,然后把最后的删掉,然后再从根部往下整理堆
//出队
public int poll(){
if(sz > 0){
int peek = arr[0];
MHeap.swap(arr, 0, sz - 1);
--sz;
MHeap.shiftDownSmall(arr, sz, 0);
return peek;
}
return -1;
}
public int peek(){
return arr[0];
}
public boolean isEmpty(){
return sz == 0;
}
来源:CSDN
作者:yiqqYi
链接:https://blog.csdn.net/yiqqYi/article/details/104555360