二项堆的操作

class Node {
	Node parent;
	Node child;
	Node sibling;
	int key;
	int degree;

	public Node(int key) {
		this.key = key;
		this.degree = 0;
		this.child = null;
		this.parent = null;
		this.sibling = null;

	}
}

public class BinomialHeap {
	public Node head;

	public BinomialHeap() {
		head = null;
	}

	// 寻找最小关键字
	public Node min() {
		Node n = head;
		Node m = null;
		int min = head.key;

		while (null != n) {
			if (min > n.key) {
				min = n.key;
				m = n;
			}
			n = n.sibling;
		}

		return m;
	}

	// 按度的大小归并两个二项堆
	public void merge(BinomialHeap heap) {
		Node node;
		Node head1 = this.head;
		Node head2 = heap.head;

		// 确定head
		if (head1.degree < head2.degree) {
			node = head1;
			head1 = head.sibling;
		} else {
			this.head = head2;
			node = heap.head;
			head2 = head2.sibling;
		}

		// 归并二项堆
		while (head1 != null && head2 != null) {
			if (head1.degree < head2.degree) {
				node.sibling = head1;
				node = head1;
				head1 = head1.sibling;
			} else {
				node.sibling = head2;
				node = head2;
				head2 = head2.sibling;
			}
		}

		if (head1 == null) {
			node.sibling = head2;
		} else {
			node.sibling = head1;
		}
	}

	// 合并二叉树
	public void link(Node big, Node small) {
		big.parent = small;
		big.sibling = small.child;
		small.child = big;
		small.degree++;
	}

	// 合并二项堆(把this和heap合并为一个新的this)
	public void union(BinomialHeap heap) {
		// 处理空值的情况
		if (null == heap.head) {
			return;
		}
		if (null == this.head) {
			this.head = heap.head;
			return;
		}

		// 没有空值开始合并
		merge(heap);

		Node pre = null;
		Node x = this.head;
		Node next = x.sibling;

		while (null != next) {
			if ((x.degree != next.degree)
					|| (null != next.sibling && next.sibling.degree == x.degree)) {
				pre = x;
				x = next;
			} else if (x.key <= next.key) {
				x.sibling = next.sibling;
				link(next, x);
			} else {
				if (null == pre) {
					this.head = next;
				} else {
					pre.sibling = next;
				}
				link(x, next);
				x = next;
			}
			next = x.sibling;
		}
	}

	// 插入新结点
	public void insert(int key) {
		Node node = new Node(key);
		BinomialHeap h = new BinomialHeap();
		h.head = node;
		union(h);
	}

	// 查找某结点
	public Node find(int key, Node node) {
		if (null == node) {
			return null;
		}
		if (key == node.key) {
			return node;
		}
		Node n1 = find(key, node.sibling);
		Node n2 = find(key, node.child);
		if (n1 != null || n2 != null) {
			if (n1 != null) {
				return n1;
			} else {
				return n2;
			}
		} else {
			return null;
		}
	}

	// 抽取关键字最小的结点
	public void extract_min() {
		Node min = min();
		Node premin = head;

		// 把最小值所在的二项树独立出来
		if (min != head) {
			while (premin.sibling != min) {
				premin = premin.sibling;
			}
			premin.sibling = min.sibling;
		} else {
			head = head.sibling;
		}
		min.sibling = null;

		// 把最小值所在的二项树重新组织成二项堆
		BinomialHeap bh = new BinomialHeap();

		// 让min脱离出来
		Node child = min.child;
		child.parent = null;
		min.child = null;

		// 反转min的孩子使之成为新的二项堆(这也是反转单向链表的一般方法)
		Node pre, cur, ne;
		pre = child;
		cur = child.sibling;
		pre.sibling = null;
		while (cur != null) {
			ne = cur.sibling;
			cur.parent = null;
			cur.sibling = pre;
			pre = cur;
			cur = ne;
		}
		bh.head = pre;

		// 分离出来的新二项堆与原来的合并
		union(bh);
	}

	// 减小某结点的值
	public void decrease_key(int key, int nkey) {
		if (nkey > key) {
			System.out.print("error,输入的数比原结点的值大\n");
			return;
		} else {
			Node n = find(key, head);
			if (n == null) {
				System.out.print("结点不存在\n");
				return;
			} else {
				n.key = nkey;
				Node nparent = n.parent;
				while (nparent != null && n.key < nparent.key) {
					int temp = n.key;
					n.key = nparent.key;
					nparent.key = temp;

					n = nparent;
					nparent = nparent.parent;
				}
			}
		}
	}

	// 删除结点
	public void delete(int key) {
		Node n = find(key, head);
		if (n == null) {
			System.out.print("结点不存在\n");
			return;
		} else {
			decrease_key(key, -Integer.MAX_VALUE);
			extract_min();
		}
	}

	// 遍历二项堆
	public void traversal(Node node) {
		if (null == node) {
			return;
		}
		System.out.print(node.key + ",");
		traversal(node.sibling);
		traversal(node.child);
	}

	public static void main(String[] args) {
		int[] E = { 0, 12, 90, 1, 85, 12, 3, 13, 49, 55, 10, 3, 31, 97, 19, 93,
				41, 55, 56, 82, 2, };
		BinomialHeap heap = new BinomialHeap();

		// 建立二项堆
		for (int i = 0; i < E.length; i++) {
			heap.insert(E[i]);
		}
		// 遍历
		heap.traversal(heap.head);

		// 查找
		Node n = heap.find(87, heap.head);
		System.out.println();
		if (null == n) {
			System.out.print("结点不存在\n");
		} else
			System.out.print("要找的结点值为" + n.key + "\n");

		// 输出最小值
		System.out.println("最小值为:" + heap.min().key);

		// 删除结点
		heap.delete(19);

		heap.traversal(heap.head);
	}
}


转自:http://hi.baidu.com/%D0%D0%D7%DF%D4%DA%BF%D5%D6%D0/blog/item/7523d112268f0a41f819b89f.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章