diff --git a/Algorithms.Tests/Graph/BreadthFirstTreeTraversalTests.cs b/Algorithms.Tests/Graph/BreadthFirstTreeTraversalTests.cs new file mode 100644 index 00000000..657e0df1 --- /dev/null +++ b/Algorithms.Tests/Graph/BreadthFirstTreeTraversalTests.cs @@ -0,0 +1,93 @@ +using Algorithms.Graph; +using NUnit.Framework; +using DataStructures.BinarySearchTree; +using System; + +namespace Algorithms.Tests.Graph +{ + public static class BreadthFirstTreeTraversalTests + { + [Test] + public static void CorrectLevelOrderTraversal() + { + // Arrange + int[] correctPath = { 7, 4, 13, 2, 5, 11, 15, 14, 16 }; + int[] insertionOrder = { 7, 13, 11, 15, 14, 4, 5, 16, 2 }; + BinarySearchTree testTree = new BinarySearchTree(); + foreach (int data in insertionOrder) + { + testTree.Add(data); + } + + // Act + int[] levelOrder = BreadthFirstTreeTraversal.LevelOrderTraversal(testTree); + + // Assert + Assert.AreEqual(levelOrder, correctPath); + } + + [Test] + public static void EmptyArrayForNullRoot() + { + // Arrange + BinarySearchTree testTree = new BinarySearchTree(); + + // Act + int[] levelOrder = BreadthFirstTreeTraversal.LevelOrderTraversal(testTree); + + // Assert + Assert.IsEmpty(levelOrder); + } + + [Test] + [TestCase(new [] {7, 9, 5})] + [TestCase(new [] { 7, 13, 11, 15, 14, 4, 5, 16, 2 })] + public static void IncorrectLevelOrderTraversal(int[] insertion) + { + // Arrange + BinarySearchTree testTree = new BinarySearchTree(); + foreach (int data in insertion) + { + testTree.Add(data); + } + + // Act + int[] levelOrder = BreadthFirstTreeTraversal.LevelOrderTraversal(testTree); + + // Assert + Assert.AreNotEqual(levelOrder, insertion); + } + + [Test] + public static void DeepestNodeInTree() + { + // Arrange + BinarySearchTree testTree = new BinarySearchTree(); + int[] insertion = { 7, 13, 11, 15, 4, 5, 12, 2, 9 }; + foreach (int data in insertion) + { + testTree.Add(data); + } + + // Act + int deepest = BreadthFirstTreeTraversal.DeepestNode(testTree); + + // Assert + Assert.AreEqual(12, deepest); + } + + [Test] + public static void DeepestNodeOfEmptyTree() + { + // Arrange + BinarySearchTree testTree = new BinarySearchTree(); + + // Act + int? deepest = BreadthFirstTreeTraversal.DeepestNode(testTree); + + // Assert + Assert.IsNull(deepest); + } + } +} + diff --git a/Algorithms/Graph/BreadthFirstTreeTraversal.cs b/Algorithms/Graph/BreadthFirstTreeTraversal.cs new file mode 100644 index 00000000..04b5ef0b --- /dev/null +++ b/Algorithms/Graph/BreadthFirstTreeTraversal.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using DataStructures.BinarySearchTree; + +namespace Algorithms.Graph +{ + /// + /// Breadth first tree traversal traverses through a binary tree + /// by iterating through each level first. + /// time complexity: O(n). + /// space complexity: O(w) where w is the max width of a binary tree. + /// + /// Type of key held in binary search tree. + public static class BreadthFirstTreeTraversal + { + /// + /// Level Order Traversal returns an array of integers in order + /// of each level of a binary tree. It uses a queue to iterate + /// through each node following breadth first search traversal. + /// + /// Passes the binary tree to traverse. + /// Returns level order traversal. + public static TKey[] LevelOrderTraversal(BinarySearchTree tree) + { + BinarySearchTreeNode? root = tree.Root; + TKey[] levelOrder = new TKey[tree.Count]; + if (root is null) + { + return Array.Empty(); + } + + Queue> breadthTraversal = new Queue>(); + breadthTraversal.Enqueue(root); + for (int i = 0; i < levelOrder.Length; i++) + { + BinarySearchTreeNode current = breadthTraversal.Dequeue(); + levelOrder[i] = current.Key; + if (current.Left is not null) + { + breadthTraversal.Enqueue(current.Left); + } + + if (current.Right is not null) + { + breadthTraversal.Enqueue(current.Right); + } + } + + return levelOrder; + } + + /// + /// Deepest Node return the deepest node in a binary tree. If more + /// than one node is on the deepest level, it is defined as the + /// right-most node of a binary tree. Deepest node uses breadth + /// first traversal to reach the end. + /// + /// Tree passed to find deepest node. + /// Returns the deepest node in the tree. + public static TKey? DeepestNode(BinarySearchTree tree) + { + BinarySearchTreeNode? root = tree.Root; + if (root is null) + { + return default(TKey); + } + + Queue> breadthTraversal = new Queue>(); + breadthTraversal.Enqueue(root); + TKey deepest = root.Key; + while (breadthTraversal.Count > 0) + { + BinarySearchTreeNode current = breadthTraversal.Dequeue(); + if (current.Left is not null) + { + breadthTraversal.Enqueue(current.Left); + } + + if (current.Right is not null) + { + breadthTraversal.Enqueue(current.Right); + } + + deepest = current.Key; + } + + return deepest; + } + } +} diff --git a/DataStructures/BinarySearchTree/BinarySearchTree.cs b/DataStructures/BinarySearchTree/BinarySearchTree.cs index b5138966..70a416a9 100644 --- a/DataStructures/BinarySearchTree/BinarySearchTree.cs +++ b/DataStructures/BinarySearchTree/BinarySearchTree.cs @@ -24,20 +24,20 @@ public class BinarySearchTree private readonly Comparer comparer; /// - /// The root of the BST. + /// Gets the root of the BST. /// - private BinarySearchTreeNode? root; + public BinarySearchTreeNode? Root { get; private set; } public BinarySearchTree() { - root = null; + Root = null; Count = 0; comparer = Comparer.Default; } public BinarySearchTree(Comparer customComparer) { - root = null; + Root = null; Count = 0; comparer = customComparer; } @@ -56,13 +56,13 @@ public BinarySearchTree(Comparer customComparer) /// public void Add(TKey key) { - if (root is null) + if (Root is null) { - root = new BinarySearchTreeNode(key); + Root = new BinarySearchTreeNode(key); } else { - Add(root, key); + Add(Root, key); } Count++; @@ -86,14 +86,14 @@ public void AddRange(IEnumerable keys) /// /// The key to search for. /// The node with the specified key if it exists, otherwise a default value is returned. - public BinarySearchTreeNode? Search(TKey key) => Search(root, key); + public BinarySearchTreeNode? Search(TKey key) => Search(Root, key); /// /// Checks if the specified key is in the BST. /// /// The key to search for. /// true if the key is in the BST, false otherwise. - public bool Contains(TKey key) => Search(root, key) is not null; + public bool Contains(TKey key) => Search(Root, key) is not null; /// /// Removes a node with a key that matches . @@ -102,12 +102,12 @@ public void AddRange(IEnumerable keys) /// true if the removal was successful, false otherwise. public bool Remove(TKey key) { - if (root is null) + if (Root is null) { return false; } - var result = Remove(root, root, key); + var result = Remove(Root, Root, key); if (result) { Count--; @@ -122,12 +122,12 @@ public bool Remove(TKey key) /// The node if possible, a default value otherwise. public BinarySearchTreeNode? GetMin() { - if (root is null) + if (Root is null) { return default; } - return GetMin(root); + return GetMin(Root); } /// @@ -136,31 +136,31 @@ public bool Remove(TKey key) /// The node if possible, a default value otherwise. public BinarySearchTreeNode? GetMax() { - if (root is null) + if (Root is null) { return default; } - return GetMax(root); + return GetMax(Root); } /// /// Returns all the keys in the BST, sorted In-Order. /// /// A list of keys in the BST. - public ICollection GetKeysInOrder() => GetKeysInOrder(root); + public ICollection GetKeysInOrder() => GetKeysInOrder(Root); /// /// Returns all the keys in the BST, sorted Pre-Order. /// /// A list of keys in the BST. - public ICollection GetKeysPreOrder() => GetKeysPreOrder(root); + public ICollection GetKeysPreOrder() => GetKeysPreOrder(Root); /// /// Returns all the keys in the BST, sorted Post-Order. /// /// A list of keys in the BST. - public ICollection GetKeysPostOrder() => GetKeysPostOrder(root); + public ICollection GetKeysPostOrder() => GetKeysPostOrder(Root); /// /// Recursive method to add a key to the BST. @@ -261,7 +261,7 @@ private bool Remove(BinarySearchTreeNode? parent, BinarySearchTreeNode(predecessorNode.Key) { Left = node.Left, @@ -271,9 +271,9 @@ private bool Remove(BinarySearchTreeNode? parent, BinarySearchTreeNode