您的位置:首页 > 其它

设计一个没有扩容负担的堆结构

2017-11-04 23:20 330 查看
import java.util.Comparator;

/**
* Created by lxw, liwei4939@126.com on 2017/11/4.
* 设计一个没有扩容负担的堆结构
*/
class Node{
public int value;
public Node left;
public Node right;
public Node parent;

public Node(int data){
this.value = data;
}
}

public class myHeap {
private Node head;  // 堆头结点
private Node last;  // 堆尾结点
private long size;  // 堆的大小
private Comparator<Integer> comp; // 大根堆或小根堆

public myHeap(Comparator<Integer> compare){
head = null;
last = null;
size = 0;
comp = compare;
}

public int getHead(){
return head == null ? null : head.value;
}

public long getSize(){
return size;
}

public boolean isEmpty(){
return size == 0 ? true : false;
}

// 添加一个新节点到堆中
public void add(int value){
Node newNode = new Node(value);
if(size ==0){
head = newNode;
last = newNode;
size++;
return;
}
Node node = last;
Node parent = node.parent;
// 找到正确的位置,插入到新节点
while (parent != null && node != parent.left){
node = parent;
parent = node.parent;
}
Node nodeToAdd = null;
if(parent == null){
nodeToAdd  =mostLeft(head);
nodeToAdd.left = newNode;
newNode.parent = nodeToAdd;
} else if(parent.right == null){
parent.right = newNode;
newNode.parent = parent;
} else {
nodeToAdd = mostLeft(parent.right);
nodeToAdd.left = newNode;
newNode.parent = nodeToAdd;
}
last = newNode;
// 建堆及其调整
heapInsertModify();
size++;
}

// 建堆和调整的过程
private void heapInsertModify(){
Node node = last;
Node parent = node.parent;
if(parent != null && comp.compare(node.value, parent.value) < 0){
last = parent;
}
while (parent != null && comp.compare(node.value, parent.value) < 0){
swapClosedTwoNodes(node, parent);
parent = node.parent;
}
if(head.parent != null){
head = head.parent;
}
}

// 堆heapify过程
private void heapify(Node node){
Node left = node.left;
Node right = node.right;
Node most = node;
while (left != null){
if(left != null && comp.compare(left.value, most.value) < 0){
most = left;
}
if(right != null && comp.compare(right.value, most.value) < 0){
most = right;
}
if(most != node){
swapClosedTwoNodes(most, node);
} else {
break;
}
left = node.left;
right = node.right;
most = node;
}
if(node.parent == last){
last = node;
}
while (node.parent != null){
node = node.parent;
}
head = node;
}

//交换两个相近的结点
private void swapClosedTwoNodes(Node node, Node parent){
if(node == null || parent == null){
return;
}
Node parentparent = parent.parent;
Node parentLeft = parent.left;
Node parentRight = parent.right;
Node nodeLeft = node.left;
Node nodeRight = node.right;
node.parent  =parentparent;
if(parentparent != null){
if(parent == parentparent.left){
parentparent.left = node;
} else {
parentparent.right = node;
}
}
if(nodeLeft != null){
nodeLeft.parent = parent;
}
if(nodeRight != null){
nodeRight.parent = parent;
}
parent.parent = node;
parent.left = nodeLeft;
parent.right = nodeRight;

if(node == parent.left){
node.left = parent;
node.right = parentRight;
if(parentRight != null){
parentRight.parent = node;
}
} else {
node.left = parentLeft;
node.right = parent;
if(parentLeft != null){
parentLeft.parent = parent;
}
}
}

// 找到以node为头的子树中,最左的结点
private Node mostLeft(Node node){
while (node.left !=null){
node = node.left;
}
return node;
}

public int popHead(){
if(size == 0){
return 0;
}
Node res = head;
if(size == 1){
head = null;
last = null;
size--;
return res.value;
}
Node oldLast = popLastAndSetPrevoiusLast();
// 若弹出堆尾结点后,堆大小为1
if(size ==1){
head = oldLast;
last = oldLast;
return res.value;
}
// 若弹出堆结点后,堆大小大于1
Node headLeft = res.left;
Node headRight = res.right;
oldLast.left = headLeft;
if(headLeft != null){
headLeft.parent = oldLast;
}
oldLast.right = headRight;
if(headRight != null){
headRight.parent = oldLast;
}
res.left = null;
res.right = null;
head = oldLast;
// 堆heapify过程
heapify(oldLast);
return res.value;
}

// 在树中弹出堆尾结点,找到倒数第二个结点设置为新的堆尾结点
private Node popLastAndSetPrevoiusLast(){
Node node = last;
Node parent  =node.parent;
while (parent != null && node != parent.right){
node = parent;
parent = node.parent;
}
if(parent == null){
node = last;
parent = node.parent;
node.parent = null;
if(node == parent.left){
parent.left = null;
} else {
parent.right = null;
}
last = mostRight(head);
} else {
Node newlast = mostRight(parent.left);
node =last;
parent = node.parent;
node.parent = null;
if(node == parent.left){
parent.left = null;
} else {
parent.right = null;
}
last = newlast;
}
size--;
return node;
}

// 找到以node为头的子树中,最右的节点
private Node mostRight(Node node){
while (node.right != null){
node = node.right;
}
return node;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