extract Min function is not working properly

93 views Asked by At

I got an assignment but I'm stuck in the titled problem. It will be very glad that you will help me to solve this. The quick over review I have provided the classes and main file for which I have to implemented the function and run the code. There are two files named fheap.hpp and djstra.hpp and the main file.

int main(){

    // Fibonacci Heap

    FibonacciHeap<int> heap(3);
    std::cout<<(heap.get_min()==std::nullopt)<<std::endl;

    std::vector<int> inserted;

    for(int i = 0 ; i < 15 ; ++i) {
        int temp = rand() % 100+1;
        heap.insert(temp);
        cout << temp;
        cout << "inserted  & min :";
        cout << heap.get_min().value() << endl;

    }

    std::cout<<heap.get_min().value()<<std::endl;
    for (int j = 0; j < 15; ++j) {
        int min_value = heap.extract_min().value();
        cout << "min_value: ";
        std::cout << min_value;
        cout << "  size: ";
        cout << heap.size()<<endl;
    }


    // Dijkstra's Algorithm

    edges_t edges1 = {{0, 1, 3.0f},
                      {0, 2, 1.0f},
                      {1, 2, 7.0f},
                      {1, 3, 5.0f},
                      {1, 4, 1.0f},
                      {2, 3, 2.0f},
                      {3, 4, 7.0f}};


    Graph g1(5, edges1, GraphType::UNDIRECTED);

    std::unordered_map<vertex_t, std::optional<std::tuple<vertex_t, edge_weight_t>>> result
            = dijkstra_shortest_path(g1, 2);

    // Previous vertex of src are not checked.
    std::vector<vertex_t> previous = {2, 0, (vertex_t)-1, 2, 1};
    std::vector<edge_weight_t> dist = {1.0f, 4.0f, 0.0f, 2.0f, 5.0f};


    // The printed result should be same as above.

    for(size_t i = 0 ; i < 5 && i!=2 ; ++i) {
        std::cout<<"[vertex i] ";
        std::cout<<"previous: "<<std::get<0>(result[i].value())<<", ";
        std::cout<<"distance: "<<std::get<1>(result[i].value())<<std::endl;
    }

    return 0;

}

Suprisingly the djstra part is giving me the required output. second file loop in the main section throws memory error Edit: ( meaning it exits the program with some memory address and sometimes show what() std:: optional error). The fheap class is below that are responsible for it are below:

#ifndef __FHEAP_H_
#define __FHEAP_H_

#include <iostream>
#include <initializer_list>
#include <optional>
#include <vector>
#include <cmath>
#include <memory>
#include <queue>
#include <list>

template <typename T>
class PriorityQueue {
public:
    virtual void insert(const T& item) = 0;
    virtual std::optional<T> extract_min() = 0;
    virtual bool is_empty() const = 0;
};

template <typename T>
class FibonacciNode {
public:
    // Constructors
    FibonacciNode()
            :key(), degree(0), marked(false), child(nullptr), right(nullptr) {}

    FibonacciNode(const T& item)
            :key(item), degree(0), marked(false), child(nullptr), right(nullptr) {}

    // Destructor
    ~FibonacciNode() = default;

    T key;
    size_t degree;
    bool marked;

    std::shared_ptr<FibonacciNode<T>> right;
    std::shared_ptr<FibonacciNode<T>> child;
    // NOTE: To prevent circular reference, left/parent pointer should be set to weak_ptr.
    std::shared_ptr<FibonacciNode<T>> left;
    std::shared_ptr<FibonacciNode<T>> parent;
};

template <typename T>
class FibonacciHeap : public PriorityQueue<T> {
public:
    // Constructors
    FibonacciHeap()
            : min_node(nullptr), size_(0) {}
    FibonacciHeap(const T& item)
            : min_node(nullptr), size_(0) { insert(item); }

    // Disable copy constructor.
    FibonacciHeap(const FibonacciHeap<T> &);

