二项堆、二项树—优先队列(Java实现)

二项堆

(binomial heap)是一种类似于二叉堆的堆结构。二项堆是指满足以下性质的二项树的集合,每一棵堆序树都是由约束的形式,叫做二项树。与二叉堆相比,其优势是可以快速合并两个堆,因此它属于可合并堆(mergeable heap)抽象数据类型的一种。

 

二项堆属性:

在一个高度为K的二项树中:

1. 根节点有K个儿子

2.树有2^{k}个节点

3. 树的高度为K

4. 二项树B_{k}子树由一个带有儿子B_{0}B_{1}、、、B_{k-1} 的根组成。

5 .每棵二项树都满足最小堆性质,即结点关键字大于等于其父结点的值

6 .不能有两棵或以上的二项树有相同度数(包括度数为0)。换句话说,具有度数k的二项树有0个或1个。

 

二项树

度数为0的二项树只包含一个结点。

度数为k的二项树有一个根结点,根结点下有k个子女,每个子女分别是度数分别为{\displaystyle k-1,k-2,...,2,1,0}的二项树的根。

  度为0的二项树

  度为1的二项树

   度为2的二项树

 度为3的二项树

代码:

二项堆节点

class BinomialHeapNode
{
    int key, degree;
    BinomialHeapNode parent;
    BinomialHeapNode sibling;
    BinomialHeapNode child;
 
    /* Constructor */
    public BinomialHeapNode(int k) 
    {
        key = k;
        degree = 0;
        parent = null;
        sibling = null;
        child = null;        
    }
    /* Function reverse */
    public BinomialHeapNode reverse(BinomialHeapNode sibl) 
    {
            BinomialHeapNode ret;
            if (sibling != null)
                ret = sibling.reverse(this);
            else
                ret = this;
            sibling = sibl;
            return ret;
    }
    /* Function to find min node */
    public BinomialHeapNode findMinNode() 
    {
            BinomialHeapNode x = this, y = this;
            int min = x.key;
 
            while (x != null) {
                if (x.key < min) {
                    y = x;
                    min = x.key;
                }
                x = x.sibling;
            }
 
            return y;
    }
    /* Function to find node with key value */
    public BinomialHeapNode findANodeWithKey(int value) 
    {
            BinomialHeapNode temp = this, node = null;
 
            while (temp != null) 
            {
                if (temp.key == value) 
                {
                    node = temp;
                    break;
                }
                if (temp.child == null)
                    temp = temp.sibling;
                else 
                {
                    node = temp.child.findANodeWithKey(value);
                    if (node == null)
                        temp = temp.sibling;
                    else
                        break;
                }
            }
 
            return node;
    }
    /* Function to get size */
    public int getSize() 
    {
        return (1 + ((child == null) ? 0 : child.getSize()) + ((sibling == null) ? 0 : sibling.getSize()));
    }
}

二项堆:

class BinomialHeap
{
    private BinomialHeapNode Nodes;
    private int size;
 
