【朱江的数据结构课堂】数据结构之二项队列

二项队列是一种特殊的树形数据结构,由多个二项树组成,每个二项树都满足特定的约束条件。这篇博客介绍了二项队列的概念、性质以及基本操作,包括查找最小项、合并二项树、插入和删除最小值。通过代码实现展示了如何高效地进行这些操作,特别是合并二项队列的switch语句设计巧妙。二项队列在数据结构和算法中有着重要的应用。
摘要由CSDN通过智能技术生成

二项队列

  1. 前序知识

    左式堆的各种操作,斜堆的各种操作

  2. 二项队列概念

    二项队列不是一颗堆序的数,而是堆序树的集合,成为森林。

    具有的性质:

    1. 每一棵树都是有约束的树,叫做二项树
    2. 高度为k的第k个二项树Bk由一个根节点和B0, B1, …B(k-1)构成。(k从0开始)
    3. 高度为k的二项树的结点个数为2^k

    我们可以将其理解为二进制的一个数组,从前往后看,例如1101,意义为我们有一颗高度为0的树(节点个数为20个),高度为1的树(节点个数21个),高度为3的树(节点个数2^3个)

  3. 二项队列的操作

    • 查找最小项
    • 合并两颗二项树
    • 插入一颗二项树
    • 删除最小
  4. 二项队列的代码实现

    • 队列申明

      typedef struct BinNode *Position;
      typedef struct BinNode *BinTree;
      typedef struct Collection *BinQueue;
      struct BinNode
      {
      	ElementType Element;//二项树元素类型
      	Position LeftChild;//最左边的孩子
      	Position Sibling;//兄弟节点
      };
      struct Collection//森林申明
      {
      	int CurrentSize;//数组大小
      	BinTree TheTrees[MaxTree];//定义二项队列长度
      }
      
    • 合并两棵二叉树

      这里对指针的大量运用,需要慢慢的理解体会

      合并同样大小的两颗二项树的例程

      BinTree CombineTree(BinTree T1,BinTree T2)
      {
      	if(T1->Element>T2->Element)
      		return CombineTree(T2,T1);
      	T2->Sibling = T1->LeftChild;
      	T1->LeftChild = T2;
      	return T1;
      }
      

      合并两个二项队列

      BinQueue Merge(BinQueue H1, BinQueue H2)
      {
      	BinTree T1, T2, Carry = NULL;
      	int i,j;
      	if(H1->CurrentSize+H2->CurrentSize>Capacity)
      		Error("Exceed the Capacity");
      	H1->CurrentSize = H1->CurrentSize + H2->CurrentSize;
      	for(i=0,j=1;j<H1->CurrentSize;i++,j*=2)
      	{
      		T1 = H1->TheTrees[i];
      		T2 = H2->TheTrees[i];
      		switch(!!T1+2*!!T2+4*!!Carry)
      		{
      			case 0: //No Trees
      			case 1: //Only H1
      				break; 
      			case 2: 
      				H1->TheTrees[i] = T2;
      				H2->TheTrees[i] = NULL;
      				break;
      			case 4: //Only Carry
      				H1->TheTrees[i] = Carry;
      				Carry = NULL;
      				break;
      			case 3: //T1,T2
      				Carry = CombineTree(T1,T2);
      				H1->TheTrees[i] = H2->TheTrees[i] = NULL;
      				break;
      			case 5:
      				Carry = CombineTree(T1,Carry);
      				H1->TheTrees[i] = NULL;
      				break;
      			case 6:
      				Carry = CombineTree(T2,Carry);
      				H2->TheTrees[i] = NULL;
      				break;
      			case 7:
      				H1->TheTrees[i] = Carry;
      				Carry = CombineTree(T1,T2);
      				H2->TheTrees[i] = NULL;
      				break;
      		}
      	}
      	return H1;
      }
      

      switch语句真的牛逼,这一段我看了半天才搞明白到底是怎么一回事!!!建议细细品味

      删除最小值

      ElementType DeleteMin(BinQueue H)
      {
      	int i,j;
      	int MinTree;
      	BinQueue DeleteQueue;
      	Position DeletedTree, OldRoot;
      	ElementType MinItem;
       
      	if(IsEmpty(H))
      	{
      		Error("Empty BinQueue!!");
      		return -Infinity;
      	}
      	//find the minmum
      	Min = Infinity;
      	for(i=0;i<MaxTree;i++)
      	{
      		if(H->TheTrees[i] && H->TheTrees[i]->Element<MinItem)
      		{
      			// Updata the minmun
      			MiniItem = H->TheTrees[i]->Element;
      			MinTree = i;
      		}
      	}
      	// have found the DeleteTree
      	DeleteTree = H->TheTrees[MinTree];
      	OldRoot = DeleteTree;
      	DeleteTree = OldRoot->LeftChild;
      	free(OldRoot);
       
      	// form the DeleteQueue
      	DeletedQueue = Initialize();
      	DeletedQueue->CurrentSize = (1<<MinTree) - 1;
       
      	for(j=MinTree-1;j>=0;j--)
      	{
      		DeletedQueue->TheTree[j] = DeletedTree;
      		DeletedTree = DeletedTree->Sibling;
      		DeletedQueue->TheTree[j]->Sibling = NULL;
      	}
      	H->TheTrees[MiniTree] = NULL;
      	H->CurrentSize -= DeletedQueue->CurrentSize+1;
       
      	Merge(H,DeletedQueue);
      	return MinItem;
       
      }
      

参考资料:《数据结构与算法分析》以及b站视频[]: https://www.bilibili.com/video/BV1fC4y1h7CT?spm_id_from=333.337.search-card.all.click

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值