算法导论学习笔记(13)——二项堆

来源:互联网 发布:8月份上海房产成交数据 编辑:程序博客网 时间:2024/04/30 22:41

一颗二项堆由一组二项树组成,二项树Bk是一种递归定义的有序树,

B[k]是由两棵B[k-1]二项树组成,其中一颗树是另外一颗树的子树。

下面

(b)是B0 - B4的二项树:

(a)表示二项树Bk的递归定义,三角形表示有根的子树

(c)以另一种方式来看二项树Bk

显然二项树具有如下的性质:

1. 对于树B[k]该树含有2^k个节点;

2.  树的高度为k;

3. 在深度为i中含有Cik节点,其中i = 0, 1,2 ... , k;

4.根的度数为k,它大于任何其他节点的度数;并且,如果根的子女从左到右编号为k-1,k-2,···,0.子女i是子树 Bi 的根。

定义完二项树之后,下面来定义二项堆H,二项堆是由一组满足下面的二项树组成:

1.  H中的每个二项树遵循最小堆性质;

2. 对于任意的整数k的话,在H不存在另外一个度数也是k的二项树;

另外定义:

1. 二项堆的度数定义成子女个数;

2. 定义二项堆的根表是二项树的根节点形成的链表;

好的,二项堆的定义完成之后,下面的问题就是我们在什么情况下使用“二项堆”?

如果是不支持所谓的合并操作union的话,普通的堆的数据结构就是一种很理想的数据结构。 但是如果想要支持集合上的合并操作的话,最好是使用二项堆或者是斐波那契堆,普通的堆在union操作上最差的情况是O(n),但是二项堆和斐波那契堆是O(lgn)。

 

二项堆中每个节点的类型:

1. parent:指向父节点

2. sibling:指向右边的兄弟节点

3. child:定义该节点的子节点

4. degree:定义该节点的度数

5. key: 定义关键字域

5. 其他应用场景中需要的卫星数据

typedef struct _bin_node {
struct _bin_node* parent;
struct _bin_node*  sibling;
struct _bin_node* child;
unsigned int degree;
        int key;

}BinNode,*pBinNode;

对于定义的字段,对于根表中的节点和非根表中的元素是不相同的,根表中的节点的parent全部是空,sibling指向的是根表中的下一个元素;对于非根表中的节点的话,parent指向的是该节点的父节点,sibling指向该节点的兄弟节点。

typedef pBinNode pBinHeap;//二项堆

//创建一个空的二项堆
pBinHeap CreateBinHeap()
{
 pBinHeap newHeap = (pBinHeap)malloc(sizeof(BinHeap)); 
 memset(newHeap, 0, sizeof(BinHeap)); 
 return newHeap;
}
//寻找最小关键字
pBinNode SearchMinKey(pBinHeap pHeap)

 pBinNode y = NULL; 
 pBinNode x = pHeap->pHead; 
 int min = MAX; 
 while(x) 
 {
  if (x->key<min)
  {
   min = x->key;
   y = x;
  }
  x = x->sibling;
 }
 return y;
}

//连接两个二项堆
void Link(pBinHeap pH1, pBinHeap pH2)
{
 pBinNode pH1Parent = pH1->parent;
 pH1->sibling = pH1Parent->child;
 pH1Parent->child = pH1;
 ++(pH1Parent->degree);
}

//将H1, H2的根表合并成一个按度数的单调递增次序排列的链表
pBinHeap Merge(pBinHeap pH1, pBinHeap pH2)
{   
 //heap->堆的首地址,H3为指向新堆根结点   
 pBinHeap heap = NULL, firstHeap = NULL, secondHeap = NULL, pre_H3 = NULL, H3 = NULL;
 if (pH1 != NULL && pH2 != NULL)
 {     
  firstHeap = pH1;
  secondHeap = pH2;
  //整个while,firstHeap, secondHeap, pre_H3, H3都在往后顺移       
  while (firstHeap != NULL && secondHeap != NULL)
  {          
   if (firstHeap->degree <= secondHeap->degree)
   {              
    H3 = firstHeap; 
    firstHeap = firstHeap->sibling;
   }
   else
   {  
    H3 = secondHeap;
    secondHeap = secondHeap->sibling; 
   }  

   if (pre_H3 == NULL)
   {            
    pre_H3 = H3;
    heap = H3; 
   }
   else
   {   
    pre_H3->sibling = H3;
    pre_H3 = H3;   
   }  

   if (firstHeap != NULL)
    H3->sibling = firstHeap;
   else
    H3->sibling = secondHeap;
  }//while   
 }
 else if (pH1 != NULL)
  heap = pH1;  
 else
  heap = pH2;
 pH1 = pH2 = NULL;
 return heap;
}

//合并两个二项堆
pBinHeap Union(pBinHeap pH1, pBinHeap pH2)
{
 pBinHeap pre_x = NULL, x = NULL, next_x = NULL;
 pBinHeap newH= CreateBinHeap();
 newH = Merge(pH1,pH2);
 if(newH == NULL) return newH;
 
 x = newH;
 next_x = x->sibling;

 while (next_x)
 {
  if (x->degree != next_x->degree || ( next_x->sibling != NULL && next_x->sibling->degree == x->degree))
  {
   pre_x = x;
   x = next_x;
  }
  else if (x->key <= next_x->key)
  {
   x->sibling = next_x->sibling;
   Link(next_x,x);
  }
  else
  {
   if (pre_x == NULL)
    newH = next_x;
   else
    pre_x->sibling = next_x;
   Link(x, next_x);
   x = next_x;
  }
  next_x = x->sibling;
 }
 return newH;
}

//插入一个节点到二项堆中
void Inerst(pBinHeap pH, BinNode node)
{
 pBinHeap newH = CreateBinHeap();
 node.parent = NULL;
 node.child = NULL;
 node.sibling = NULL;
 node.degree = 0;
 newH = &node;
 pH = Union(pH,newH);
}

//抽取有最小关键字的结点
pBinHeap ExtractMin(pBinHeap heap)
{  
 pBinHeap pre_y = NULL, y = NULL, x = heap;
 int min = INT_MAX;  
 while (x != NULL)
 {      
  if (x->key < min)
  {         
   min = x->key;
   pre_y = y;  
   y = x;     
  }      
  x = x->sibling;
 }   
 if (y == NULL)
 {      
  return NULL;
 }   
 if (pre_y == NULL)
 {      
  heap = heap->sibling;
 }
 else
 {  
  pre_y->sibling = y->sibling;
 }    
 //将y的子结点指针reverse 
 pBinHeap H2 = NULL, p = NULL;
 x = y->child;
 while (x != NULL)
 {     
  p = x;   
  x = x->sibling;
  p->sibling = H2;
  H2 = p;    
  p->parent = NULL;  
 }    
 heap = Union(heap, H2); 
 return y;
}

//减小关键字的值
void Decrease(pBinHeap pH, pBinNode x, int k)
{

 pBinNode y,z;
 if (k>x->key)
  return;
 x->key = k;
 y = x;
 z = y->parent;
 while (z && y->key<z->key)
 {
  int tem = y->key;
  y->key = z->key;
  z->key = tem;

  y = z;
  z = y->parent;
 }
}

//删除一个关键字
void Delete(pBinNode pH, pBinNode x)
{
 Decrease(pH,x,-MAX);
 ExtractMin(pH);

}

原创粉丝点击