DFS and BFS Traversal

DFS and BFS Traversal

What are DFS and BFS Traversal and what is the Difference between?

I was working on one of the TestDome tasks, where I needed to implement a closestRelative function that returns the closest relative child element of a specific element. I wasn’t able to solve the task until I fully understood the problem, which led me to dive deeper into two important algorithms: DFS and BFS.

Here’s Task Link :

https://www.testdome.com/library?page=1&skillArea=31&questionSets=public&questionTypes=code&questionId=110586

It passes 2 tests of 3 :

function closestRelative(
  parent,
  relativeName
) {
  if (parent.nodeName === relativeName.toUpperCase()) {
    return parent;
  }
  for (const child of Array.from(parent.children)) {
    const closestChild = closestRelative(child, relativeName);
    if (closestChild) {
      return closestChild;
    }
  }
  return null;
}

document.body.innerHTML =
  "<James>" +
  "  <ali>" +
  "    <Mike></Mike>" +
  "  </ali>" +
  "  <Mike></Mike>" +
  "  <Sarah>" +
  "    <Mike></Mike>" +
  "  </Sarah>" +
  "</James>";

// Example 
let parent = document.getElementsByTagName("James")[0];
let relative = closestRelative(parent, "Mike");
console.log(relative && relative.tagName); // prints MIKE

At Beginning , let’s understand the code and what’s the problem :

The code above first checks if the nodeName of the parent matches the relativeName (converted to uppercase). If they match, it directly returns the parent element. If not, Array.from() is used to convert the parent's children (an HTMLCollection) into an array, and then the function recursively searches through each child element using the closestRelative function. If a matching child is found, it returns the closest relative; otherwise, it returns null.

DFS:

The closestRelative function uses a depth-first search (DFS) approach. DFS explores one branch of the family tree as far as possible before backtracking :

DFS would first find the "Mike" inside the "ali" element, as it fully explores that branch before moving on. This is the incorrect result, as the "Mike" between "ali" and "Sarah" is the closest relative.

The issue with DFS is that it may not identify the closest relative when there are multiple elements with the same name, especially when nested at different levels. DFS returns the first match it finds, even if a closer relative exists elsewhere in the tree.

BFS:

The closestRelative function can be implemented using a breadth-first search (BFS) approach. BFS explores the family tree level by level, visiting all nodes at the current depth before moving on.

In the example HTML:

function closestRelative(
  parent,
  relativeName
) {
  const queue = Array.from(parent.children);
  const tagName = relativeName.toUpperCase();

  while (queue.length > 0) {
    const current = queue.shift();

    if (current?.tagName === tagName) {
      return current;
    }

    if (current?.hasChildNodes()) {
      queue.push(...Array.from(current.children));
    }
  }

  return null;
}

BFS would first find the "Mike" element between "ali" and "Sarah", as it visits all nodes at the current level before going deeper. This is the correct result, as this "Mike" is the closest relative.

The advantage of BFS is that it ensures the first matching element in the tree is always returned, even if it is nested deeper than other matches. This addresses the issue with the depth-first search (DFS) approach, which may not identify the closest relative when there are multiple elements with the same name at different levels.