1

I hope this isn't a duplicate but I couldn't find any similar posts.

The build on this may seem overly convoluted but I am trying to learn binary sorting trees and apply it to my graph knowledge. I understand it may be easier to use an adjacency list.

Currently the build utilizes two structs and a class, one struct for Edges, one for Vectors, and the "Graph" class functions as a binary search tree.

    // Vertex node stores name and neighbors
    struct Vertex {
        string name;
        vector<Edge *> *neighbors;
    };


    class Graph {
        // Functions like BST and stores a Vertex object with each node
        int value;
        Graph *left, *right;
        struct Vertex *node;

The functions that interact with this portion of the program are my default and parameterized constructors:

    Graph::Graph() : value(0), left(NULL), right(NULL), node(){};

    Graph::Graph(int data, Vertex* node) {
        value = data;
        left = right = NULL;
        Vertex* newNode = new Vertex;
        newNode = node;
    };

and my addVertex function:

    Graph* Graph::addVertex(Graph* root, string name, int data){
        if (!root) {
            Vertex* newVertex = new Vertex;
            newVertex->name = name;
            newVertex->neighbors = new vector<Edge *>();
            node = newVertex;
            return new Graph(data, node);
        }
        if (value > root->value){
            root->right = addVertex(root->right, name, data);
        }
        else if (value < root->value){
            root->left = addVertex(root->left, name, data);
        }
        return root;
    };

I have tried removing each one of the constructors separately, tried creating a new Vertex within the constructors. Changing the variable order within the class and structs. It seems like the program is only creating over vertex and is overwriting the vertex repeatedly.

What I expect to happen is the program would create a new Vertex and store its name for later comparison, but my output is this:

    Vertex name: g Graph Node Value: 3
    vertex name: g Neighbors:
    Vertex name: g Graph Node Value: 2
    vertex name: g Neighbors:
    Vertex name: g Graph Node Value: 1
    vertex name: g Neighbors:

So I am getting the value that is assigned to the node in the BST but I am not getting the name stored in the Vertex.

ravenspoint
  • 19,093
  • 6
  • 57
  • 103
  • *but my output is this* -- [What is a debugger?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems). To that, `newVertex->neighbors = new vector();` -- `vector *neighbors;` -- Using `new` to create a vector is not necessary. You have too much pointer usage. This could have been just `vector neighbors;`. – PaulMcKenzie Mar 25 '23 at 00:12
  • Ok, this is a helpful start. I can't believe I forgot about the debugger. I've been using inline pings and print statements to tell me where and what is going wrong. I will be going through this. – Bran The Builder Mar 25 '23 at 00:16
  • I am learning pointers as you can probably tell. I am using the `new` as a way to create a vector for each vertex to store all of its edges. Would using the `vector neighbors;` cause issues? – Bran The Builder Mar 25 '23 at 00:22
  • There is little to no reason to instantiate a container using `new`. If you used `vector neighbors;` the vector is created automatically on construction of a `Vertex`. Also remember that you have to untangle all of the code created with `new` with calls to `delete` -- otherwise you have memory leaks. The less you use `new`, the less you will have to write code to call `delete`. – PaulMcKenzie Mar 25 '23 at 00:30
  • I went through and debugged step by step and in my print function I've noticed that everything changes e.g. value, root, and associated memory locations but the node does not change. so either each leaf in the BST is using the same vertex node or the node is not changing when the function runs. I'm inclined to believe its the first option because later functions that rely on having different vertex nodes are giving me seg faults because its not finding the proper node. – Bran The Builder Mar 25 '23 at 01:08
  • First thing -- your design is confusing. A `Graph` should be a single entity. The whole idea of creating new `Graphs` every time a vertex is added is confusing. A `Graph` class should be instantiated *one* time, and then an `addVertex` member of that object just adds a vertex to *that* graph, however it wants to do it. Also, using a BST to represent a Graph is another point of confusion on a conceptual level. Also, you didn't post a [mcve]. – PaulMcKenzie Mar 25 '23 at 01:21
  • I understand that its confusing, which is probably why I am having so many issues. With you pointing out that I'm creating a new graph object each time, I'm realizing a few major areas that I've messed up. The whole thing is an experiment meant for learning purposes. Also I apologize for the code not being a minimal reproducible example. I was trying to minimize and focus on the areas with issues. Thank you for pointing these things out. – Bran The Builder Mar 25 '23 at 02:04
  • *"but my output is this"* -- I don't see any output produced by the shown code. Your [mre] should be short, yet still enough for someone to copy-compile-run and reproduce your result. – JaMiT Mar 25 '23 at 02:21

1 Answers1

0

In your graph constructor you have:

    Vertex* newNode = new Vertex;
    newNode = node;

The constructs a new vertex and a pointer to it in a local variable, newNode.

Then the local variable is assigned to point to a different vertex, the one passed in as a parameter

Then it exits. The new vertex that was constructed remains, but nothing remains that can reference it. This is a memory leak.

There are a number of other problems with your code ( the left and right pointers should be in the Vertex class, not the Graph class ... ) which I will not go into here.

Here is the code for a complete application that does what you need:

#include <string>
#include <sstream>
#include <iostream>
#include <vector>

struct Edge
{
};

// Vertex node stores name, value and neighbors
struct Vertex
{
    std::string name;
    int value;
    std::vector<Edge *> *neighbors;
    Vertex *left, *right;

    Vertex(const std::string &n,
           int v)
        : name(n), value(v),
          left(0), right(0)
    {
    }
    std::string text() const
    {
        std::stringstream ss;
        ss << name << " " << value << "\n";
        return ss.str();
    }
};

// Functions like BST and stores a Vertex object with each node
class Graph
{
    struct Vertex *root;

public:
    /// @brief Construct empty graph
    Graph()
        : root(0)
    {
    }
    /// @brief Construct graph with root vertex
    /// @param name root vertex name
    /// @param value root vertex value

    cGraph(
        const std::string &name,
        int value)
    {
        root = new Vertex(name, value);
    }

    /// @brief Add root vertex to empty graph
    /// @param name
    /// @param value

    void setRoot(
        const std::string &name,
        int value)
    {
        if (root)
            throw std::runtime_error(
                "root already set");
        root = new Vertex(name, value);
    }

    /// @brief add vertex to graph
    /// @param name
    /// @param value
    /// @param cur  // application code must omit this parameter
    
    void addVertex(
        const std::string &name,
        int value,
        Vertex *cur = 0)
    {
        if (!cur) {
            if (!root)
                setRoot("defaultRoot", 0);
            cur = root;
        }

        if (value < cur->value)
        {
            if (!cur->left)
            {
                cur->left = new Vertex(name, value);
                return;
            }
            else
                addVertex(name, value, cur->left);
        }
        else
        {
            if (!cur->right)
            {
                cur->right = new Vertex(name, value);
                return;
            }
            else
                addVertex(name, value, cur->right);
        }
    }

    // display graph contents
    void text()
    {
        text(root);
    }

private:
    void text(Vertex *v)
    {
        if (!v)
            return;
        text(v->left);
        std::cout << v->text();
        text(v->right);
    }
};

main()
{
    Graph g;

    g.setRoot("A", 10);

    g.addVertex("B", 20);
    g.addVertex("C", 5);

    g.text();

    return 0;
}

which outputs

C 5
A 10
B 20
ravenspoint
  • 19,093
  • 6
  • 57
  • 103