我想开发一个二叉树结构,使每个节点都存储一个密钥和一个链表。这种实现背后的原因是我想在二叉树(二进制搜索树)中用适当的密钥进行搜索,链表将作为存储结构,我可以随时轻松地检索任何信息。任何人都可以帮我这个方法吗?或者如果有人能提出更好的方法,我们将不胜感激。
P.S:使用二叉树是由于搜索算法O(log n)的性能,并且链表的使用是由于结构必须是动态的,所以我不能使用数组,因为它的结构是静态的。
答案 0 :(得分:1)
您应该考虑使用其中一个内置的内容,例如此其他堆栈帖子中描述的SortedDictionary:Looking for a .NET binary tree
答案 1 :(得分:0)
NGenerics项目是一个很棒的数据结构和算法集合,包括Binary Tree。与LinkedList类一起使用,如:
BinaryTree<LinkedList<T>> tree;
答案 2 :(得分:0)
您应该使用Sorted Diccionary:“SortedDictionary(Of TKey,TValue)泛型类是一个带有O(log n)检索的二叉搜索树”,请查看文档:{{3}}
答案 3 :(得分:0)
您可以使用其他答案中提供的实现。如果您想了解如何自己编写,请参阅我的霍夫曼编码项目中的示例。它并不完美,但你可以看到一个普遍的想法。
我将从使用开始
class Program
{
static void Main(string[] args)
{
string[] testData = new string[] { "aa", "bbb", "cccccc", "d", "ee", "ffffff", "ggggg" };
var expected = new BinaryNode<string>("ffffff");
IBinaryTree<string> tree = new BinaryTree<string>();
tree.Build(testData);
var result = tree.Root.Traverse(expected, new List<IBinaryNode<string>>());
}
}
二进制节点接口和实现
public interface IBinaryNode<T>
{
int? ID { get; }
T Data { get; set; }
IBinaryNode<T> RightChild { get; set; }
IBinaryNode<T> LeftChild { get; set; }
IEnumerable<IBinaryNode<T>> Traverse(IBinaryNode<T> current, IEnumerable<IBinaryNode<T>> recursionData);
}
public class BinaryNode<T> : IBinaryNode<T>
{
public int? ID{get; private set;}
public T Data { get; set; }
public IBinaryNode<T> RightChild { get; set; }
public IBinaryNode<T> LeftChild { get; set; }
public BinaryNode():this(default(T)){}
public BinaryNode(T data):this(data, null){}
public BinaryNode(T data, int? id)
{
Data = data;
ID = id;
}
public IEnumerable<IBinaryNode<T>> Traverse(IBinaryNode<T> current, IEnumerable<IBinaryNode<T>> recursionData)
{
// no children found
if (RightChild == null && LeftChild == null)
{
//correct guess BinaryNode has the needed data
if (current.Data.Equals(Data))
{
return recursionData;
}
//wrong value - try another leg
return null;
}
//there are children
IEnumerable<IBinaryNode<T>> left = null; //tmp left storage
IEnumerable<IBinaryNode<T>> right = null; //tmp right storage
//start with the left child
//and travers in depth by left leg
if (LeftChild != null)
{
//go in depth through the left child
var leftPath = new List<IBinaryNode<T>>();
//add previously gathered recursionData
leftPath.AddRange(recursionData);
leftPath.Add(LeftChild);
//recursion call by rigth leg
left = LeftChild.Traverse(current, leftPath);
}
//no left children found
//travers by right leg in depth now
if (RightChild != null)
{
//go in depth through the right child
var rightPath = new List<IBinaryNode<T>>();
//add previously gathered recursionData
rightPath.AddRange(recursionData);
//add current value
rightPath.Add(RightChild);
//recursion call by rigth leg
right = RightChild.Traverse(current, rightPath);
}
//return collected value of left or right
if (left != null)
{
return left;
}
return right;
}
}
二叉树界面和实现
public interface IBinaryTree<T>
{
void Build(IEnumerable<T> source);
IBinaryNode<T> Root { get; set; }
}
public class BinaryTree<T> : IBinaryTree<T>
{
private readonly List<IBinaryNode<T>> nodes;
private int nodeId = 0;
public IBinaryNode<T> Root { get; set; }
public BinaryTree()
{
nodes = new List<IBinaryNode<T>>();
}
public bool IsLeaf(IBinaryNode<T> binaryNode)
{
return (binaryNode.LeftChild == null && binaryNode.RightChild == null);
}
public void Build(IEnumerable<T> source)
{
foreach (var item in source)
{
var node = new BinaryNode<T>(item, nodeId);
nodeId++;
nodes.Add(node);
}
//construct a tree
while (nodes.Count > 1) //while more than one node in a list
{
var taken = nodes.Take(2).ToList();
// Create a parent BinaryNode and sum probabilities
var parent = new BinaryNode<T>()
{
LeftChild = taken[0],
RightChild = taken[1]
};
//this has been added so remove from the topmost list
nodes.Remove(taken[0]);
nodes.Remove(taken[1]);
nodes.Add(parent);
}
Root = nodes.FirstOrDefault();
}
}