    // Destructor
    //~FibonacciHeap();

    void insert(const T& item) override;
    void insert(std::shared_ptr<FibonacciNode<T>>& node);

    // Return raw pointer of the min_node.
    FibonacciNode<T>* get_min_node() { return min_node.get(); }

    std::optional<T> get_min() const;

    std::optional<T> extract_min() override;
    std::optional<T> extract_min1();
    void decrease_key(std::shared_ptr<FibonacciNode<T>>& x, T new_key);

    void remove(std::shared_ptr<FibonacciNode<T>>& node);

    bool is_empty() const override { return !size_; }

    size_t size() const { return size_; }

private:

    std::shared_ptr<FibonacciNode<T>> min_node;
    std::shared_ptr<FibonacciNode<T>> min;
    size_t size_;

    void consolidate();
    void merge(std::shared_ptr<FibonacciNode<T>>& x, std::shared_ptr<FibonacciNode<T>>& y);
    void cut(std::shared_ptr<FibonacciNode<T>>& x);
    void recursive_cut(std::shared_ptr<FibonacciNode<T>>& x);

};

template <typename T>
void FibonacciHeap<T>::insert(const T& item) {
    std::shared_ptr<FibonacciNode<T>> node = std::make_shared<FibonacciNode<T>>(item);
    insert(node);
}
template <typename T>
std::optional<T> FibonacciHeap<T>::get_min() const {
    if (min_node) {
        return min_node->key;
    } else {
        return std::nullopt;
    }
}

template <typename T>
void FibonacciHeap<T>::insert(std::shared_ptr<FibonacciNode<T>>& node) {
// Make the new node the right sibling of the min_node, if it exists
    if (min_node) {
        node->right = min_node->right;
        min_node->right = node;
        node->left = min_node;
        node->right->left = node;
    }
// Otherwise, make the new node the min_node and its own right sibling
    else {
        min_node = node;
        node->right = node;
        node->left = node;
    }
// If the new node has a smaller key than the current min_node, update min_node
    if (node->key < min_node->key) {
        min_node = node;
    }
// Increase the size of the heap
    ++size_;
}



template <typename T>
std::optional<T> FibonacciHeap<T>::extract_min() {
    // Return nullopt if the heap is empty
    if (!min_node) {
        return std::nullopt;
    }

    // Store the min_node in a temporary variable
    std::shared_ptr<FibonacciNode<T>> z = min_node;

    // If the min_node has children, add them to the root list
    if (z->child) {
        std::shared_ptr<FibonacciNode<T>> child = z->child;
        do {
            child->parent.reset();
            child = child->right;
        } while (child != z->child);
        merge(min_node, z->child);
    }

    // Remove the min_node from the root list
    std::shared_ptr<FibonacciNode<T>> left = z->left;
    std::shared_ptr<FibonacciNode<T>> right = z->right;
    left->right = right;
    right->left = left;

    // If the min_node was the only node in the heap, set min_node to nullptr
    if (z == right) {
        min_node.reset();
    }
        // Otherwise, set the new min_node to be the node that was previously to the right of z
    else {
        min_node = right;
        consolidate();
    }

    // Decrease the size of the heap
    --size_;

    // Return the key of the extracted min_node
    return z->key;
}

template <typename T>
void FibonacciHeap<T>::decrease_key(std::shared_ptr<FibonacciNode<T>>& x, T new_key) {
// If the new key is greater than the current key, throw an exception
    if (new_key > x->key) {
        throw std::invalid_argument("New key is greater than current key.");
    }
// Update the key of the node
    x->key = new_key;
// If the node has a parent and its new key is smaller than its parent's key, cut it from its parent and add it to the root list
    auto parent = x->parent.lock();
    if (parent && x->key < parent->key) {
        cut(x);
    }
// If the node's new key is smaller than the current min_node's key, update min_node
    if (x->key < min_node->key) {
        min_node = x;
    }
}



