Question

In: Computer Science

Streaming Heaps Binary heaps in general allow for constant time findMin and logarithmic time deleteMin and...

Streaming Heaps

Binary heaps in general allow for constant time findMin and logarithmic
time deleteMin and insert operations. However one of the drawbacks of
binary heaps is merging two heaps together which takes linear time.
Often in real world while working with streaming data, you have a
stream of prioritized data clustered together and having a fast way to
merge two heaps together would be really critical.
Design a data structure that builds upon the heap design and allows for
faster than linear time merge operation. You can take some penalty in
other operations but none of the other operations can be slower than
logarithmic time.

Solutions

Expert Solution

There are actually two variants of mergeable heaps: Leftist heaps and Binomial heaps I've personally only implemented leftist heaps before, but both of these variants will give you all of the following operations in O(logn) time:

  • Insert a new element
  • Find the minimum (maximum) element
  • Delete the minimum (maximum) element
  • Decrease the key of any given element
  • Delete any given element
  • Merge two heaps into a single heap

Function       Complexity              Comparison
1) Get Min:       O(1)     
2) Delete Min:    O(Log n) 
3) Insert:        O(Log n)                                                           
4) Merge:         O(Log n)  

//C++ program for leftist heap / leftist tree

#include <bits/stdc++.h>

using namespace std;

// Node Class Declaration

class LeftistNode

{

public:

    int element;

    LeftistNode *left;

    LeftistNode *right;

    int dist;

    LeftistNode(int & element, LeftistNode *lt = NULL,

                LeftistNode *rt = NULL, int np = 0)

    {

        this->element = element;

        right = rt;

        left = lt,

        dist = np;

    }

};

//Class Declaration

class LeftistHeap

{

public:

    LeftistHeap();

    LeftistHeap(LeftistHeap &rhs);

    ~LeftistHeap();

    bool isEmpty();

    bool isFull();

    int &findMin();

    void Insert(int &x);

    void deleteMin();

    void deleteMin(int &minItem);

    void makeEmpty();

    void Merge(LeftistHeap &rhs);

    LeftistHeap & operator =(LeftistHeap &rhs);

private:

    LeftistNode *root;

    LeftistNode *Merge(LeftistNode *h1,

                       LeftistNode *h2);

    LeftistNode *Merge1(LeftistNode *h1,

                        LeftistNode *h2);

    void swapChildren(LeftistNode * t);

    void reclaimMemory(LeftistNode * t);

    LeftistNode *clone(LeftistNode *t);

};

// Construct the leftist heap

LeftistHeap::LeftistHeap()

{

    root = NULL;

}

// Copy constructor.

LeftistHeap::LeftistHeap(LeftistHeap &rhs)

{

    root = NULL;

    *this = rhs;

}

// Destruct the leftist heap

LeftistHeap::~LeftistHeap()

{

    makeEmpty( );

}

/* Merge rhs into the priority queue.

rhs becomes empty. rhs must be different

from this.*/

void LeftistHeap::Merge(LeftistHeap &rhs)

{

    if (this == &rhs)

        return;

    root = Merge(root, rhs.root);

    rhs.root = NULL;

}

/* Internal method to merge two roots.

Deals with deviant cases and calls recursive Merge1.*/

LeftistNode *LeftistHeap::Merge(LeftistNode * h1,

                                LeftistNode * 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);

}

/* Internal method to merge two roots.

Assumes trees are not empty, and h1's root contains

  smallest item.*/

LeftistNode *LeftistHeap::Merge1(LeftistNode * h1,

                                 LeftistNode * h2)

{

    if (h1->left == NULL)

        h1->left = h2;

    else

    {

        h1->right = Merge(h1->right, h2);

        if (h1->left->dist < h1->right->dist)

            swapChildren(h1);

        h1->dist = h1->right->dist + 1;

    }

    return h1;

}

// Swaps t's two children.

void LeftistHeap::swapChildren(LeftistNode * t)

{

    LeftistNode *tmp = t->left;

    t->left = t->right;

    t->right = tmp;

}

/* Insert item x into the priority queue, maintaining

  heap order.*/

void LeftistHeap::Insert(int &x)

{

    root = Merge(new LeftistNode(x), root);

}

/* Find the smallest item in the priority queue.

Return the smallest item, or throw Underflow if empty.*/

int &LeftistHeap::findMin()

{

    return root->element;

}

/* Remove the smallest item from the priority queue.

Throws Underflow if empty.*/

void LeftistHeap::deleteMin()

{

    LeftistNode *oldRoot = root;

    root = Merge(root->left, root->right);

    delete oldRoot;

}

/* Remove the smallest item from the priority queue.

Pass back the smallest item, or throw Underflow if empty.*/

void LeftistHeap::deleteMin(int &minItem)

{

    if (isEmpty())

    {

        cout<<"Heap is Empty"<<endl;

        return;

    }

    minItem = findMin();

    deleteMin();

}

/* Test if the priority queue is logically empty.

Returns true if empty, false otherwise*/

bool LeftistHeap::isEmpty()

{

    return root == NULL;

}

/* Test if the priority queue is logically full.

Returns false in this implementation.*/

bool LeftistHeap::isFull()

{

    return false;

}

// Make the priority queue logically empty

