1. 程式人生 > >數據結構--左式堆的思想和代碼

數據結構--左式堆的思想和代碼

child 靈魂 init esp 每一個 all 短路徑 out single

左式堆也是實現優先列隊的一種數據結構,和二叉堆一樣,左式堆也具有堆序性和結構性。

堆序性: 一個節點的後裔都大於等於這個節點。

結構性:左式堆也是二叉樹,和二叉堆的唯一區別在於左式堆不是理想平衡的,實際上是趨於非常不平衡,對於堆中每一個節點X,左兒子的零路徑長至少與右兒子的零路徑長一樣大,零路徑長Npl的定義為:節點到一個沒有兩個兒子的節點的最短路徑長,因此具有0個或者1個兒子節點的Npl為0,Npl(NULL) = -1。

左式堆可以高效的支持合並操作,而插入和刪除操作都可以通過合並操作來實現,相關的代碼如下:

#include<iostream>

using namespace std;

struct TreeNode;
typedef struct TreeNode *PriorityQueue;

PriorityQueue Init(void);
int FindMin(PriorityQueue H);
bool IsEmpty (PriorityQueue H);
PriorityQueue Merge(PriorityQueue H1,PriorityQueue H2);  //合並操作

#define Insert(x,H) (H = Insert1(x,H))

PriorityQueue Insert1 (int x,PriorityQueue H);
PriorityQueue DeleteMin1(PriorityQueue H);

struct TreeNode
{
   int Element;
   PriorityQueue Left;
   PriorityQueue Right;
   int Npl;   //零路徑長,節點X到一個沒有兩個兒子的節點的最短路徑的長
};

static void SwapChildren (PriorityQueue H)   //交換根節點的左右子樹
{
  PriorityQueue temp;
  temp = H->Right;
  H->Right = H->Left;
  H->Left = temp;
}
static PriorityQueue Merge1(PriorityQueue H1,PriorityQueue H2)
{
   if(H1->Left == NULL)  //H1為單點,就一個元素
	   H1->Left = H2;
   else
   {
      H1->Right = Merge(H1->Right,H2);
	  if(H1->Left->Npl < H1->Right->Npl)
		  SwapChildren(H1);
	  H1->Npl = H1->Right->Npl + 1;
   }
   return H1;
}

PriorityQueue Merge(PriorityQueue H1,PriorityQueue H2)     //處理特殊情況 
{
   if(H1 == NULL)
	   return H2;
   if(H2 == NULL)
	   return H1;
   if(H1->Element < H2->Element )
	   return Merge1(H1,H2);
   else
	   return Merge1(H2,H1);
}


PriorityQueue Insert1(int x,PriorityQueue H)   //把x看成但節點,執行合並操作,思想很巧妙
{
   PriorityQueue SingleNode;
   SingleNode = (PriorityQueue)malloc(sizeof(struct TreeNode));
   if(SingleNode == NULL) cout << "out of space" << endl;
   else
   {
      SingleNode->Element = x;
	  SingleNode->Left = NULL;
	  SingleNode->Npl = 0;
	  SingleNode->Right = NULL;
	  H = Merge(SingleNode, H);
   }
   return H;
}

bool IsEmpty(PriorityQueue H)
{
     if(H == NULL)
		 return true;
	 else
		 return false;
}

PriorityQueue DeleteMin(PriorityQueue H)    //刪除操作,因為左式堆的堆序性,最小值就在根處,因此刪除操作直接就是把根的左子樹和右子樹合並即可
{
   PriorityQueue LeftHeap,RightHeap;
   if(IsEmpty(H))
   {
      cout << "Priority queue is Empty" << endl;
	  return H;
   }
   LeftHeap = H->Left;
   RightHeap = H->Right;
   free(H);
   return Merge(LeftHeap,RightHeap);
}

int main ()
{


   return 0;
}

   插入和刪除操作都可以通過合並操作來實現,這種思想很巧妙,值得我們學習。

夜深了,,,

網易雲的歌單循環到了《願得一人心》這首鋼琴曲,音樂都是有靈魂的,只願得一人心,白首不分離。

數據結構--左式堆的思想和代碼