首页 > 代码库 > 【数据结构】左式堆
【数据结构】左式堆
复杂度:
实现:
1 #ifndef LEFTIST_HEAP_H 2 #define LEFTIST_HEAP_H 3 4 #include "dsexceptions.h" 5 #include <iostream> 6 using namespace std; 7 8 // Leftist heap class 9 // 10 // CONSTRUCTION: with no parameters 11 // 12 // ******************PUBLIC OPERATIONS********************* 13 // void insert( x ) --> Insert x 14 // deleteMin( minItem ) --> Remove (and optionally return) smallest item 15 // Comparable findMin( ) --> Return smallest item 16 // bool isEmpty( ) --> Return true if empty; else false 17 // void makeEmpty( ) --> Remove all items 18 // void merge( rhs ) --> Absorb rhs into this heap 19 // ******************ERRORS******************************** 20 // Throws UnderflowException as warranted 21 22 template <typename Comparable> 23 class LeftistHeap 24 { 25 public: 26 LeftistHeap( ) : root{ nullptr } 27 { } 28 LeftistHeap( const LeftistHeap & rhs ) : root{ nullptr } 29 { root = clone( rhs.root ); } 30 31 LeftistHeap( LeftistHeap && rhs ) : root{ rhs.root } 32 { 33 rhs.root = nullptr; 34 } 35 36 ~LeftistHeap( ) 37 { makeEmpty( ); } 38 39 40 /** 41 * Deep copy. 42 */ 43 LeftistHeap & operator=( const LeftistHeap & rhs ) 44 { 45 LeftistHeap copy = rhs; 46 std::swap( *this, copy ); 47 return *this; 48 } 49 50 /** 51 * Move. 52 */ 53 LeftistHeap & operator=( LeftistHeap && rhs ) 54 { 55 std::swap( root, rhs.root ); 56 57 return *this; 58 } 59 60 /** 61 * Returns true if empty, false otherwise. 62 */ 63 bool isEmpty( ) const 64 { return root == nullptr; } 65 66 /** 67 * Find the smallest item in the priority queue. 68 * Return the smallest item, or throw Underflow if empty. 69 */ 70 const Comparable & findMin( ) const 71 { 72 if( isEmpty( ) ) 73 throw UnderflowException{ }; 74 return root->element; 75 } 76 77 /** 78 * Inserts x; duplicates allowed. 79 */ 80 void insert( const Comparable & x ) 81 { root = merge( new LeftistNode{ x }, root ); } 82 83 /** 84 * Inserts x; duplicates allowed. 85 */ 86 void insert( Comparable && x ) 87 { root = merge( new LeftistNode{ std::move( x ) }, root ); } 88 89 /** 90 * Remove the minimum item. 91 * Throws UnderflowException if empty. 92 */ 93 void deleteMin( ) 94 { 95 if( isEmpty( ) ) 96 throw UnderflowException{ }; 97 98 LeftistNode *oldRoot = root; 99 root = merge( root->left, root->right );100 delete oldRoot;101 }102 103 /**104 * Remove the minimum item and place it in minItem.105 * Throws UnderflowException if empty.106 */107 void deleteMin( Comparable & minItem )108 {109 minItem = findMin( );110 deleteMin( );111 }112 113 /**114 * Make the priority queue logically empty.115 */116 void makeEmpty( )117 {118 reclaimMemory( root );119 root = nullptr;120 }121 122 /**123 * Merge rhs into the priority queue.124 * rhs becomes empty. rhs must be different from this.125 */126 void merge( LeftistHeap & rhs )127 {128 if( this == &rhs ) // Avoid aliasing problems129 return;130 131 root = merge( root, rhs.root );132 rhs.root = nullptr;133 }134 135 136 private:137 struct LeftistNode138 {139 Comparable element;140 LeftistNode *left;141 LeftistNode *right;142 int npl;143 144 LeftistNode( const Comparable & e, LeftistNode *lt = nullptr,145 LeftistNode *rt = nullptr, int np = 0 )146 : element{ e }, left{ lt }, right{ rt }, npl{ np } { }147 148 LeftistNode( Comparable && e, LeftistNode *lt = nullptr,149 LeftistNode *rt = nullptr, int np = 0 )150 : element{ std::move( e ) }, left{ lt }, right{ rt }, npl{ np } { }151 };152 153 LeftistNode *root;154 155 /**156 * Internal method to merge two roots.157 * Deals with deviant cases and calls recursive merge1.158 */159 LeftistNode * merge( LeftistNode *h1, LeftistNode *h2 )160 {161 if( h1 == nullptr )162 return h2;163 if( h2 == nullptr )164 return h1;165 if( h1->element < h2->element )166 return merge1( h1, h2 );167 else168 return merge1( h2, h1 );169 }170 171 /**172 * Internal method to merge two roots.173 * Assumes trees are not empty, and h1‘s root contains smallest item.174 */175 LeftistNode * merge1( LeftistNode *h1, LeftistNode *h2 )176 {177 if( h1->left == nullptr ) // Single node178 h1->left = h2; // Other fields in h1 already accurate179 else180 {181 h1->right = merge( h1->right, h2 );182 if( h1->left->npl < h1->right->npl )183 swapChildren( h1 );184 h1->npl = h1->right->npl + 1;185 }186 return h1;187 }188 189 /**190 * Swaps t‘s two children.191 */192 void swapChildren( LeftistNode *t )193 {194 LeftistNode *tmp = t->left;195 t->left = t->right;196 t->right = tmp;197 }198 199 /**200 * Internal method to make the tree empty.201 * WARNING: This is prone to running out of stack space;202 * exercises suggest a solution.203 */204 void reclaimMemory( LeftistNode *t )205 {206 if( t != nullptr )207 {208 reclaimMemory( t->left );209 reclaimMemory( t->right );210 delete t;211 }212 }213 214 /**215 * Internal method to clone subtree.216 * WARNING: This is prone to running out of stack space.217 * exercises suggest a solution.218 */219 LeftistNode * clone( LeftistNode *t ) const220 {221 if( t == nullptr )222 return nullptr;223 else224 return new LeftistNode{ t->element, clone( t->left ), clone( t->right ), t->npl };225 }226 };227 228 #endif
应用:
1 #include "LeftistHeap.h" 2 #include <iostream> 3 using namespace std; 4 5 int main( ) 6 { 7 int numItems = 10000; 8 LeftistHeap<int> h; 9 LeftistHeap<int> h1;10 LeftistHeap<int> h2;11 int i = 37;12 13 cout << "Begin test..." << endl;14 for( i = 37; i != 0; i = ( i + 37 ) % numItems )15 if( i % 2 == 0 )16 h1.insert( i );17 else18 h.insert( i );19 h.merge( h1 );20 h2 = h;21 22 for( i = 1; i < numItems; ++i )23 {24 int x;25 h2.deleteMin( x );26 if( x != i )27 cout << "Oops! " << i << endl;28 }29 30 if( !h1.isEmpty( ) )31 cout << "Oops! h1 should have been empty!" << endl;32 33 cout << "End test... no other output is good" << endl;34 35 return 0;36 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。