void LeftistHeap::makeEmpty()

{

    reclaimMemory(root);

    root = NULL;

}

// Deep copy

LeftistHeap &LeftistHeap::operator =(LeftistHeap & rhs)

{

    if (this != &rhs)

    {

        makeEmpty();

        root = clone(rhs.root);

    }

    return *this;

}

// Internal method to make the tree empty.

void LeftistHeap::reclaimMemory(LeftistNode * t)

{

    if (t != NULL)

    {

        reclaimMemory(t->left);

        reclaimMemory(t->right);

        delete t;

    }

}

// Internal method to clone subtree.

LeftistNode *LeftistHeap::clone(LeftistNode * t)

{

    if (t == NULL)

        return NULL;

    else

        return new LeftistNode(t->element, clone(t->left),

                               clone(t->right), t->dist);

}

//Driver program

int main()

{

    LeftistHeap h;

    LeftistHeap h1;

    LeftistHeap h2;

    int x;

    int arr[]= {1, 5, 7, 10, 15};

    int arr1[]= {22, 75};

    h.Insert(arr[0]);

    h.Insert(arr[1]);

    h.Insert(arr[2]);

    h.Insert(arr[3]);

    h.Insert(arr[4]);

    h1.Insert(arr1[0]);

    h1.Insert(arr1[1]);

    h.deleteMin(x);

    cout<< x <<endl;

    h1.deleteMin(x);

    cout<< x <<endl;

    h.Merge(h1);

    h2 = h;

    h2.deleteMin(x);

    cout<< x << endl;

    return 0;

}


Related Solutions

A binary variable can be introduced to a mixed integer program to allow for a “threshold...
A binary variable can be introduced to a mixed integer program to allow for a “threshold constraint.” A threshold constraint says that if any units are used, at least a specified minimum amount must be used. Define X as the number of students that will go on a planned field trip. The school will rent a bus only if at least 20 students plan to go on the trip. Define Y as a binary variable that equals 1 if X...
In your final specification, you allow for the binary variables to interact. The results are as...
In your final specification, you allow for the binary variables to interact. The results are as follows: Earn = 0.14 + 0.093 × Educ + 0.032 × Exper – 0.0005 × Exper2 - 0.158 × Female + 0.173 × Married – 0.218 × (Female × Married), (0.16) (0.011) (0.006) (0.001) (0.075) (0.080) (0.097) R2 = 0.44, SER = 0.375 A) What is the gender wage gap for married individuals? B) What is the gender wage gap for single individuals?
Create design document for a program that will allow the user: Convert a number to binary....
Create design document for a program that will allow the user: Convert a number to binary. Convert from binary to number. Display the hexadecimal representation of a binary number. Given an hexadecimal display its binary representation. Convert a number to IEEE single precision and vice versa. More to come. PLEASE ADD PSEUDOCODE AND USE C PROGRAMMING USE FUNCTIONS IF POSSIBLE
Prove it's correct or wrong. A particular version of PARTITION runs in logarithmic time but produces...
Prove it's correct or wrong. A particular version of PARTITION runs in logarithmic time but produces splits where all elements go to the same side of the pivot every time. QUICKSORT based on this PARTITION has the same worse-case running time as the standard version.
This force can either push the block upward at a constant velocity or allow it to...
This force can either push the block upward at a constant velocity or allow it to slide downward at a constant velocity. The magnitude of the force is different in the two cases, while the directional angle θ is the same. Kinetic friction exists between the block and the wall, and the coefficient of kinetic friction is 0.310. The weight of the block is 55.0 N, and the directional angle for the force Upper F Overscript right-arrow EndScripts is θ...
Question about Financial risk management and derivative products Explain why the binary model will allow the...
Question about Financial risk management and derivative products Explain why the binary model will allow the option price to converge to a specific value as the number of periods increases? What is that convergent option value? When n approaches infinity, what famous model converges to the binary model?
5. Which of the below are ways that allow you to recognize equilibrium? a. constant temperature...
5. Which of the below are ways that allow you to recognize equilibrium? a. constant temperature b. constant color c. constant pressure d. All of the above are correct. e. None of the above are correct. 6. Equilibrium is a state of dynamic molecular behavior, meaning that a. the reaction eventually comes to a stop. b. reactants continually turn into products at a progressively slower rate. c. products continually turn into reactants at a progressively faster rate. d. reactants turn...
derive the general formula for leverage in a regression model using a single binary covariate with...
derive the general formula for leverage in a regression model using a single binary covariate with ?11’s and ?0 0’s?
General equilibrium models of asset pricing allow us to determine the relevant measure of risk for...
General equilibrium models of asset pricing allow us to determine the relevant measure of risk for any asset and the relationship between expected return and risk. Two of these models have been subject to fierce debate among practitioners and academics, The Capital Asset Pricing Model (CAPM) and The Arbitrage Pricing Model (APT). Based on the assumptions and tests of each model you are asked to: 1. Critically analyse the assumptions of both models. 2. Discuss the similarities and differences between...
Please explain how Rm, Cm, and Ri contribute to the time constant in the length constant...
Please explain how Rm, Cm, and Ri contribute to the time constant in the length constant of an axon. Can we manipulate Rm, Cm, and Ri? What would we want to change to create the fastest conduction velocity?  
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT