Первый проход
Я пытался решить один вопрос с интервью, но для этого мне нужно пройти уровень двоичного дерева по уровню. Я разработал BinaryNode со значением ниже переменной
private object data;
private BinaryNode left;
private BinaryNode right;
Может ли кто-нибудь помочь написать метод BreadthFirstSearch внутри моего класса BinarySearchTree?
Обновление: Спасибо всем за ваш вклад. Так что это был вопрос интервью.
"Учитывая двоичное дерево поиска, создайте алгоритм, который создает связанный список всех узлов на каждой глубине (т.е. Если у вас есть дерево с глубиной D, у вас есть D связанных списков)".
Вот мой метод, дайте мне знать ваш экспертный комментарий.
public List<LinkedList<BNode>> FindLevelLinkList(BNode root)
{
Queue<BNode> q = new Queue<BNode>();
// List of all nodes starting from root.
List<BNode> list = new List<BNode>();
q.Enqueue(root);
while (q.Count > 0)
{
BNode current = q.Dequeue();
if (current == null)
continue;
q.Enqueue(current.Left);
q.Enqueue(current.Right);
list.Add(current);
}
// Add tree nodes of same depth into individual LinkedList. Then add all LinkedList into a List
LinkedList<BNode> LL = new LinkedList<BNode>();
List<LinkedList<BNode>> result = new List<LinkedList<BNode>>();
LL.AddLast(root);
int currentDepth = 0;
foreach (BNode node in list)
{
if (node != root)
{
if (node.Depth == currentDepth)
{
LL.AddLast(node);
}
else
{
result.Add(LL);
LL = new LinkedList<BNode>();
LL.AddLast(node);
currentDepth++;
}
}
}
// Add the last linkedlist
result.Add(LL);
return result;
}
Ответы
Ответ 1
Первый поиск по ширине обычно выполняется с помощью очереди, сначала поиск глубины с использованием стека.
Queue<Node> q = new Queue<Node>();
q.Enqueue(root);
while(q.Count > 0)
{
Node current = q.Dequeue();
if(current == null)
continue;
q.Enqueue(current.Left);
q.Enqueue(current.Right);
DoSomething(current);
}
В качестве альтернативы проверке на null
после дезактивации вы можете проверить перед добавлением в очередь. Я не компилировал код, поэтому он может содержать некоторые небольшие ошибки.
Расширенная (но более медленная) версия, которая хорошо интегрируется с LINQ:
public static IEnumerable<T> BreadthFirstTopDownTraversal<T>(T root, Func<T, IEnumerable<T>> children)
{
var q = new Queue<T>();
q.Enqueue(root);
while (q.Count > 0)
{
T current = q.Dequeue();
yield return current;
foreach (var child in children(current))
q.Enqueue(child);
}
}
Что можно использовать вместе с свойством Children
на Node
:
IEnumerable<T> Children { get { return new []{node.Left, node.Right}.Where(x => x != null); } };
...
foreach(var element in BreadthFirstTopDownTraversal(root, node => node.Children)
{
...
}
Ответ 2
var queue = new Queue<BinaryNode>();
queue.Enqueue(rootNode);
while(queue.Any())
{
var currentNode = queue.Dequeue();
if(currentNode.data == searchedData)
{
break;
}
if(currentNode.Left != null)
queue.Enqueue(currentNode.Left);
if(currentNode.Right != null)
queue.Enqueue(currentNode.Right);
}
Ответ 3
с использованием подхода DFS: обход дерева - это O (n)
public class NodeLevel
{
public TreeNode Node { get; set;}
public int Level { get; set;}
}
public class NodeLevelList
{
private Dictionary<int,List<TreeNode>> finalLists = new Dictionary<int,List<TreeNode>>();
public void AddToDictionary(NodeLevel ndlvl)
{
if(finalLists.ContainsKey(ndlvl.Level))
{
finalLists[ndlvl.Level].Add(ndlvl.Node);
}
else
{
finalLists.Add(ndlvl.Level,new List<TreeNode>(){ndlvl.Node});
}
}
public Dictionary<int,List<TreeNode>> GetFinalList()
{
return finalLists;
}
}
Метод, который проходит обход:
public static void DFSLevel(TreeNode root, int level, NodeLevelList nodeLevelList)
{
if(root == null)
return;
nodeLevelList.AddToDictionary(new NodeLevel{Node = root, Level = level});
level++;
DFSLevel(root.Left,level,nodeLevelList);
DFSLevel(root.Right,level,nodeLevelList);
}