vendredi 20 décembre 2019

How to maintain std:: queue in std::unordered_map without loosing changes being done on queue?

I am trying to construct an euler path for a rooted tree where root can have multiple children (i.e. its not a binary tree). To keep track of each already traversed child I am maintaining a queue in a map. When I encounter a root I simply pop one of its children and set it as root. The problem is whenever, I pop a child and its parent is traversed again the popped node appears again. I am guessing I need to store references of queue but can't get my head around it. Any help would be appreciated.

vector<int> getEulerPath(Node* root) {

    Node* node = root;
    vector<int> path;
    unordered_map<int, queue<Node*>> uvc;

    while(node != NULL) {
        path.push_back(node->data);
        cout << "processing node " << node->data << endl;
        if(uvc.find(node->data) != uvc.end()) {
            cout << "found queue: " << node->data << endl;
            uv = uvc.find(node->data)->second;
        } else {
            for(int i = 0; i < node->children.size(); i++) {
                uv.push(node->children[i]);
            }
            cout << "adding queue: " << node->data << endl;
            uvc.insert(pair<int, queue<Node*>>{node->data, uv});
        }

        if(!uv.empty()) {
            cout << "queue size before popping: " << uv.size() << endl;
            cout << "have some children left for : " << node->data << endl;
            node = uv.front();
            uv.pop();
            cout << "queue size after popping: " << uv.size() << endl;
        } else {
            cout << "no children left reverting back to : " << node->parent->data << endl; 
            node = node->parent;
        }

        cout << "new node is: " << node->data << endl;
    }

    return path;
}

Update

Following is the minimal runnable example

#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>

using namespace std;

class Node {
public:
    vector<Node*> children;
    Node* parent;
    int data;
    Node();
    Node(int, Node*);
};

Node::Node() {
    parent = NULL;
    data = -1;
}

Node::Node(int d, Node* p) {
    parent = p;
    data = d;
}

Node* generateTree(vector<vector<int>> edges) {
    unordered_map<int, Node*> nodes;
    Node* root = new Node();
    for(int i = 0; i < edges.size(); i++) {
        vector<int> edge = edges[i];
        Node* parent;
        Node* child;
        if(nodes.find(edge[0]) == nodes.end()) {
            parent = new Node(edge[0], NULL);
            nodes.insert(pair<int, Node*>{edge[0], parent});
        } else {
            parent = nodes.find(edge[0])->second;
        }
        if(nodes.find(edge[1]) == nodes.end()) {
            child = new Node(edge[1], parent);
            nodes.insert(pair<int, Node*>{edge[0], child});
        } else {
            child = nodes.find(edge[1])->second;
        }
        if(i == 0) root = parent;
        parent->children.push_back(child);
    }
    return root;
}

vector<int> getEulerPath(Node* root) {

    Node* node = root;
    vector<int> path;
    unordered_map<int, queue<Node*>> uvc;

    while(node != NULL) {
        path.push_back(node->data);
        cout << "processing node " << node->data << endl;
        queue<Node*> uv;
        if(uvc.find(node->data) != uvc.end()) {
            cout << "found queue: " << node->data << endl;
            uv = uvc.find(node->data)->second;
        } else {
            for(int i = 0; i < node->children.size(); i++) {
                uv.push(node->children[i]);
            }
            cout << "adding queue: " << node->data << endl;
            uvc.insert(pair<int, queue<Node*>>{node->data, uv});
        }

        if(!uv.empty()) {
            cout << "queue size before popping: " << uv.size() << endl;
            cout << "have some children left for : " << node->data << endl;
            node = uv.front();
            uv.pop();
            cout << "queue size after popping: " << uv.size() << endl;
        } else {
            cout << "no children left reverting back to : " << node->parent->data << endl; 
            node = node->parent;
        }

        cout << "new node is: " << node->data << endl;
    }

    return path;
}

int main() {
    vector<vector<int>> edges;
    edges.push_back(vector<int> {1, 2});
    edges.push_back(vector<int> {1, 3});
    edges.push_back(vector<int> {1, 4});
    edges.push_back(vector<int> {3, 5});
    edges.push_back(vector<int> {3, 6});
    edges.push_back(vector<int> {3, 7});
    Node* root = generateTree(edges);
    vector<int> euler_path = getEulerPath(root);
    for(int i = 0; i < euler_path.size(); i++) {
        cout << euler_path[i] << " ";
    }
    cout << endl;
    return 0;
}

Aucun commentaire:

Enregistrer un commentaire