Unordered map not updating

I was cloning a graph (deep copy) and the only problem in my code is in the BFS() function inside the if statement, when I’m updating the visited hashmap, it’s not updating.

Node* cloneGraph(Node* node){
    Node* r_head = node;
    if(node == NULL){
        return r_head;
    }
    std::unordered_map<Node*,Node*> indexer;
    r_head = new Node(r_head->val,r_head->neighbors);
    indexer.insert({node,r_head});
    BFS(r_head,indexer);
    return r_head;
}

void BFS(Node* node,std::unordered_map<Node*,Node*> indexer){
    int temp_val;
    std::unordered_map<int,bool> visited;
    std::vector<Node*> output_nodes;
    output_nodes.push_back(node);
    visited.insert(std::make_pair(node->val,1)); // only this one is updated
    Node* temp_node;
    Node* temp_node_2;
    for(int i = 0 ; i < output_nodes.size() ; i++){
        for(int j = 0 ; j < output_nodes.at(i)->neighbors.size(); j++){
            temp_node = output_nodes.at(i)->neighbors[j];
            if(!visited[temp_node->val]){
                temp_node_2 = new Node(temp_node->val,temp_node->neighbors);
                indexer.insert({temp_node,temp_node_2});
                output_nodes.push_back(temp_node_2);

                visited.insert(std::make_pair(temp_val,true)); //does not get updated
                //printf("visited %dn", visited[2]);

            }
        }
    }
    new_neigbors(indexer,node,output_nodes);
}

void new_neigbors(std::unordered_map<Node*,Node*> indexer ,Node* node, std::vector<Node*> output_nodes){
    printf("output node size in new_neighbor %dn",output_nodes.size());
    for(int i = 0 ; i < output_nodes.size(); i ++){
        for(int j = 0 ; j < output_nodes.at(i)->neighbors.size(); j++){
            output_nodes.at(i)->neighbors.at(j) = indexer[output_nodes.at(i)->neighbors.at(j)];
            printf(" inside new _neignors wooo j %dn",j);
        }
    }
}

9

You seem to be missing code to assign a value to temp_val.

My suggestion is to change this line:

            if(!visited[temp_node->val]){

into two lines:

            temp_val = temp_node->val;
            if(!visited[temp_val]){

That way, you will not be trying to read from an uninitialized value when creating your new entry:

                visited.insert(std::make_pair(temp_val,true)); //...

However, as user4581301 pointed out in comments, this insertion fails. When you use the [] accessor to test if you have visited the node, you have generated an entry in visited for that key. So, you will not be able to insert the new pair.

You could just assign true, though.

                visited[temp_val] = true; //...

2

The visited[temp_node->val] in if(!visited[temp_node->val]) Automatically adds temp_node->val:false to visited and makes the later insert` fail because the node is already present.

Simple example:

#include <iostream>
#include <unordered_map>

int main()
{
    std::unordered_map<int, bool> visited;

    if (!visited[42]) // auto inserts {42,false}
    {
        visited.insert({42,true}); //42 already in map, insertion refused.
    }
    std::cout << visited[42] <<std::endl;
}

Outputs 0.

A unordered_set should work better for you here as presence, or lack of it, in the set implies the boolean output.

#include <iostream>
#include <unordered_set>

int main()
{
    std::unordered_set<int> visited;

    if (!visited.contains(42))
    {
        visited.insert(42);
    }
    std::cout << visited.contains(42) <<std::endl;
}

Outputs 1.

Side note: std::unordered_set::contains was added in C++20. Before that, use find and compare the result against visited‘s end iterator:

#include <iostream>
#include <unordered_set>

int main()
{
    std::unordered_set<int> visited;

    if (visited.find(42) == visited.end())
    {
        visited.insert(42);
    }
    std::cout << visited.contains(42) <<std::endl;
}

You must also address the uninitialized temp_val pointed out by jhx’s answer.

Replace

std::unordered_map<int,bool> visited;

with

std::unordered_set<int> visited;

and then you can

            temp_node = output_nodes.at(i)->neighbors[j];
            temp_val = temp_node->val;
            if(!visited[temp_val].contains()){
                temp_node_2 = new Node(temp_node->val,temp_node->neighbors);
                indexer.insert({temp_node,temp_node_2});
                output_nodes.push_back(temp_node_2);

                visited.insert(temp_val);
            }

And at some point in the future you need to address the pass-by-value problem Yakk highlights.

2

void BFS(Node* node,std::unordered_map<Node*,Node*> indexer){

when you take an object (like an unordered map) by value, you get a local copy of it. You appear to think that modifying indexer within BFS will change the passed in indexer when you called it. This won’t happen.

The easiest way to detect such errors is to mark your function arguments as const on the right like this:

void BFS(Node*const node,std::unordered_map<Node*,Node*>const indexer){

the compiler will now generate errors whenever you try to modify them. You do this on the right so that if they are pointers, it is the pointer and not the pointed to that is const. (For reference parameters, const on the right generates an error: this is good, because you don’t want the const in that case).

Do this to every function in this example. Every line that generates an error is you misunderstanding what “passing an object by value” means.

It is possible that you intend to actually take the objects by & reference; I do not know. It is a very bad habit to just take every parameter by reference, however.

The core issue is you need to understand that objects in C++ have actual values, and when you create a variable of an object type you get a type that is an actual value, not a reference to that object on the heap somewhere.

Keeping track of where objects are and who owns them is an extra task that C++ places on programmers. One way we avoid the problem is that we write “pure functions” that take values in and return modified versions, and we std::move stuff in and assign the results.


Your next problem is here:

  if(!visited[temp_node->val]){

this causes visited to have a false value under temp_node->val if it didn’t exist prior to this line. [] creates with default value in a std::map and std::unordered_map, here false, if it is missing.

There are two problems here:

  visited.insert(std::make_pair(temp_val,true)); //does not 

first, temp_val is never given a value. You could just delete it and use temp_node->val, or you could assign it the value earlier; either works.

The second is that insert does not replace a value that already exists. It returns a std::pair<iterator, bool> where the 2nd parameter says if the insert actually replaced something.

Normally this isn’t a problem, but earlier use of [] caused the element to be created

.insert_or_assign does what you want; alternatively, you can just do visited[key] = true.

The use of a map from a key to a bool is often a mistake. Using a unordered_set can help; use visited.count(key) > 0 or visited.contains(key) to detect if something is in the set, and use insert (without the pair/bool) to add to the set: visited.insert(key).

This is a bit less error prone, and doesn’t waste memory on storing not-visited elements.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật