J'ai besoin de créer un catalogue de produits, sous forme d'arborescence.
chaque nœud d'arbre présente par un ID (chaîne), les fonctions sur les données d'arbre seulement 2:
getChild(string ID)
, donner un ID, obtenir des enfants (pas besoin d'inclure les enfants des enfants), si l'ID est nul, obtenir tous les nœuds racinegetParent(string ID)
, retourne l'ID parent si have, ou null si est rootDepuis qu'une fois l'arbre décidé, ne changera pas, donc je pense que mettre tout le code en statique sera le meilleur. Je commence donc à essayer d'utiliser le dictionnaire
"id": {parent:ID, child:[id2, id3, id4....]}
Depuis theres environ 1000+ catalogue, j'ai trouvé que je me gâche rapidement, beaucoup d'erreurs dans les données statiques et rend le résultat final utilisable. De plus, maintenant je n'en ai écrit que des dizaines et le code ressemble à du gâchis.
Veuillez conseiller une manière de créer cette arborescence de catalogue simple avec de hautes performances. Merci
Faites-en juste un cours.
MISE À JOUR:
class TreeNode : IEnumerable<TreeNode>
{
private readonly Dictionary<string, TreeNode> _children =
new Dictionary<string, TreeNode>();
public readonly string ID;
public TreeNode Parent { get; private set; }
public TreeNode(string id)
{
this.ID = id;
}
public TreeNode GetChild(string id)
{
return this._children[id];
}
public void Add(TreeNode item)
{
if (item.Parent != null)
{
item.Parent._children.Remove(item.ID);
}
item.Parent = this;
this._children.Add(item.ID, item);
}
public IEnumerator<TreeNode> GetEnumerator()
{
return this._children.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public int Count
{
get { return this._children.Count; }
}
}
L'utilisation sera assez simple à définir statiquement:
var tree = new TreeNode("Root")
{
new TreeNode("Category 1")
{
new TreeNode("Item 1"),
new TreeNode("Item 2"),
new TreeNode("Item 3"),
},
new TreeNode("Category 2")
{
new TreeNode("Item 1"),
new TreeNode("Item 2"),
new TreeNode("Item 3"),
new TreeNode("Item 4"),
}
};
Modifier
Encore plus de fonctionnalités pour une création encore plus facile ...
public static TreeNode BuildTree(string tree)
{
var lines = tree.Split(new[] { Environment.NewLine },
StringSplitOptions.RemoveEmptyEntries);
var result = new TreeNode("TreeRoot");
var list = new List<TreeNode> { result };
foreach (var line in lines)
{
var trimmedLine = line.Trim();
var indent = line.Length - trimmedLine.Length;
var child = new TreeNode(trimmedLine);
list[indent].Add(child);
if (indent + 1 < list.Count)
{
list[indent + 1] = child;
}
else
{
list.Add(child);
}
}
return result;
}
public static string BuildString(TreeNode tree)
{
var sb = new StringBuilder();
BuildString(sb, tree, 0);
return sb.ToString();
}
private static void BuildString(StringBuilder sb, TreeNode node, int depth)
{
sb.AppendLine(node.ID.PadLeft(node.ID.Length + depth));
foreach (var child in node)
{
BuildString(sb, child, depth + 1);
}
}
Utilisation:
var tree = TreeNode.BuildTree(@"
Cat1
Sub1
Item1
Item2
Item3
Sub2
Item1
Item2
Cat2
Sub1
Sub2
Item1
Item2
Sub3
Item1
Cat3
Cat4");
J'ai créé un Node class qui pourrait être utile. Il est rapide et possède des propriétés supplémentaires, comme:
Vous pouvez écrire un simple arbre binaire, j'écris le pseudo-code ci-dessous:
class TreeNode {
TreeNode Right;
TreeNode Left;
int id;
//...
}
class BinTree {
void Insert(TreeNode node)
{
while(true) {
if(node.id > target.id) {
if(target.Right != null) {
target = target.Right;
continue;
}
else {
target.Right = node;
break;
}
}
else if(node.id < target.id) {
if(target.Left != null) {
target = target.Left;
continue;
}
else {
target.Left = node;
break;
}
}
else {
throw new ArgumentException("Duplicated id");
}
}
}
TreeNode Search(int id)
{
TreeNode target = root;
while(target != null) {
if(id > target.id) {
target = target.Right;
}
else if(id < target.id) {
target = target.Left;
}
else {
return target;
}
}
return null;
}
}
Mais si votre nombre de données est très élevé, l'arborescence AVL est peut-être plus efficace