template <typename T>
void FibonacciHeap<T>::remove(std::shared_ptr<FibonacciNode<T>>& x) {
    // Set the key of the node to be removed to the minimum value
    x->key = std::numeric_limits<T>::min();
    // Perform a decrease key operation on the node to be removed
    decrease_key(x, std::numeric_limits<T>::min());
    // Extract the minimum value, which should be the node to be removed
    extract_min();
}

template <typename T>
void FibonacciHeap<T>::consolidate() {
    float phi = (1 + sqrt(5)) / 2.0;
    int len = int(log(size_) / log(phi)) + 10;
    std::vector<std::shared_ptr<FibonacciNode<T>>> A(len, nullptr);

    std::shared_ptr<FibonacciNode<T>> w = min_node;
    std::shared_ptr<FibonacciNode<T>> x = w;
    do {
        x = x->right;
        std::shared_ptr<FibonacciNode<T>> y = x;
        int d = y->degree;
        while (A[d]) {
            std::shared_ptr<FibonacciNode<T>> z = A[d];
            if (y->key > z->key) {
                std::swap(y, z);
            }
            merge(y, z);
            A[d] = nullptr;
            ++d;
        }
        A[d] = y;
    } while (w != x);

    min_node.reset();
    for (int i = 0; i < len; ++i) {
        if (A[i]) {
            if (min_node) {
                A[i]->right = min_node->right;
                min_node->right = A[i];
                A[i]->left = min_node;
                A[i]->right->left = A[i];
                if (A[i]->key < min_node->key) {
                    min_node = A[i];
                }
            }
            else {
                min_node = A[i];
                min_node->right = min_node;
                min_node->left = min_node;
            }
        }
    }
}

template <typename T>
void FibonacciHeap<T>::merge(std::shared_ptr<FibonacciNode<T>>& x, std::shared_ptr<FibonacciNode<T>>& y) {
// Make x the right sibling of y
    x->right = y->right;
    y->right->left = x;
    y->right = x;
    x->left = y;
// If x has a smaller key than y, make x the new min_node
    if (x->key < y->key) {
        min_node = x;
    }
// Otherwise, make y the new min_node
    else {
        min_node = y;
    }
// Increase the size of the heap
    size_ += 2;
}

template <typename T>
void FibonacciHeap<T>::cut(std::shared_ptr<FibonacciNode<T>>& x) {
// Get a pointer to the parent of x
    auto parent = x->parent;
// If x has no parent, we do not need to cut it
    if (!parent) return;

// Remove x from the child list of parent
    if (x->right == x) {
        parent->child = nullptr;
    }
    else {
        x->right->left = x->left;
        x->left->right = x->right;
        if (parent->child == x) {
            parent->child = x->right;
        }
    }

// Decrease the degree of parent
    --parent->degree;

// Add x to the root list of the heap
    x->right = min_node->right;
    min_node->right = x;
    x->left = min_node;
    x->right->left = x;

// Clear the parent and marked fields of x
    x->parent.reset();
    x->marked = false;
}

template <typename T>
void FibonacciHeap<T>::recursive_cut(std::shared_ptr<FibonacciNode<T>>& x) {
    // Get the parent of the node
    auto parent = x->parent.lock();

    // If the node has a parent, cut it from the parent and perform a recursive cut on the parent
    if (parent) {
        if (x->marked) {
            // Cut the node from the parent
            cut(x);
            // Perform a recursive cut on the parent
            recursive_cut(parent);
        }
            // If the node is not marked, mark it
        else {
            x->marked = true;
        }
    }
}
#endif // __FHEAP_H_

I know, I'm asking a very long question. I've tried every approach but it's not solving.

I Tried debugging the code and introducing cout operations where I think is error after debugging is in the line `

std::shared_ptr<FibonacciNode<T>> z = A[d];

I tried ArrayList but still no change.

Edit: Second for loop means the 2nd loop in int main ()

0

There are 0 answers