Skip to content

Commit a27d4cf

Browse files
Dalfonso06Dalfonso06siriak
authored
Add Breadth First Tree Traversal (TheAlgorithms#364)
Co-authored-by: Dalfonso06 <[email protected]> Co-authored-by: Andrii Siriak <[email protected]>
1 parent 8b49dce commit a27d4cf

File tree

4 files changed

+205
-21
lines changed

4 files changed

+205
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using Algorithms.Graph;
2+
using NUnit.Framework;
3+
using DataStructures.BinarySearchTree;
4+
using System;
5+
6+
namespace Algorithms.Tests.Graph
7+
{
8+
public static class BreadthFirstTreeTraversalTests
9+
{
10+
[Test]
11+
public static void CorrectLevelOrderTraversal()
12+
{
13+
// Arrange
14+
int[] correctPath = { 7, 4, 13, 2, 5, 11, 15, 14, 16 };
15+
int[] insertionOrder = { 7, 13, 11, 15, 14, 4, 5, 16, 2 };
16+
BinarySearchTree<int> testTree = new BinarySearchTree<int>();
17+
foreach (int data in insertionOrder)
18+
{
19+
testTree.Add(data);
20+
}
21+
22+
// Act
23+
int[] levelOrder = BreadthFirstTreeTraversal<int>.LevelOrderTraversal(testTree);
24+
25+
// Assert
26+
Assert.AreEqual(levelOrder, correctPath);
27+
}
28+
29+
[Test]
30+
public static void EmptyArrayForNullRoot()
31+
{
32+
// Arrange
33+
BinarySearchTree<int> testTree = new BinarySearchTree<int>();
34+
35+
// Act
36+
int[] levelOrder = BreadthFirstTreeTraversal<int>.LevelOrderTraversal(testTree);
37+
38+
// Assert
39+
Assert.IsEmpty(levelOrder);
40+
}
41+
42+
[Test]
43+
[TestCase(new [] {7, 9, 5})]
44+
[TestCase(new [] { 7, 13, 11, 15, 14, 4, 5, 16, 2 })]
45+
public static void IncorrectLevelOrderTraversal(int[] insertion)
46+
{
47+
// Arrange
48+
BinarySearchTree<int> testTree = new BinarySearchTree<int>();
49+
foreach (int data in insertion)
50+
{
51+
testTree.Add(data);
52+
}
53+
54+
// Act
55+
int[] levelOrder = BreadthFirstTreeTraversal<int>.LevelOrderTraversal(testTree);
56+
57+
// Assert
58+
Assert.AreNotEqual(levelOrder, insertion);
59+
}
60+
61+
[Test]
62+
public static void DeepestNodeInTree()
63+
{
64+
// Arrange
65+
BinarySearchTree<int> testTree = new BinarySearchTree<int>();
66+
int[] insertion = { 7, 13, 11, 15, 4, 5, 12, 2, 9 };
67+
foreach (int data in insertion)
68+
{
69+
testTree.Add(data);
70+
}
71+
72+
// Act
73+
int deepest = BreadthFirstTreeTraversal<int>.DeepestNode(testTree);
74+
75+
// Assert
76+
Assert.AreEqual(12, deepest);
77+
}
78+
79+
[Test]
80+
public static void DeepestNodeOfEmptyTree()
81+
{
82+
// Arrange
83+
BinarySearchTree<int?> testTree = new BinarySearchTree<int?>();
84+
85+
// Act
86+
int? deepest = BreadthFirstTreeTraversal<int?>.DeepestNode(testTree);
87+
88+
// Assert
89+
Assert.IsNull(deepest);
90+
}
91+
}
92+
}
93+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using DataStructures.BinarySearchTree;
4+
5+
namespace Algorithms.Graph
6+
{
7+
/// <summary>
8+
/// Breadth first tree traversal traverses through a binary tree
9+
/// by iterating through each level first.
10+
/// time complexity: O(n).
11+
/// space complexity: O(w) where w is the max width of a binary tree.
12+
/// </summary>
13+
/// <typeparam name="TKey">Type of key held in binary search tree.</typeparam>
14+
public static class BreadthFirstTreeTraversal<TKey>
15+
{
16+
/// <summary>
17+
/// Level Order Traversal returns an array of integers in order
18+
/// of each level of a binary tree. It uses a queue to iterate
19+
/// through each node following breadth first search traversal.
20+
/// </summary>
21+
/// <param name="tree">Passes the binary tree to traverse.</param>
22+
/// <returns>Returns level order traversal.</returns>
23+
public static TKey[] LevelOrderTraversal(BinarySearchTree<TKey> tree)
24+
{
25+
BinarySearchTreeNode<TKey>? root = tree.Root;
26+
TKey[] levelOrder = new TKey[tree.Count];
27+
if (root is null)
28+
{
29+
return Array.Empty<TKey>();
30+
}
31+
32+
Queue<BinarySearchTreeNode<TKey>> breadthTraversal = new Queue<BinarySearchTreeNode<TKey>>();
33+
breadthTraversal.Enqueue(root);
34+
for (int i = 0; i < levelOrder.Length; i++)
35+
{
36+
BinarySearchTreeNode<TKey> current = breadthTraversal.Dequeue();
37+
levelOrder[i] = current.Key;
38+
if (current.Left is not null)
39+
{
40+
breadthTraversal.Enqueue(current.Left);
41+
}
42+
43+
if (current.Right is not null)
44+
{
45+
breadthTraversal.Enqueue(current.Right);
46+
}
47+
}
48+
49+
return levelOrder;
50+
}
51+
52+
/// <summary>
53+
/// Deepest Node return the deepest node in a binary tree. If more
54+
/// than one node is on the deepest level, it is defined as the
55+
/// right-most node of a binary tree. Deepest node uses breadth
56+
/// first traversal to reach the end.
57+
/// </summary>
58+
/// <param name="tree">Tree passed to find deepest node.</param>
59+
/// <returns>Returns the deepest node in the tree.</returns>
60+
public static TKey? DeepestNode(BinarySearchTree<TKey> tree)
61+
{
62+
BinarySearchTreeNode<TKey>? root = tree.Root;
63+
if (root is null)
64+
{
65+
return default(TKey);
66+
}
67+
68+
Queue<BinarySearchTreeNode<TKey>> breadthTraversal = new Queue<BinarySearchTreeNode<TKey>>();
69+
breadthTraversal.Enqueue(root);
70+
TKey deepest = root.Key;
71+
while (breadthTraversal.Count > 0)
72+
{
73+
BinarySearchTreeNode<TKey> current = breadthTraversal.Dequeue();
74+
if (current.Left is not null)
75+
{
76+
breadthTraversal.Enqueue(current.Left);
77+
}
78+
79+
if (current.Right is not null)
80+
{
81+
breadthTraversal.Enqueue(current.Right);
82+
}
83+
84+
deepest = current.Key;
85+
}
86+
87+
return deepest;
88+
}
89+
}
90+
}

DataStructures/BinarySearchTree/BinarySearchTree.cs

+21-21
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ public class BinarySearchTree<TKey>
2424
private readonly Comparer<TKey> comparer;
2525

2626
/// <summary>
27-
/// The root of the BST.
27+
/// Gets the root of the BST.
2828
/// </summary>
29-
private BinarySearchTreeNode<TKey>? root;
29+
public BinarySearchTreeNode<TKey>? Root { get; private set; }
3030

3131
public BinarySearchTree()
3232
{
33-
root = null;
33+
Root = null;
3434
Count = 0;
3535
comparer = Comparer<TKey>.Default;
3636
}
3737

3838
public BinarySearchTree(Comparer<TKey> customComparer)
3939
{
40-
root = null;
40+
Root = null;
4141
Count = 0;
4242
comparer = customComparer;
4343
}
@@ -56,13 +56,13 @@ public BinarySearchTree(Comparer<TKey> customComparer)
5656
/// </exception>
5757
public void Add(TKey key)
5858
{
59-
if (root is null)
59+
if (Root is null)
6060
{
61-
root = new BinarySearchTreeNode<TKey>(key);
61+
Root = new BinarySearchTreeNode<TKey>(key);
6262
}
6363
else
6464
{
65-
Add(root, key);
65+
Add(Root, key);
6666
}
6767

6868
Count++;
@@ -86,14 +86,14 @@ public void AddRange(IEnumerable<TKey> keys)
8686
/// </summary>
8787
/// <param name="key">The key to search for.</param>
8888
/// <returns>The node with the specified key if it exists, otherwise a default value is returned.</returns>
89-
public BinarySearchTreeNode<TKey>? Search(TKey key) => Search(root, key);
89+
public BinarySearchTreeNode<TKey>? Search(TKey key) => Search(Root, key);
9090

9191
/// <summary>
9292
/// Checks if the specified key is in the BST.
9393
/// </summary>
9494
/// <param name="key">The key to search for.</param>
9595
/// <returns>true if the key is in the BST, false otherwise.</returns>
96-
public bool Contains(TKey key) => Search(root, key) is not null;
96+
public bool Contains(TKey key) => Search(Root, key) is not null;
9797

9898
/// <summary>
9999
/// Removes a node with a key that matches <paramref name="key" />.
@@ -102,12 +102,12 @@ public void AddRange(IEnumerable<TKey> keys)
102102
/// <returns>true if the removal was successful, false otherwise.</returns>
103103
public bool Remove(TKey key)
104104
{
105-
if (root is null)
105+
if (Root is null)
106106
{
107107
return false;
108108
}
109109

110-
var result = Remove(root, root, key);
110+
var result = Remove(Root, Root, key);
111111
if (result)
112112
{
113113
Count--;
@@ -122,12 +122,12 @@ public bool Remove(TKey key)
122122
/// <returns>The node if possible, a default value otherwise.</returns>
123123
public BinarySearchTreeNode<TKey>? GetMin()
124124
{
125-
if (root is null)
125+
if (Root is null)
126126
{
127127
return default;
128128
}
129129

130-
return GetMin(root);
130+
return GetMin(Root);
131131
}
132132

133133
/// <summary>
@@ -136,31 +136,31 @@ public bool Remove(TKey key)
136136
/// <returns>The node if possible, a default value otherwise.</returns>
137137
public BinarySearchTreeNode<TKey>? GetMax()
138138
{
139-
if (root is null)
139+
if (Root is null)
140140
{
141141
return default;
142142
}
143143

144-
return GetMax(root);
144+
return GetMax(Root);
145145
}
146146

147147
/// <summary>
148148
/// Returns all the keys in the BST, sorted In-Order.
149149
/// </summary>
150150
/// <returns>A list of keys in the BST.</returns>
151-
public ICollection<TKey> GetKeysInOrder() => GetKeysInOrder(root);
151+
public ICollection<TKey> GetKeysInOrder() => GetKeysInOrder(Root);
152152

153153
/// <summary>
154154
/// Returns all the keys in the BST, sorted Pre-Order.
155155
/// </summary>
156156
/// <returns>A list of keys in the BST.</returns>
157-
public ICollection<TKey> GetKeysPreOrder() => GetKeysPreOrder(root);
157+
public ICollection<TKey> GetKeysPreOrder() => GetKeysPreOrder(Root);
158158

159159
/// <summary>
160160
/// Returns all the keys in the BST, sorted Post-Order.
161161
/// </summary>
162162
/// <returns>A list of keys in the BST.</returns>
163-
public ICollection<TKey> GetKeysPostOrder() => GetKeysPostOrder(root);
163+
public ICollection<TKey> GetKeysPostOrder() => GetKeysPostOrder(Root);
164164

165165
/// <summary>
166166
/// Recursive method to add a key to the BST.
@@ -261,7 +261,7 @@ private bool Remove(BinarySearchTreeNode<TKey>? parent, BinarySearchTreeNode<TKe
261261
else
262262
{
263263
var predecessorNode = GetMax(node.Left);
264-
Remove(root, root, predecessorNode.Key);
264+
Remove(Root, Root, predecessorNode.Key);
265265
replacementNode = new BinarySearchTreeNode<TKey>(predecessorNode.Key)
266266
{
267267
Left = node.Left,
@@ -271,9 +271,9 @@ private bool Remove(BinarySearchTreeNode<TKey>? parent, BinarySearchTreeNode<TKe
271271

272272
// Replace the relevant node with a replacement found in the previous stages.
273273
// Special case for replacing the root node.
274-
if (node == root)
274+
if (node == Root)
275275
{
276-
root = replacementNode;
276+
Root = replacementNode;
277277
}
278278
else if (parent.Left == node)
279279
{

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ find more than one implementation for the same objective but using different alg
3636
* [Minimum Spanning Tree](./Algorithms/Graph/MinimumSpanningTree)
3737
* [Prim's Algorithm (Adjacency Matrix)](./Algorithms/Graph/MinimumSpanningTree/PrimMatrix.cs)
3838
* [Kruskal's Algorithm](./Algorithms/Graph/MinimumSpanningTree/Kruskal.cs)
39+
* [BreadthFirstTreeTraversal](./Algorithms/Graph/BreadthFirstTreeTraversal.cs)
3940
* [BreadthFirstSearch](./Algorithms/Graph/BreadthFirstSearch.cs)
4041
* [DepthFirstSearch](./Algorithms/Graph/DepthFirstSearch.cs)
4142
* [Dijkstra Shortest Path](./Algorithms/Graph/Dijkstra/DijkstraAlgorithm.cs)

0 commit comments

Comments
 (0)