左偏樹的c++實現

來源:互聯網
上載者:User

/*<br />與平衡樹不同(平衡樹是具有非常小的深度的,這也意味著到達任何一個節點所經過的邊數很少),左偏樹並不是為了<br />快速存取所有的節點而設計的,它的目的是快速存取最小節點以及在對樹修改後快速的恢複堆性質。<br />左偏樹是一種可合并堆,常用於優先順序隊列。</p><p>左偏樹有兩個性質:<br />1)堆的性質(注意:一般堆是完全二叉樹,但這裡不是):<br />A[parent(i)]>=A[i] or A[parent(i)]<=A[i],即父節點大於(或者小於)子節點的值(這個“值”可以看成Key或者優先順序)。</p><p>2)左偏性質:<br />節點的左子節點的距離不小於右子節點的距離,即dist(left(i))≥dist(right(i)) 。<br />其中節點的距離等於它的右子節點的距離加1,即 dist(i) = dist( right(i) ) + 1 ;如果一個節點的右子節點為空白節點,<br />則其距離為0;為了滿足性質,故規定空節點的距離為-1。</p><p>這裡左偏樹提供一下功能:<br />1)插入節點Insert, 時間複雜度O(logn)<br />2)獲得根節點(即最小節點(如果是最小堆)或者最大節點(如果是最大堆)),時間複雜度O(1)<br />3)刪除根節點DeleteRoot,時間複雜度O(logn)<br />4)合并兩個左偏樹Merge,時間複雜度O(logn)<br />*/<br />#include <iostream><br />#include <functional><br />#include <cassert><br />using namespace std;</p><p>//節點資料結構<br />template<class Type><br />struct Node<br />{<br /> Type data;//資料<br /> int dist;//距離<br /> Node<Type> *left;//左兒子指標<br /> Node<Type> *right;//右兒子指標</p><p>Node(Type val)<br />{<br />data = val;<br />dist = 0;<br />left = right = NULL;<br />}</p><p> ~Node()<br />{<br />}<br />};</p><p>//左偏樹<br />template <class Type,class Compare = less<Type>/*預設是小堆*/ ><br />class LeftistTree<br />{<br />private:<br /> Node<Type> *root;</p><p> //刪除以指定節點為根的左偏樹<br />void Delete(Node<Type> *node)<br />{<br />if(NULL != node)<br />{<br />Delete(node->left);<br />Delete(node->right);<br />delete node;<br />//node = NULL;<br />}<br />}</p><p>//判斷指定節點是否有左兒子<br />//static bool HasLeft(Node<Type>* node)<br />//{<br />//if(!node) return false;//空節點沒有左兒子<br />//return node->left;<br />//}</p><p>//擷取指定節點的左兒子<br />static Node<Type>*& Left(Node<Type>*& node)<br />{<br />assert(NULL != node);<br />return node->left;<br />}</p><p>//判斷指定節點是否有右兒子<br />//static bool HasRight(Node<Type>* node)<br />//{<br />//if(!node) return false;//空節點沒有右兒子<br />//return node->right;<br />//}</p><p>//擷取指定節點的右兒子<br />static Node<Type>*& Right(Node<Type>*& node)<br />{<br />assert(NULL != node);<br />return node->right;<br />}</p><p>//擷取指定節點的距離<br />static int Dist(Node<Type>* node)<br />{<br />if(NULL == node) return -1;//規定空節點的距離為-1<br />return node->dist;<br />}</p><p>//交換left指標與right指標<br />static void Swap(Node<Type>*& left,Node<Type>*& right)<br />{<br />Node<Type> *temp = left;<br />left = right;<br />right = temp;<br />}</p><p>//合并兩顆左偏樹(返回合并之後左偏樹的根結點)<br />static Node<Type>*& Merge(Node<Type>*& t1, Node<Type>*& t2)<br />{</p><p>if(NULL == t1)<br />return t2;<br />else if(NULL == t2)<br />return t1;</p><p>//確定t1,t2兩個節點誰作為合并後的根節點,以滿足左偏樹的堆的性質(A[parent(i)]>=A[i] or A[parent(i)]<=A[i])。<br /> //但這裡的“堆”未必是完全二叉樹<br />//注意是個遞迴過程<br />if( Compare()(t2->data, t1->data) ) //Compare是比較規則,它確定堆是大堆還是小堆<br />Swap(t1,t2);<br />Right(t1) = Merge(Right(t1), t2);</p><p>//為左右兒子排序,以滿足左偏樹的左偏性質,即節點的左子節點的距離不小於右子節點的距離<br />if( Dist(Right(t1)) > Dist(Left(t1)) )<br />Swap( Left(t1),Right(t1) );<br />//調整距離<br />if( NULL == Right(t1) )<br />t1->dist = 0;<br />else t1->dist = Dist(Right(t1)) + 1;</p><p>return t1;<br />}</p><p> //輸出以指定節點為根的左偏樹(遞迴方式的先序遍曆)<br />void Print(Node<Type> *node)<br />{<br />if(NULL != node)<br />{</p><p>cout << node->data <<endl;</p><p>cout<<"節點"<<node->data<<"的左兒子為:";<br />if(NULL != node->left)<br />Print(node->left);<br />else<br />cout<<"NULL";<br />cout<<endl;</p><p>cout<<"節點"<<node->data<<"的右兒子為:";<br />if(NULL != node->right)<br />Print(node->right);<br />else<br />cout<<"NULL";<br />cout<<endl;<br />}<br />}<br />public:</p><p>LeftistTree(): root(NULL)<br />{<br />}</p><p> ~LeftistTree()<br />{<br />Delete(root);<br />}</p><p> //向左偏樹插入元素<br /> void Insert(Type val)<br />{<br />Node<Type> *newNode;<br />newNode = new Node<Type>(val);<br />root = Merge(root, newNode);<br />}</p><p> //刪除左偏樹的根結點<br />void DeleteRoot()<br />{<br />if(NULL == root)<br />{<br />cout << "警告:左偏樹為空白" << endl;<br />return;<br />}<br />Node<Type> *p = root;<br />root = Merge(p->left, p->right);<br />delete p;<br />}</p><p> //合并兩棵左偏樹<br />//合并後t2就為空白樹了。<br /> void Merge(LeftistTree<Type,Compare>& t2)<br />{<br />root = Merge(root, t2.root);<br />t2.root = NULL;<br />}</p><p> //擷取根結點的值(相當於優先順序)<br />Type Root()<br />{<br />if(NULL == root)<br />{<br />cout << "左偏樹為空白" << endl;<br />return NULL;<br />}<br />return root->data;<br />}</p><p> //輸出整棵左偏樹中的元素<br />void Print()<br />{<br />Print(root);<br />cout << endl;<br />}<br />};</p><p>int main()<br />{<br />//建立小堆的左偏樹<br />{<br /> LeftistTree<double> tree;<br /> tree.Insert(5);<br /> tree.Insert(4);<br />tree.Insert(3);<br /> tree.Insert(8);<br /> tree.Insert(1);<br /> tree.Insert(2);<br /> tree.Insert(9);<br /> tree.Insert(7);<br /> tree.Insert(6);<br />tree.Insert(0);<br />cout<< "第一顆左偏樹:" << endl;<br />tree.Print();</p><p> tree.DeleteRoot();<br />tree.DeleteRoot();<br />cout<< "新的左偏樹:" << endl;<br /> tree.Print();</p><p> cout <<"新的左偏樹的根節點:"<< tree.Root() << endl;</p><p> LeftistTree<double> tr;<br /> tr.Insert(4.3);<br /> tr.Insert(9.6);<br /> tr.Insert(5.5);<br /> tr.Insert(6.6);</p><p>cout<<"第二顆左偏樹:"<<endl;<br /> tr.Print();<br /> cout <<"第二顆左偏樹的根節點:"<<tr.Root() << endl;</p><p> tree.Merge(tr);<br />cout <<"合并後的左偏樹為:" << endl;<br /> tree.Print();<br />}</p><p> cout<<"-----------------------------------"<<endl;</p><p>//建立大堆的左偏樹<br />{<br /> LeftistTree< double, greater<double> > tree2;<br /> tree2.Insert(5);<br /> tree2.Insert(4);<br />tree2.Insert(3);<br /> tree2.Insert(8);<br /> tree2.Insert(1);<br /> tree2.Insert(2);<br /> tree2.Insert(9);<br /> tree2.Insert(7);<br /> tree2.Insert(6);<br />tree2.Insert(0);<br />cout<< "第一顆左偏樹:" << endl;<br />tree2.Print();</p><p> tree2.DeleteRoot();<br />tree2.DeleteRoot();<br />cout<< "新的左偏樹:" << endl;<br /> tree2.Print();</p><p> cout <<"新的左偏樹的根節點:"<< tree2.Root() << endl;</p><p> LeftistTree< double, greater<double> > tr2;<br /> tr2.Insert(4.3);<br /> tr2.Insert(9.6);<br /> tr2.Insert(5.5);<br /> tr2.Insert(6.6);</p><p>cout<<"第二顆左偏樹:"<<endl;<br /> tr2.Print();<br /> cout <<"第二顆左偏樹的根節點:"<<tr2.Root() << endl;</p><p> tree2.Merge(tr2);<br />cout <<"合并後的左偏樹為:" << endl;<br /> tree2.Print();<br />}</p><p> return 0;<br />}

 

參考文獻:

http://www.docin.com/p-1775556.html

http://www.ozobo.cn/?p=78

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.