我想垂直遍历二叉树。我在Geeks for Cek中找到了一个工作代码。我想将它转换为C#,但我无法这样做。请指导我。
以下是我的尝试:
// we always need the address of the Root Node come what may!
public class BstNode
{
public int data { get; set; }
public BstNode left { get; set; }
public BstNode right { get; set; }
public BstNode(int value) => data = value;
}
public class BstTree
{
// For BST
public BstNode Insert(BstNode root, int data)
{
if (root == null)
{
root = new BstNode(data);
root.left = null;
root.right = null;
}
else if (data > root.data)
root.right = Insert(root.right, data);
else root.left = Insert(root.left, data);
return root;
}
// PROBLEM IN BELOW CODE
public void VerticalOrderTraverse(BstNode root)
{
// Base case
if (root == null)
return;
// Create a map and store vertical oder in
Dictionary<int, List<int>> dict = new Dictionary<int, List<int>>();
int hd = 0;
// Create queue to do level order traversal.
// Every item of queue contains node and
// horizontal distance.
Queue<Tuple<BstNode, int>> que = new Queue<Tuple<BstNode, int>>();
que.Enqueue(new Tuple<BstNode, int>(root, hd));
while (que.Count != 0)
{
// pop from queue front
Tuple<BstNode, int> temp = que.Peek();
que.Dequeue();
hd = temp.Item2;
BstNode node = temp.Item1;
// insert this node's data in vector of hash
dict.Add(hd, new List<int>(node.data)); // CONFUSED HERE
if (node.left != null)
que.Enqueue(new Tuple<BstNode, int>(node.left, hd - 1));
if (node.right != null)
que.Enqueue(new Tuple<BstNode, int>(node.right, hd + 1));
}
foreach (var item in dict)
foreach (var ite in item.Value)
Console.WriteLine(ite);
}
}
class Program
{
public static void Main()
{
BstNode root = null;
BstTree bstTree = new BstTree();
root = bstTree.Insert(root, 10);
root = bstTree.Insert(root, 12);
root = bstTree.Insert(root, 7);
root = bstTree.Insert(root, 8);
root = bstTree.Insert(root, 15);
root = bstTree.Insert(root, 11);
root = bstTree.Insert(root, 6);
bstTree.VerticalOrderTraverse(root);
}
}
请注意,我在&#34; VerticalOrderTraversal&#34;方法。 此VerticalOrderTraversal是Vertical Order Traversal in C++
的精确副本异常:密钥已存在于字典
中
修改
添加此检查后,Logic仍未提供正确的输出
if (dict.ContainsKey(hd))
dict[hd].Add(node.data);
else dict.Add(hd, new List<int>(node.data));
答案 0 :(得分:0)
你有这个:
dict.Add(hd, new List<int>(node.data));
原作有:
m[hd].push_back(node->key);
现在,当我们在documentation中查找运算符std::map::operator[]
的内容时,我们发现
如果k匹配容器中元素的键,则该函数返回对其映射值的引用。
而且重要的是,
如果k与容器中任何元素的键不匹配,则该函数会使用该键插入一个新元素
Dictionary<TKey, TValue>.Item
的索引器具有相同的功能(“set操作使用指定的键创建一个新元素”),但在C ++中,这意味着构造一个新的vector作为新元素的值,C#不会为我们创建List<int>
的实例,因此一个简单的解决方案可能是:
if (dict.ContainsKey(hd))
dict[hd].Add(node.data);
else dict.Add(hd, new List<int>(node.data));
答案 1 :(得分:0)
/// <summary>
/// We must calculate horizontal distance.
/// Each node along with its hd shall be queued.
/// Add hd and values in one hashset.
/// </summary>
/// <param name="root"></param>
public void VerticalOrderTraversal(Node<T> root)
{
if (root == null)
return;
int hd = 0;
Queue<Tuple<Node<T>,int>> q = new Queue<Tuple<Node<T>,int>>();
Dictionary<int, HashSet<T>> ht = new Dictionary<int, HashSet<T>>();
q.Enqueue(new Tuple<Node<T>, int>(root,hd));
ht[hd] = new HashSet<T>();
ht[hd].Add(root.Data);
while (q.Count > 0)
{
Tuple<Node<T>, int> current = q.Peek();
q.Dequeue();
if (current.Item1.leftNode != null)
{
if (!ht.ContainsKey(current.Item2 -1))
{
ht[current.Item2 - 1] = new HashSet<T>();
ht[current.Item2 - 1].Add(current.Item1.leftNode.Data);
}
else
{
ht[current.Item2 - 1].Add(current.Item1.leftNode.Data);
}
q.Enqueue(new Tuple<Node<T>, int>(current.Item1.leftNode, current.Item2 - 1));
}
if (current.Item1.rightNode != null)
{
if (!ht.ContainsKey(current.Item2 + 1))
{
ht[current.Item2 + 1] = new HashSet<T>();
ht[current.Item2 + 1].Add(current.Item1.rightNode.Data);
}
else
{
ht[current.Item2 + 1].Add(current.Item1.rightNode.Data);
}
q.Enqueue(new Tuple<Node<T>, int>(current.Item1.rightNode, current.Item2 + 1));
}
}
foreach (int key in ht.Keys)
{
foreach (T data in ht[key])
{
Console.WriteLine("Vertical Level " + key + " value " + data);
}
}
}
答案 2 :(得分:0)
我对原始代码进行了一些更改:
1.如果Dict中已经存在级别(hd),则需要将节点添加到列表的末尾,而不要插入新的级别和列表元组。所以我添加了if语句[if(dict.ContainsKey(hd))]
2.最好使用排序的字典,以便从最低级别打印,而不是从插入的第一级别打印。
3.在原始代码中,列表是在插入Dict时创建的,这是一个问题,因为node.data将被视为列表的容量,而不是列表中的数据。
public void VerticalOrderTraverse(BstNode root)
{
// Base case
if (root == null)
return;
// Create a map and store vertical oder in
SortedDictionary<int, List<int>> dict = new SortedDictionary<int, List<int>>(); //used Sorted Dictionary
int hd = 0;
Queue<Tuple<BstNode, int>> que = new Queue<Tuple<BstNode, int>>();
que.Enqueue(new Tuple<BstNode, int>(root, hd));
while (que.Count != 0)
{
Tuple<BstNode, int> temp = que.Peek();
que.Dequeue();
hd = temp.Item2;
BstNode node = temp.Item1;
if (dict.ContainsKey(hd)) //No need to try creating a new list, add it to the existing
dict[hd].Add(node.data);
else
{
dict.Add(hd, new List<int>());
dict[hd].Add(node.data);
}
if (node.left != null)
que.Enqueue(new Tuple<BstNode, int>(node.left, hd - 1));
if (node.right != null)
que.Enqueue(new Tuple<BstNode, int>(node.right, hd + 1));
}
foreach (var item in dict)
foreach (var ite in item.Value)
Console.WriteLine(ite);
}
}
}
}
答案 3 :(得分:0)
public class Solution {
public IList<IList<int>> result = new List<IList<int>>();
public SortedDictionary<int, List<int>> IndexingItems = new SortedDictionary<int, List<int>>();
public IList<IList<int>> VerticalTraversal(TreeNode root)
{
if(root == null) return result;
Queue<(int, TreeNode)> queue = new Queue<(int, TreeNode)>();
int hDis = 0;
queue.Enqueue((hDis, root));
while(queue.Count != 0)
{
(int, TreeNode) qTop = queue.Peek();
queue.Dequeue();
hDis = qTop.Item1;
TreeNode current = qTop.Item2;
AddItemToDictionary(hDis, current);
if(current.left != null)
{
queue.Enqueue((hDis - 1, current.left));
}
if(current.right != null)
{
queue.Enqueue((hDis + 1, current.right));
}
}
foreach(var item in IndexingItems)
{
var value = item.Value as List<int>;
result.Add(value);
}
return result;
}
public void AddItemToDictionary(int hDis, TreeNode node)
{
if(IndexingItems.ContainsKey(hDis))
{
IndexingItems[hDis].Add(node.val);
// Console.WriteLine($"Updating {hDis} value");
}
else
{
// Console.WriteLine($"Adding new item {hDis} to Dictionary with {node.val} value");
IndexingItems.Add(hDis, new List<int>(){ node.val });
}
}
}
我尝试过这种方法。但我不确定,为什么相同节点的数据顺序有一些不匹配。