    /* Constructor */
    public BinomialHeap()
    {
        Nodes = null;
        size = 0;
    }
    /* Check if heap is empty */
    public boolean isEmpty()
    {
        return Nodes == null;
    }
    /* Function to get size */
    public int getSize()
    {
        return size;
    }
    /* clear heap */
    public void makeEmpty()
    {
        Nodes = null;
        size = 0;
    }
    /* Function to insert */        
    public void insert(int value) 
    {
        if (value > 0)
        {
            BinomialHeapNode temp = new BinomialHeapNode(value);
            if (Nodes == null) 
            {
                Nodes = temp;
                size = 1;
            } 
            else 
            {
                unionNodes(temp);
                size++;
            }
        }
    }
    /* Function to unite two binomial heaps */
    private void merge(BinomialHeapNode binHeap) 
    {
        BinomialHeapNode temp1 = Nodes, temp2 = binHeap;
 
        while ((temp1 != null) && (temp2 != null)) 
        {
            if (temp1.degree == temp2.degree) 
            {
                BinomialHeapNode tmp = temp2;
                temp2 = temp2.sibling;
                tmp.sibling = temp1.sibling;
                temp1.sibling = tmp;
                temp1 = tmp.sibling;
            } 
            else 
            {
                if (temp1.degree < temp2.degree) 
                {
                    if ((temp1.sibling == null) || (temp1.sibling.degree > temp2.degree)) 
                    {
                        BinomialHeapNode tmp = temp2;
                        temp2 = temp2.sibling;
                        tmp.sibling = temp1.sibling;
                        temp1.sibling = tmp;
                        temp1 = tmp.sibling;
                    }
                    else 
                    {
                        temp1 = temp1.sibling;
                    }
                }
                else 
                {
                    BinomialHeapNode tmp = temp1;
                    temp1 = temp2;
                    temp2 = temp2.sibling;
                    temp1.sibling = tmp;
                    if (tmp == Nodes) 
                    {
                        Nodes = temp1;
                    }
                    else 
                    {
 
                    }
                }
            }
        }
        if (temp1 == null) 
        {
            temp1 = Nodes;
            while (temp1.sibling != null) 
            {
                temp1 = temp1.sibling;
            }
            temp1.sibling = temp2;
        } 
        else
        {
 
        }
    }
    /* Function for union of nodes */
    private void unionNodes(BinomialHeapNode binHeap) 
    {
        merge(binHeap);
 
        BinomialHeapNode prevTemp = null, temp = Nodes, nextTemp = Nodes.sibling;
 
        while (nextTemp != null) 
        {
            if ((temp.degree != nextTemp.degree) || ((nextTemp.sibling != null) && (nextTemp.sibling.degree == temp.degree))) 
            {                
                prevTemp = temp;
                temp = nextTemp;
            } 
            else
            {
                if (temp.key <= nextTemp.key) 
                {
                    temp.sibling = nextTemp.sibling;
                    nextTemp.parent = temp;
                    nextTemp.sibling = temp.child;
                    temp.child = nextTemp;
                    temp.degree++;
                } 
                else 
                {
                    if (prevTemp == null) 
                    {
                        Nodes = nextTemp;
                    }
                    else 
                    {
                        prevTemp.sibling = nextTemp;
                    }
                    temp.parent = nextTemp;
                    temp.sibling = nextTemp.child;
                    nextTemp.child = temp;
                    nextTemp.degree++;
                    temp = nextTemp;
                }
            }
            nextTemp = temp.sibling;
        }
    }
    /* Function to return minimum key */
    public int findMinimum() 
    {
        return Nodes.findMinNode().key;
    }
    /* Function to delete a particular element */
    public void delete(int value) 
    {
        if ((Nodes != null) && (Nodes.findANodeWithKey(value) != null)) 
        {
            decreaseKeyValue(value, findMinimum() - 1);
            extractMin();
        }
    }
    /* Function to decrease key with a given value */
    public void decreaseKeyValue(int old_value, int new_value) 
    {
        BinomialHeapNode temp = Nodes.findANodeWithKey(old_value);
        if (temp == null)
            return;
        temp.key = new_value;
        BinomialHeapNode tempParent = temp.parent;
 
        while ((tempParent != null) && (temp.key < tempParent.key)) 
        {
            int z = temp.key;
            temp.key = tempParent.key;
            tempParent.key = z;
 
            temp = tempParent;
            tempParent = tempParent.parent;
        }
    }
    /* Function to extract the node with the minimum key */
    public int extractMin() 
    {
        if (Nodes == null)
            return -1;
 
        BinomialHeapNode temp = Nodes, prevTemp = null;
        BinomialHeapNode minNode = Nodes.findMinNode();
 
        while (temp.key != minNode.key) 
        {
            prevTemp = temp;
            temp = temp.sibling;
        }
 
        if (prevTemp == null) 
        {
            Nodes = temp.sibling;
        }
        else
        {
            prevTemp.sibling = temp.sibling;
        }
 
        temp = temp.child;
        BinomialHeapNode fakeNode = temp;
 
        while (temp != null) 
        {
            temp.parent = null;
            temp = temp.sibling;
        }
 
        if ((Nodes == null) && (fakeNode == null))
        {
            size = 0;
        } 
        else
        {
            if ((Nodes == null) && (fakeNode != null)) 
            {
                Nodes = fakeNode.reverse(null);
                size = Nodes.getSize();
            }
            else
            {
                if ((Nodes != null) && (fakeNode == null))
                {
                    size = Nodes.getSize();
                }
                else
                {
                    unionNodes(fakeNode.reverse(null));
                    size = Nodes.getSize();
                }
            }
        }
 
        return minNode.key;
    }
 
    /* Function to display heap */
    public void displayHeap()
    {
        System.out.print("\nHeap : ");
        displayHeap(Nodes);
        System.out.println("\n");
    }
    private void displayHeap(BinomialHeapNode r)
    {
        if (r != null)
        {
            displayHeap(r.child);
            System.out.print(r.key +" ");
            displayHeap(r.sibling);
        }
    }    
}    
 

参考:

https://zh.wikipedia.org/wiki/%E4%BA%8C%E9%A1%B9%E5%A0%86

https://www.sanfoundry.com/java-program-implement-binomial-heap/

https://www.youtube.com/watch?v=7UQd9SYUoNk

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、抽象数据类型定义如下: 本程序主要定义了两个类,一个用于创建节点,另一个用于创建二项堆。 class BinomialHeapNode { public: int key; //节点的关键字的值 int degree; //节点的度 BinomialHeapNode* sibling; //节点的右兄弟节点 BinomialHeapNode* child; //节点的最最孩子节点 BinomialHeapNode* father; //节点的双亲节点 BinomialHeapNode(int newkey) ; //构造函数,以关键字创建节点 BinomialHeapNode(); //重载构造函数,默认关键字为0 }; class BinomialHeap { public: typedef BinomialHeapNode node_t; private: static BinomialHeap heapMerge(BinomialHeap& heapA, BinomialHeap& heapB) ; //将两个二项堆按照根的度的递增顺序构成一个新的二项堆 static void nodeLink(node_t* child, node_t* father) ; //将两个节点连接成二项树 public: node_t* head; //二项堆的头节点 BinomialHeap(); //构造函数,头结点为0 { head = 0 } BinomialHeap(node_t& node) //构造函数,以一个节点进行构造 { head = &node; } BinomialHeap(node_t* node) //构造函数,以一个节点进行构造 { head = node; } BinomialHeap(const BinomialHeap& src) //构造函数,以一个二项堆进行构造 { head = src.head; } inline void insertNode(node_t& node) ; //在堆中插入一个节点 void insertNode(node_t* node) ; //在堆中插入一个节点 node_t* Find_Min(); //查找关键字值最小的节点 node_t* Extract_Min(); //查找并删除关键字值最小的节点 static BinomialHeap heapUnion(BinomialHeap& heapA, BinomialHeap& heapB) ; //合并两个二项堆 node_t*Findnode(int key) ; //查找关键字为key的节点 inline void swapkey(node_t* source,node_t*target ) ; //交换两个节点的关键字的值 void decreaseKey(int key,int newkey) ; //减小关键字为key的节点的值为newkey void traverse(); //遍历二项堆 void DeleteNode(int key) ; //删除关键字为key的节点 };

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值