堆
floyd建堆法
介绍:通过找到最后一个非叶子结点的方法 执行下潜操作 一直到根节点
1、建堆
2、找到最后一个非叶子节点
3、下潜
实现堆最重要的几个方法:
下潜
思路:
当前节点:parent
子节点:child
rightChild = parent * 2 + 1
leftChild = right + 1
1、parent依次和左右子节点进行比较
2、如果parent处的节点小于左右子节点 则进行交换 继续下潜
3、如果都parent比左右子节点都大 停止下潜
这里通过递归实现
private void down(int parent){
int rightChild = parent * 2 + 1;
int leftChild = rightChild + 1;
int max = parent;
if(rightChild < size && array[rightChild] > array[max]){
max = rightChild;
}
if(leftChild < size && array[leftChild] > array[max]){
max = leftChild;
}
if(max != parent){
swap(parent, max);
down(max);
}
}
上浮
思路:
当前节点:child 父节点:parent
parent = (child-1)/2
1、每次child处的值 和 parent处的值进行比较
2、大于 则将parent处的值赋值给child 继续上浮 否则执行步骤3
3、将值赋值给最后的child
private void up(int element){
int child = size;
//为了避免parent越界 判断child
while(child > 0){
int parent = (child-1)/2;
if(array[parent] <= element){
array[child] = array[parent];
child = parent;
}else{
break;
}
}
** **array[child] = element;
}
交换:
通过临时变量接收来交换
上代码
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
其他方法:
删除弹出元素 poll
堆顶 指定索引出删除
思路:
从当前结点开始 执行下潜操作
public int poll(){
if(isEmpty()){
return -1;
}
int removed = array[0];
swap(0,size-1);
size--;
down(0);
return removed;
}
public int poll(int index){
if(index >= size){
return -1;
}
int removed = array[index];
swap(index,size-1);
size--;
down(index);
return removed;
}
弹出元素 peek
public int peek() throws Exception{
if(isEmpty()){
throw new Exception("list is null");
}
return array[0];
}
尾部添加 offer
从当前节点开始 执行上浮操作
public boolean offer(int element){
if(isFull()){
return false;
}
up(element);
size++;
return false;
}
堆顶替换 replace
替换堆顶元素,执行下潜操作
//替换堆顶的元素
public void replace(int element){
//当堆顶为空时,直接添加
if(isEmpty()){
offer(element);
}
array[0] = element;
down(0);
}
结论:以后遇到边界问题,优先判断离边界更近的一段,这样可避免大多数越界问题。
比如上面的下潜先判断孩子索引 上浮判断parent索引
可能结论有误,等到以后有新的结果才来推翻。