Implementácia binomickej haldy
In predchádzajúci článok diskutovali sme o konceptoch súvisiacich s binomickou haldou.
Príklady binomickej haldy:
12------------10--------------------20
/ / |
15 50 70 50 40
| / | |
30 80 85 65
|
100
A Binomial Heap with 13 nodes. It is a collection of 3
Binomial Trees of orders 0 2 and 3 from left to right.
10--------------------20
/ / |
15 50 70 50 40
| / | |
30 80 85 65
|
100V tomto článku sa diskutuje o implementácii binomickej haldy. Nasledujúce funkcie implementované:
- vložiť(Hk): Vloží kľúč „k“ do binomickej haldy „H“. Táto operácia najprv vytvorí binomickú haldu s jedným kľúčom „k“, potom zavolá spojenie na H a novú binomickú haldu.
- getMin(H): Jednoduchým spôsobom getMin() je prejsť zoznam koreňov binomických stromov a vrátiť minimálny kľúč. Táto implementácia vyžaduje čas O(Logn). Môže byť optimalizovaný na O(1) udržiavaním ukazovateľa na minimálny kľúčový koreň.
- extraktMin(H): Táto operácia tiež používa union(). Najprv zavoláme getMin(), aby sme našli minimálny kľúčový binomický strom, potom odstránime uzol a vytvoríme novú binomickú haldu spojením všetkých podstromov odstráneného minimálneho uzla. Nakoniec zavoláme union() na H a novovytvorenú binomickú haldu. Táto operácia vyžaduje čas O(Logn).
Implementácia:
CPPJava// C++ program to implement different operations // on Binomial Heap #includeusing namespace std ; // A Binomial Tree node. struct Node { int data degree ; Node * child * sibling * parent ; }; Node * newNode ( int key ) { Node * temp = new Node ; temp -> data = key ; temp -> degree = 0 ; temp -> child = temp -> parent = temp -> sibling = NULL ; return temp ; } // This function merge two Binomial Trees. Node * mergeBinomialTrees ( Node * b1 Node * b2 ) { // Make sure b1 is smaller if ( b1 -> data > b2 -> data ) swap ( b1 b2 ); // We basically make larger valued tree // a child of smaller valued tree b2 -> parent = b1 ; b2 -> sibling = b1 -> child ; b1 -> child = b2 ; b1 -> degree ++ ; return b1 ; } // This function perform union operation on two // binomial heap i.e. l1 & l2 list < Node *> unionBionomialHeap ( list < Node *> l1 list < Node *> l2 ) { // _new to another binomial heap which contain // new heap after merging l1 & l2 list < Node *> _new ; list < Node *>:: iterator it = l1 . begin (); list < Node *>:: iterator ot = l2 . begin (); while ( it != l1 . end () && ot != l2 . end ()) { // if D(l1) <= D(l2) if (( * it ) -> degree <= ( * ot ) -> degree ) { _new . push_back ( * it ); it ++ ; } // if D(l1) > D(l2) else { _new . push_back ( * ot ); ot ++ ; } } // if there remains some elements in l1 // binomial heap while ( it != l1 . end ()) { _new . push_back ( * it ); it ++ ; } // if there remains some elements in l2 // binomial heap while ( ot != l2 . end ()) { _new . push_back ( * ot ); ot ++ ; } return _new ; } // adjust function rearranges the heap so that // heap is in increasing order of degree and // no two binomial trees have same degree in this heap list < Node *> adjust ( list < Node *> _heap ) { if ( _heap . size () <= 1 ) return _heap ; list < Node *> new_heap ; list < Node *>:: iterator it1 it2 it3 ; it1 = it2 = it3 = _heap . begin (); if ( _heap . size () == 2 ) { it2 = it1 ; it2 ++ ; it3 = _heap . end (); } else { it2 ++ ; it3 = it2 ; it3 ++ ; } while ( it1 != _heap . end ()) { // if only one element remains to be processed if ( it2 == _heap . end ()) it1 ++ ; // If D(it1) < D(it2) i.e. merging of Binomial // Tree pointed by it1 & it2 is not possible // then move next in heap else if (( * it1 ) -> degree < ( * it2 ) -> degree ) { it1 ++ ; it2 ++ ; if ( it3 != _heap . end ()) it3 ++ ; } // if D(it1)D(it2) & D(it3) are same i.e. // degree of three consecutive Binomial Tree are same // in heap else if ( it3 != _heap . end () && ( * it1 ) -> degree == ( * it2 ) -> degree && ( * it1 ) -> degree == ( * it3 ) -> degree ) { it1 ++ ; it2 ++ ; it3 ++ ; } // if degree of two Binomial Tree are same in heap else if (( * it1 ) -> degree == ( * it2 ) -> degree ) { Node * temp ; * it1 = mergeBinomialTrees ( * it1 * it2 ); it2 = _heap . erase ( it2 ); if ( it3 != _heap . end ()) it3 ++ ; } } return _heap ; } // inserting a Binomial Tree into binomial heap list < Node *> insertATreeInHeap ( list < Node *> _heap Node * tree ) { // creating a new heap i.e temp list < Node *> temp ; // inserting Binomial Tree into heap temp . push_back ( tree ); // perform union operation to finally insert // Binomial Tree in original heap temp = unionBionomialHeap ( _heap temp ); return adjust ( temp ); } // removing minimum key element from binomial heap // this function take Binomial Tree as input and return // binomial heap after // removing head of that tree i.e. minimum element list < Node *> removeMinFromTreeReturnBHeap ( Node * tree ) { list < Node *> heap ; Node * temp = tree -> child ; Node * lo ; // making a binomial heap from Binomial Tree while ( temp ) { lo = temp ; temp = temp -> sibling ; lo -> sibling = NULL ; heap . push_front ( lo ); } return heap ; } // inserting a key into the binomial heap list < Node *> insert ( list < Node *> _head int key ) { Node * temp = newNode ( key ); return insertATreeInHeap ( _head temp ); } // return pointer of minimum value Node // present in the binomial heap Node * getMin ( list < Node *> _heap ) { list < Node *>:: iterator it = _heap . begin (); Node * temp = * it ; while ( it != _heap . end ()) { if (( * it ) -> data < temp -> data ) temp = * it ; it ++ ; } return temp ; } list < Node *> extractMin ( list < Node *> _heap ) { list < Node *> new_heap lo ; Node * temp ; // temp contains the pointer of minimum value // element in heap temp = getMin ( _heap ); list < Node *>:: iterator it ; it = _heap . begin (); while ( it != _heap . end ()) { if ( * it != temp ) { // inserting all Binomial Tree into new // binomial heap except the Binomial Tree // contains minimum element new_heap . push_back ( * it ); } it ++ ; } lo = removeMinFromTreeReturnBHeap ( temp ); new_heap = unionBionomialHeap ( new_heap lo ); new_heap = adjust ( new_heap ); return new_heap ; } // print function for Binomial Tree void printTree ( Node * h ) { while ( h ) { cout < < h -> data < < ' ' ; printTree ( h -> child ); h = h -> sibling ; } } // print function for binomial heap void printHeap ( list < Node *> _heap ) { list < Node *> :: iterator it ; it = _heap . begin (); while ( it != _heap . end ()) { printTree ( * it ); it ++ ; } } // Driver program to test above functions int main () { int ch key ; list < Node *> _heap ; // Insert data in the heap _heap = insert ( _heap 10 ); _heap = insert ( _heap 20 ); _heap = insert ( _heap 30 ); cout < < 'Heap elements after insertion: n ' ; printHeap ( _heap ); Node * temp = getMin ( _heap ); cout < < ' n Minimum element of heap ' < < temp -> data < < ' n ' ; // Delete minimum element of heap _heap = extractMin ( _heap ); cout < < 'Heap after deletion of minimum element n ' ; printHeap ( _heap ); return 0 ; } Python3// Java Program to Implement Binomial Heap // Importing required classes import java.io.* ; // Class 1 // BinomialHeapNode class BinomialHeapNode { int key degree ; BinomialHeapNode parent ; BinomialHeapNode sibling ; BinomialHeapNode child ; // Constructor of this class public BinomialHeapNode ( int k ) { key = k ; degree = 0 ; parent = null ; sibling = null ; child = null ; } // Method 1 // To reverse public BinomialHeapNode reverse ( BinomialHeapNode sibl ) { BinomialHeapNode ret ; if ( sibling != null ) ret = sibling . reverse ( this ); else ret = this ; sibling = sibl ; return ret ; } // Method 2 // To find minimum node public BinomialHeapNode findMinNode () { // this keyword refers to current instance itself BinomialHeapNode x = this y = this ; int min = x . key ; while ( x != null ) { if ( x . key < min ) { y = x ; min = x . key ; } x = x . sibling ; } return y ; } // Method 3 // To find node with key value public BinomialHeapNode findANodeWithKey ( int value ) { BinomialHeapNode temp = this node = null ; while ( temp != null ) { if ( temp . key == value ) { node = temp ; break ; } if ( temp . child == null ) temp = temp . sibling ; else { node = temp . child . findANodeWithKey ( value ); if ( node == null ) temp = temp . sibling ; else break ; } } return node ; } // Method 4 // To get the size public int getSize () { return ( 1 + (( child == null ) ? 0 : child . getSize ()) + (( sibling == null ) ? 0 : sibling . getSize ())); } } // Class 2 // BinomialHeap class BinomialHeap { // Member variables of this class private BinomialHeapNode Nodes ; private int size ; // Constructor of this class public BinomialHeap () { Nodes = null ; size = 0 ; } // Checking if heap is empty public boolean isEmpty () { return Nodes == null ; } // Method 1 // To get the size public int getSize () { return size ; } // Method 2 // Clear heap public void makeEmpty () { Nodes = null ; size = 0 ; } // Method 3 // To insert public void insert ( int value ) { if ( value > 0 ) { BinomialHeapNode temp = new BinomialHeapNode ( value ); if ( Nodes == null ) { Nodes = temp ; size = 1 ; } else { unionNodes ( temp ); size ++ ; } } } // Method 4 // To unite two binomial heaps private void merge ( BinomialHeapNode binHeap ) { BinomialHeapNode temp1 = Nodes temp2 = binHeap ; while (( temp1 != null ) && ( temp2 != null )) { if ( temp1 . degree == temp2 . degree ) { BinomialHeapNode tmp = temp2 ; temp2 = temp2 . sibling ; tmp . sibling = temp1 . sibling ; temp1 . sibling = tmp ; temp1 = tmp . sibling ; } else { if ( temp1 . degree < temp2 . degree ) { if (( temp1 . sibling == null ) || ( temp1 . sibling . degree > temp2 . degree )) { BinomialHeapNode tmp = temp2 ; temp2 = temp2 . sibling ; tmp . sibling = temp1 . sibling ; temp1 . sibling = tmp ; temp1 = tmp . sibling ; } else { temp1 = temp1 . sibling ; } } else { BinomialHeapNode tmp = temp1 ; temp1 = temp2 ; temp2 = temp2 . sibling ; temp1 . sibling = tmp ; if ( tmp == Nodes ) { Nodes = temp1 ; } else { } } } } if ( temp1 == null ) { temp1 = Nodes ; while ( temp1 . sibling != null ) { temp1 = temp1 . sibling ; } temp1 . sibling = temp2 ; } else { } } // Method 5 // For union of nodes private void unionNodes ( BinomialHeapNode binHeap ) { merge ( binHeap ); BinomialHeapNode prevTemp = null temp = Nodes nextTemp = Nodes . sibling ; while ( nextTemp != null ) { if (( temp . degree != nextTemp . degree ) || (( nextTemp . sibling != null ) && ( nextTemp . sibling . degree == temp . degree ))) { prevTemp = temp ; temp = nextTemp ; } else { if ( temp . key <= nextTemp . key ) { temp . sibling = nextTemp . sibling ; nextTemp . parent = temp ; nextTemp . sibling = temp . child ; temp . child = nextTemp ; temp . degree ++ ; } else { if ( prevTemp == null ) { Nodes = nextTemp ; } else { prevTemp . sibling = nextTemp ; } temp . parent = nextTemp ; temp . sibling = nextTemp . child ; nextTemp . child = temp ; nextTemp . degree ++ ; temp = nextTemp ; } } nextTemp = temp . sibling ; } } // Method 6 // To return minimum key public int findMinimum () { return Nodes . findMinNode (). key ; } // Method 7 // To delete a particular element */ public void delete ( int value ) { if (( Nodes != null ) && ( Nodes . findANodeWithKey ( value ) != null )) { decreaseKeyValue ( value findMinimum () - 1 ); extractMin (); } } // Method 8 // To decrease key with a given value */ public void decreaseKeyValue ( int old_value int new_value ) { BinomialHeapNode temp = Nodes . findANodeWithKey ( old_value ); if ( temp == null ) return ; temp . key = new_value ; BinomialHeapNode tempParent = temp . parent ; while (( tempParent != null ) && ( temp . key < tempParent . key )) { int z = temp . key ; temp . key = tempParent . key ; tempParent . key = z ; temp = tempParent ; tempParent = tempParent . parent ; } } // Method 9 // To extract the node with the minimum key public int extractMin () { if ( Nodes == null ) return - 1 ; BinomialHeapNode temp = Nodes prevTemp = null ; BinomialHeapNode minNode = Nodes . findMinNode (); while ( temp . key != minNode . key ) { prevTemp = temp ; temp = temp . sibling ; } if ( prevTemp == null ) { Nodes = temp . sibling ; } else { prevTemp . sibling = temp . sibling ; } temp = temp . child ; BinomialHeapNode fakeNode = temp ; while ( temp != null ) { temp . parent = null ; temp = temp . sibling ; } if (( Nodes == null ) && ( fakeNode == null )) { size = 0 ; } else { if (( Nodes == null ) && ( fakeNode != null )) { Nodes = fakeNode . reverse ( null ); size = Nodes . getSize (); } else { if (( Nodes != null ) && ( fakeNode == null )) { size = Nodes . getSize (); } else { unionNodes ( fakeNode . reverse ( null )); size = Nodes . getSize (); } } } return minNode . key ; } // Method 10 // To display heap public void displayHeap () { System . out . print ( 'nHeap : ' ); displayHeap ( Nodes ); System . out . println ( 'n' ); } private void displayHeap ( BinomialHeapNode r ) { if ( r != null ) { displayHeap ( r . child ); System . out . print ( r . key + ' ' ); displayHeap ( r . sibling ); } } } // Class 3 // Main class public class GFG { public static void main ( String [] args ) { // Make object of BinomialHeap BinomialHeap binHeap = new BinomialHeap (); // Inserting in the binomial heap // Custom input integer values binHeap . insert ( 12 ); binHeap . insert ( 8 ); binHeap . insert ( 5 ); binHeap . insert ( 15 ); binHeap . insert ( 7 ); binHeap . insert ( 2 ); binHeap . insert ( 9 ); // Size of binomial heap System . out . println ( 'Size of the binomial heap is ' + binHeap . getSize ()); // Displaying the binomial heap binHeap . displayHeap (); // Deletion in binomial heap binHeap . delete ( 15 ); binHeap . delete ( 8 ); // Size of binomial heap System . out . println ( 'Size of the binomial heap is ' + binHeap . getSize ()); // Displaying the binomial heap binHeap . displayHeap (); // Making the heap empty binHeap . makeEmpty (); // checking if heap is empty System . out . println ( binHeap . isEmpty ()); } }JavaScript''' Min Heap Implementation in Python ''' class MinHeap : def __init__ ( self ): ''' On this implementation the heap list is initialized with a value ''' self . heap_list = [ 0 ] self . current_size = 0 def sift_up ( self i ): ''' Moves the value up in the tree to maintain the heap property. ''' # While the element is not the root or the left element Stop = False while ( i // 2 > 0 ) and Stop == False : # If the element is less than its parent swap the elements if self . heap_list [ i ] < self . heap_list [ i // 2 ]: self . heap_list [ i ] self . heap_list [ i // 2 ] = self . heap_list [ i // 2 ] self . heap_list [ i ] else : Stop = True # Move the index to the parent to keep the properties i = i // 2 def insert ( self k ): ''' Inserts a value into the heap ''' # Append the element to the heap self . heap_list . append ( k ) # Increase the size of the heap. self . current_size += 1 # Move the element to its position from bottom to the top self . sift_up ( self . current_size ) def sift_down ( self i ): # if the current node has at least one child while ( i * 2 ) <= self . current_size : # Get the index of the min child of the current node mc = self . min_child ( i ) # Swap the values of the current element is greater than its min child if self . heap_list [ i ] > self . heap_list [ mc ]: self . heap_list [ i ] self . heap_list [ mc ] = self . heap_list [ mc ] self . heap_list [ i ] i = mc def min_child ( self i ): # If the current node has only one child return the index of the unique child if ( i * 2 ) + 1 > self . current_size : return i * 2 else : # Herein the current node has two children # Return the index of the min child according to their values if self . heap_list [ i * 2 ] < self . heap_list [( i * 2 ) + 1 ]: return i * 2 else : return ( i * 2 ) + 1 def delete_min ( self ): # Equal to 1 since the heap list was initialized with a value if len ( self . heap_list ) == 1 : return 'Empty heap' # Get root of the heap (The min value of the heap) root = self . heap_list [ 1 ] # Move the last value of the heap to the root self . heap_list [ 1 ] = self . heap_list [ self . current_size ] # Pop the last value since a copy was set on the root * self . heap_list _ = self . heap_list # Decrease the size of the heap self . current_size -= 1 # Move down the root (value at index 1) to keep the heap property self . sift_down ( 1 ) # Return the min value of the heap return root ''' Driver program ''' # Same tree as above example. my_heap = MinHeap () my_heap . insert ( 5 ) my_heap . insert ( 6 ) my_heap . insert ( 7 ) my_heap . insert ( 9 ) my_heap . insert ( 13 ) my_heap . insert ( 11 ) my_heap . insert ( 10 ) print ( my_heap . delete_min ()) # removing min node i.e 5// JavaScript program to implement different operations // on Binomial Heap // A Binomial Tree node. class Node { constructor ( data ) { this . data = data ; this . degree = 0 ; this . child = null ; this . sibling = null ; this . parent = null ; } } // This function merges two Binomial Trees. function mergeBinomialTrees ( b1 b2 ) { // Make sure b1 is smaller if ( b1 . data > b2 . data ) { let temp = b1 ; b1 = b2 ; b2 = temp ; } // We basically make larger valued tree // a child of smaller valued tree b2 . parent = b1 ; b2 . sibling = b1 . child ; b1 . child = b2 ; b1 . degree ++ ; return b1 ; } // This function performs union operation on two // binomial heaps i.e. l1 & l2 function unionBionomialHeap ( l1 l2 ) { // _new to another binomial heap which contain // new heap after merging l1 & l2 let _new = []; let it = 0 ; let ot = 0 ; while ( it < l1 . length && ot < l2 . length ) { // if D(l1) <= D(l2) if ( l1 [ it ]. degree <= l2 [ ot ]. degree ) { _new . push ( l1 [ it ]); it ++ ; } // if D(l1) > D(l2) else { _new . push ( l2 [ ot ]); ot ++ ; } } // if there remains some elements in l1 // binomial heap while ( it < l1 . length ) { _new . push ( l1 [ it ]); it ++ ; } // if there remains some elements in l2 // binomial heap while ( ot < l2 . length ) { _new . push ( l2 [ ot ]); ot ++ ; } return _new ; } // adjust function rearranges the heap so that // heap is in increasing order of degree and // no two binomial trees have same degree in this heap function adjust ( _heap ) { if ( _heap . length <= 1 ) return _heap ; let new_heap = []; let it1 = 0 ; let it2 = 1 ; let it3 = 2 ; while ( it1 < _heap . length ) { // if only one element remains to be processed if ( it2 >= _heap . length ) it1 ++ ; // If D(it1) < D(it2) i.e. merging of Binomial // Tree pointed by it1 & it2 is not possible // then move next in heap else if ( _heap [ it1 ]. degree < _heap [ it2 ]. degree ) { it1 ++ ; it2 ++ ; if ( it3 < _heap . length ) it3 ++ ; } // if D(it1)D(it2) & D(it3) are same i.e. // degree of three consecutive Binomial Tree are same // in heap else if ( it3 < _heap . length && _heap [ it1 ]. degree == _heap [ it2 ]. degree && _heap [ it1 ]. degree == _heap [ it3 ]. degree ) { it1 ++ ; it2 ++ ; it3 ++ ; } // if degree of two Binomial Tree are same in heap else if ( _heap [ it1 ]. degree == _heap [ it2 ]. degree ) { _heap [ it1 ] = mergeBinomialTrees ( _heap [ it1 ] _heap [ it2 ]); _heap . splice ( it2 1 ); if ( it3 < _heap . length ) it3 ++ ; } } return _heap ; } // inserting a Binomial Tree into binomial heap function insertATreeInHeap ( _heap tree ) { // creating a new heap i.e temp let temp = []; // inserting Binomial Tree into heap temp . push ( tree ); // perform union operation to finally insert // Binomial Tree in original heap temp = unionBionomialHeap ( _heap temp ); return adjust ( temp ); } // removing minimum key element from binomial heap // this function takes Binomial Tree as input and returns // binomial heap after // removing head of that tree i.e. minimum element function removeMinFromTreeReturnBHeap ( tree ) { let heap = []; let temp = tree . child ; let lo ; // making a binomial heap from Binomial Tree while ( temp ) { lo = temp ; temp = temp . sibling ; lo . sibling = null ; heap . unshift ( lo ); } return heap ; } // inserting a key into the binomial heap function insert ( _head key ) { let temp = new Node ( key ); return insertATreeInHeap ( _head temp ); } // return pointer of minimum value Node // present in the binomial heap function getMin ( _heap ) { let it = 0 ; let temp = _heap [ 0 ]; while ( it < _heap . length ) { if ( _heap [ it ]. data < temp . data ) temp = _heap [ it ]; it ++ ; } return temp ; } function extractMin ( _heap ) { let new_heap = []; let lo ; let temp ; // temp contains the pointer of minimum value // element in heap temp = getMin ( _heap ); let it = 0 ; while ( it < _heap . length ) { if ( _heap [ it ] != temp ) { // inserting all Binomial Tree into new // binomial heap except the Binomial Tree // contains minimum element new_heap . push ( _heap [ it ]); } it ++ ; } lo = removeMinFromTreeReturnBHeap ( temp ); new_heap = unionBionomialHeap ( new_heap lo ); new_heap = adjust ( new_heap ); return new_heap ; } // print function for Binomial Tree function printTree ( h ) { while ( h ) { console . log ( h . data + ' ' ); printTree ( h . child ); h = h . sibling ; } } // print function for binomial heap function printHeap ( _heap ) { for ( let i = 0 ; i < _heap . length ; i ++ ) { printTree ( _heap [ i ]); } } // Driver program to test above functions function main () { let _heap = []; // Insert data in the heap _heap = insert ( _heap 10 ); _heap = insert ( _heap 20 ); _heap = insert ( _heap 30 ); console . log ( 'Heap elements after insertion:' ); printHeap ( _heap ); let temp = getMin ( _heap ); console . log ( 'nMinimum element of heap ' + temp . data ); // Delete minimum element of heap _heap = extractMin ( _heap ); console . log ( 'Heap after deletion of minimum element' ); printHeap ( _heap ); } main ();
VýstupHeap elements after insertion: 30 10 20 Minimum element of heap 10 Heap after deletion of minimum element 20 30Vytvoriť kvíz