0

I have to analyze an m-ary tree in C - using namely BFS.

There are some requirements I don't succeed to implement for a while:

1. Find the diameter of the tree.

2. Given two vertices in the tree - find the shortest simple path between them.

As for 1 - I went through the topics in Stack - and have seen some implementations (not in C unfortunately) which are not very clear to me... Some way of calculating the diameter by using BFS twice, starting from a random vertex... I'm not sure if the second BFS has to "remember" the visited array from the first BFS.

As for 2 - I really don't know how to approach to that, but I believe I can use somehow BFS here.

  • Moreover, I have to implement these two requirements in O(n^2) time complexity.

  • Besides that, I have to find the maximal and minimal heights of the tree.

  • As for the maximal height - I have implemented BFS (not sure it's absolutely correct) which to my understanding, deals with this maximal height.

  • As for the minimal height - I have no idea how to find it.

Here are my vertex struct and BFS implementations:

typedef struct Vertex {
    size_t key;
    size_t amountOfNeighbors; // The current amount of neighbors
    size_t capacity; // The capacity of the neighbors (It's updating during run-time)
    struct Vertex* parent;

    struct Vertex** neighbors; // The possible parent and children of a vertex
} Vertex;

Vertex* bfs(Vertex* allVertices, size_t numOfVertices, Vertex* startVertex, size_t* pathDistance) {

    if (startVertex -> neighbors == NULL) { // In case we have only one vertex in the graph
        *pathDistance = 0;
        return startVertex;
    }

    Queue* q = (Queue*)malloc((sizeof(size_t) * numOfVertices));
    int* visited = (int*)malloc(sizeof(int) * numOfVertices);
    for (size_t i = 0; i < numOfVertices; i++) {
        visited[i] = 0; // Mark all the vertices as unvisited
    }

    size_t lastVertex = 0; // Actually indicates the furthermost vertex from startVertex
    *pathDistance = 0; // The number of edges between lastVertex and startVertex

    enqueue(q, startVertex->key);
    visited[startVertex->key] = 1; // Mark as visited

    while (!queueIsEmpty(q)) {
        unsigned int currentVertex = dequeue(q); // The key of the current vertex
        Vertex* s = &allVertices[currentVertex];

        size_t currentAmountOfNeighbors = 0; // Detects the number of processed neighbors of the current vertex
        for (Vertex **child = s->neighbors; currentAmountOfNeighbors < s->amountOfNeighbors; currentAmountOfNeighbors++) {
            if (!visited[(*(child))->key]) {
                visited[(*(child))->key] = 1;
                enqueue(q, (*(child))->key);
                child++; // TODO Validate it's a correct use of memory!
            }
        }
        *pathDistance += 1; // Another layer passed
        lastVertex = peekQueue(q);
    }

    Vertex* furtherMostVertexFromS = &allVertices[lastVertex];
    free(q);
    q = NULL;
    return  furtherMostVertexFromS;
}

My difficulties and wondering are in bold and any help with some of them will be appreciated.

HelpMe
  • 91
  • 10

1 Answers1

0

Firstly, questions of this nature are more appropriate to the CS Stack Exchange, but I'll try to help regardless

For your first question(finding the diameter), note that the longest path of the tree must begin(or end) with the deepest node in the tree(which is a leaf). BFS helps you find the depths of all nodes, and thus help you find the deepest node. Can you figure from there how to find the end of said path? Hint: Think about the procedure for finding the deepest node of a graph.

There seems to be a misunderstanding on your part about how BFS works: Note that the point of keeping track of visited nodes, is to avoid crossing through back-edges - that is, to avoid cycles - which aren't possible in a tree. But hypothetically, even if you do maintain such a 'visited' array (e,g if you want your algorithm to handle cyclic graphs), why would it be shared between different BFS invocations?

As for the second question: BFS finds the distances between nodes in the graph and the starting node(also called 'depth' when called from root). In particular, these are the shortest paths(on an unweighted graph)

The answer to the rest of your bolded questions are also related, the key takeway is that in an acylic, unweighted graph - BFS lets you find the shortest path/minimal distance from the starting node (consult an algorithms textbook for more details on that)

Daniel K
  • 56
  • 1
  • 3
  • Re "*There seems to be a misunderstanding on your part about how BFS works: Note that the point of keeping track of visited nodes, is to avoid crossing through back-edges*", Yes and no. The OP is trying to find the shortest path between two nodes in the tree, which requires building lists visited nodes (the potential paths). This is what was meant by remembering visited nodes in a previous discussion with the OP – ikegami Nov 24 '19 at 18:07
  • @NMDanny As for the diameter - if I understand you well - the only thing I have to do to find the diameter, is actually to call the BFS function multiple times? Each call contains as the startVertex - another child of the root? And the diameter is the sum of two maximal depths?.. As for the visited issue - I understand from your explanation that my visited array in the function is sufficient. As for the second question - Now I'm really confused. How does BFS find the shortest path exactly? And it takes only one vertex - so what do you mean by path in this context? – HelpMe Nov 24 '19 at 18:31