C # 'da ağaç veri yapısı


248

C # bir ağaç veya grafik veri yapısı arıyordum ama sanırım sağlanan biri yok. C # 2.0 Kullanarak Veri Yapılarının Kapsamlı İncelenmesi Nedenini biraz açıklıyor. Bu işlevselliği sağlamak için yaygın olarak kullanılan uygun bir kütüphane var mı? Belki de makalede sunulan sorunları çözmek için bir strateji modeli aracılığıyla.

Kendi ArrayList'imi uyguladığım gibi, kendi ağacımı uygularken biraz aptal hissediyorum.

Sadece dengesiz olabilen jenerik bir ağaç istiyorum. Bir dizin ağacı düşünün. C5 şık görünüyor, ancak ağaç yapıları, bir düğüm hiyerarşisini temsil etmektense, arama için daha uygun dengeli kırmızı-siyah ağaçlar olarak uygulanmış gibi görünüyor.


2
Biraz daha aşırı ağaçlar: stackoverflow.com/questions/196294/… ;-)
Tuomas Hietanen

Bir projeye bir TreeView dahil etmek ve kullanmak için bir nedeni var mı? Bir kullanıcıya gösterilmesi için hiçbir neden yoktur. Tabii ki bu bir seçenek olmadığında birkaç proje türü vardır. Özel karmaşıklık gerekiyorsa, örneğin TreeNode'dan miras alan yeni sınıflar oluşturulabilir?
Simply G.

9
Çok basit bir ağaç için tüm bir UI kütüphanesini içe aktarmanın kötü bir fikir olduğunu düşünürdüm.
stimms

1
Motive edebilir misiniz? Gerçek sabit disk alanı gereksinimi gibi değil artık bir sorun mu? Sakar? Daha önce de belirttiğim gibi, bunun özel bir yazılım veya mevcut bir kullanıcı arayüzü olmayan bir şey için bir çözüm olmadığını anlayabilirim. Tembel bir programcıyım, eğer ücretsiz bir yapı elde edersem her şey yolunda. Ve mevcut bir kütüphanenin ücretsiz bir çok şey var, bir çok şey için onu kullanan insanlardan bir sürü kod bulabilirsiniz.
Simply G.

1
İşte size basit bir ağaç türüdür: public class Tree<T> : List<Tree<T>> { public T Value; }.
Enigmativity

Yanıtlar:


155

En iyi tavsiyem, standart ağaç veri yapısının olmamasıdır, çünkü onu uygulayabilmenin birçok yolu vardır, tüm üsleri tek bir çözümle örtmek imkansızdır. Bir çözüm ne kadar spesifik olursa, verilen herhangi bir sorun için geçerli olma olasılığı o kadar az olur. LinkedList ile bile rahatsız oluyorum - dairesel bir bağlantılı liste istersem ne olur?

Uygulamanız gereken temel yapı bir düğüm koleksiyonu olacaktır ve işte başlamanız için bazı seçenekler. Diyelim ki Node sınıfı, tüm çözümün temel sınıfıdır.

Yalnızca ağaçta gezinmeniz gerekiyorsa, bir Düğüm sınıfında bir Çocuk Listesi gerekir.

Ağacın üzerinde gezinmeniz gerekiyorsa, Düğüm sınıfının üst düğümüne bir bağlantıya ihtiyacı vardır.

Bu iki noktanın tüm minutilerini ve uygulanması gereken diğer iş mantığını (çocuk sınırları, çocukları sıralamak vb.) Halleden bir AddChild yöntemi oluşturun.


5
Şahsen ben sadece bir bitişik liste kullanmaktan biraz ekstra çalışma olduğu için kütüphaneye eklenecek kendini dengeleme ikili ağaç bir tür sakıncası olmaz.
jk.

8
@jk SortedDictionary ve SortedSet'in kırmızı / siyah ağaçların üstüne inşa edildiğine inanıyorum, bu yüzden bunları kullanmak işe yarayacak.
jonp

Kompozit desene bir göz atın ;-) Tam olarak aradığınızı
Nicolas Voron

119
delegate void TreeVisitor<T>(T nodeData);

class NTree<T>
{
    private T data;
    private LinkedList<NTree<T>> children;

    public NTree(T data)
    {
         this.data = data;
        children = new LinkedList<NTree<T>>();
    }

    public void AddChild(T data)
    {
        children.AddFirst(new NTree<T>(data));
    }

    public NTree<T> GetChild(int i)
    {
        foreach (NTree<T> n in children)
            if (--i == 0)
                return n;
        return null;
    }

    public void Traverse(NTree<T> node, TreeVisitor<T> visitor)
    {
        visitor(node.data);
        foreach (NTree<T> kid in node.children)
            Traverse(kid, visitor);
    }
}

Basit özyinelemeli uygulama ... <40 kod satırı ... Sadece sınıfın dışında ağacın köküne bir referans tutmak veya başka bir sınıfta, belki TreeNode yeniden adlandırmak gerekiyor?


22
Bu durumda, yine C #, kendi temsilci yazılmasını önlemek ve önceden yapılmış kullanabilirsiniz Action<T>temsilci: public void traverse(NTree<T> node, Action<T> visitor). Eylem <> 'nın imzadır: void Action<T>( T obj ). Ayrıca 0 ila 4 farklı parametrenin sürümleri de vardır. Ayrıca adlandırılan işlevler için benzer bir delege var Func<>.
Benny Jobigan

2
bu delege nasıl diyebilirim?
Çılgınca

3
travers yöntemini statik olarak değiştirmek veya özyinelemeli doğayı gizlemek için muhtemelen sarmak iyi bir fikir olacaktır, ancak çapraz geçiş basittir: delege imzasıyla bir yöntem oluşturun, yani bir ints ağacı için: void my_visitor_impl (int datum) - gerekiyorsa statik hale getirin, bir delgate başlatın: TreeVisitor <int> my_visitor = my_visitor_impl; ve sonra u statik hale getirirseniz kök düğümü veya NTree sınıfını çağırır: NTree <int> .traverse (my_tree, my_visitor)
Aaron Gage

10
AddChild () yönteminin döndürdüğü NTree, ağaca veri eklemeyi daha iyi hale getirir. (Yeni eklenen bir çocuğun == getChild (1)? Uygulama detayına dayanmadan, bununla bir ağaç inşa etmek için kurnaz bir yol eksik olmadığı sürece)
Rory

1
Bu ifadenin --i == 0sadece tek bir durumda işlev göreceğini düşünüyorum ? Bu doğru mu. Bu beni şaşırttı
Waseem Ahmad Naeem

57

Bence Aaron Gage'inkine çok benzeyen benim. Benim amacım için herhangi bir performans sorunuyla karşılaşmadım List<T>. Gerekirse bir LinkedList'e geçmek yeterince kolay olurdu.


namespace Overby.Collections
{
    public class TreeNode<T>
    {
        private readonly T _value;
        private readonly List<TreeNode<T>> _children = new List<TreeNode<T>>();

        public TreeNode(T value)
        {
            _value = value;
        }

        public TreeNode<T> this[int i]
        {
            get { return _children[i]; }
        }

        public TreeNode<T> Parent { get; private set; }

        public T Value { get { return _value; } }

        public ReadOnlyCollection<TreeNode<T>> Children
        {
            get { return _children.AsReadOnly(); }
        }

        public TreeNode<T> AddChild(T value)
        {
            var node = new TreeNode<T>(value) {Parent = this};
            _children.Add(node);
            return node;
        }

        public TreeNode<T>[] AddChildren(params T[] values)
        {
            return values.Select(AddChild).ToArray();
        }

        public bool RemoveChild(TreeNode<T> node)
        {
            return _children.Remove(node);
        }

        public void Traverse(Action<T> action)
        {
            action(Value);
            foreach (var child in _children)
                child.Traverse(action);
        }

        public IEnumerable<T> Flatten()
        {
            return new[] {Value}.Concat(_children.SelectMany(x => x.Flatten()));
        }
    }
}

Value özelliği yapıcıda ayarladığınızda neden gösteriliyor? zaten kurucu aracılığıyla ayarladıktan SONRA manipülasyon için açık bırakıyor değil mi? Özel set olmalı mı?
PositiveGuy

Tabii, neden değişmez hale getirmiyorsun? Düzenlenen.
Ronnie Overby

Teşekkürler! Kendi yazmak zorunda değil oldukça hoşuma gitti. (Hala bunun doğal bir şey olmadığına inanamıyorum. Her zaman .net veya en azından .net 4.0'da her şeye sahip olduğumu düşündüm .)
neminem

3
Bu çözümü beğendim. Ayrıca eklemek için gerekli buldum, bunu yapmak için aşağıdaki yöntemi ekledim. public TreeNode<T> InsertChild(TreeNode<T> parent, T value) { var node = new TreeNode<T>(value) { Parent = parent }; parent._children.Add(node); return node; } var five = myTree.AddChild(5); myTree.InsertChild(five, 55);
JabberwockyDecompiler

48

Yine başka bir ağaç yapısı:

public class TreeNode<T> : IEnumerable<TreeNode<T>>
{

    public T Data { get; set; }
    public TreeNode<T> Parent { get; set; }
    public ICollection<TreeNode<T>> Children { get; set; }

    public TreeNode(T data)
    {
        this.Data = data;
        this.Children = new LinkedList<TreeNode<T>>();
    }

    public TreeNode<T> AddChild(T child)
    {
        TreeNode<T> childNode = new TreeNode<T>(child) { Parent = this };
        this.Children.Add(childNode);
        return childNode;
    }

    ... // for iterator details see below link
}

Örnek kullanım:

TreeNode<string> root = new TreeNode<string>("root");
{
    TreeNode<string> node0 = root.AddChild("node0");
    TreeNode<string> node1 = root.AddChild("node1");
    TreeNode<string> node2 = root.AddChild("node2");
    {
        TreeNode<string> node20 = node2.AddChild(null);
        TreeNode<string> node21 = node2.AddChild("node21");
        {
            TreeNode<string> node210 = node21.AddChild("node210");
            TreeNode<string> node211 = node21.AddChild("node211");
        }
    }
    TreeNode<string> node3 = root.AddChild("node3");
    {
        TreeNode<string> node30 = node3.AddChild("node30");
    }
}

BONUS
Tam teşekküllü ağaca bakın:

  • yineleyici
  • Aranıyor
  • Java / C #

https://github.com/gt4dev/yet-another-tree-structure


Aramayı kod örneğinizde nasıl kullanabilirim? Nereden nodegeliyor? Arama kodunu kullanmak için ağacın üzerinde yinelemem gerektiği anlamına mı geliyor?
BadmintonCat

@GrzegorzDev Belki -1 çünkü tüm IEnumerable<>üyeleri uygulamaz , bu yüzden derlemez .
Uwe Keim

1
@UweKeim İyi İş, bir dahaki sefere kodu gerçek kullanıcılarla kullanmayı deneyin.
szab.kel

gördüğüm tek sorun doğru IEnumerable <> uygulamak gibi temel JsonConvert ile seri hale getirilmeyecek
Rakiah

22

Genel olarak mükemmel C5 Genel Koleksiyon Kütüphanesi , setler, çantalar ve sözlükler dahil olmak üzere birkaç farklı ağaç tabanlı veri yapısına sahiptir. Uygulama ayrıntılarını incelemek istiyorsanız kaynak kodu kullanılabilir. (C5 koleksiyonlarını iyi sonuçlarla üretim kodunda kullandım, ancak özellikle ağaç yapılarını kullanmadım.)


7
Belki bir şeylerin değişip değişmediğini bilmiyorum ama şu anda kitap C5 sitesinden PDF olarak indirilebilir.
Oskar

4
Kütüphaneyi tamamlayan 272 sayfa uzunluğunda bir pdf olduğu için dokümantasyon eksikliği artık endişe etmiyor ... Kod kalitesi hakkında yorum yapamıyorum, ancak dokümanın kalitesinden yola çıkarak gerçekten bu gece bu işe girmeyi dört gözle bekliyorum!
Florian Doyon

2
Anladığım kadarıyla, bu C5 kütüphanesinde hiç ağaç yok, sadece bazı ağaç kaynaklı veri yapıları var.
roim

10

Bkz. Http://quickgraph.codeplex.com/

QuickGraph .Net 2.0 ve üstü için genel yönlendirilmiş / yönlendirilmemiş grafik veri yapıları ve algoritmalar sağlar. QuickGraph, önce derinlik arama, ilk nefes arama, A * arama, en kısa yol, k-en kısa yol, maksimum akış, minimum yayılan ağaç, en az yaygın atalar gibi algoritmalar ile birlikte gelir ... QuickGraph MSAGL, GLEE ve Graphviz'i destekler grafikleri renderleme, GraphML'e serileştirme, vb ...


8

Kendi yazınızı yazmak isterseniz, C # 2.0 veri yapılarının etkin kullanımını ve C # 'daki veri yapılarının uygulamanızı nasıl analiz edeceğinizi ayrıntılarıyla anlatan bu altı bölümlü belgeyle başlayabilirsiniz. Her makalede örnekler ve takip edebileceğiniz örnekler içeren bir yükleyici vardır.

“C # 2.0 Kullanarak Veri Yapılarının Kapsamlı Bir İncelenmesi” Scott Mitchell


7

Çözümlere küçük bir uzantım var.

Özyinelemeli genel bildirim ve türetici bir alt sınıf kullanarak, gerçek hedefinize daha iyi konsantre olabilirsiniz.

Dikkat edin, genel olmayan bir uygulamadan farklıdır, 'NodeWorker'da' düğüm 'atmanız gerekmez.

İşte benim örnek:

public class GenericTree<T> where T : GenericTree<T> // recursive constraint  
{
  // no specific data declaration  

  protected List<T> children;

  public GenericTree()
  {
    this.children = new List<T>();
  }

  public virtual void AddChild(T newChild)
  {
    this.children.Add(newChild);
  }

  public void Traverse(Action<int, T> visitor)
  {
    this.traverse(0, visitor);
  }

  protected virtual void traverse(int depth, Action<int, T> visitor)
  {
    visitor(depth, (T)this);
    foreach (T child in this.children)
      child.traverse(depth + 1, visitor);
  }
}

public class GenericTreeNext : GenericTree<GenericTreeNext> // concrete derivation
{
  public string Name {get; set;} // user-data example

  public GenericTreeNext(string name)
  {
    this.Name = name;
  }
}

static void Main(string[] args)  
{  
  GenericTreeNext tree = new GenericTreeNext("Main-Harry");  
  tree.AddChild(new GenericTreeNext("Main-Sub-Willy"));  
  GenericTreeNext inter = new GenericTreeNext("Main-Inter-Willy");  
  inter.AddChild(new GenericTreeNext("Inter-Sub-Tom"));  
  inter.AddChild(new GenericTreeNext("Inter-Sub-Magda"));  
  tree.AddChild(inter);  
  tree.AddChild(new GenericTreeNext("Main-Sub-Chantal"));  
  tree.Traverse(NodeWorker);  
}  

static void NodeWorker(int depth, GenericTreeNext node)  
{                                // a little one-line string-concatenation (n-times)
  Console.WriteLine("{0}{1}: {2}", String.Join("   ", new string[depth + 1]), depth, node.Name);  
}  

derinlik nedir ve nereden ve nasıl alırsınız?
PositiveGuy

@ WeDoTDD.com kendi sınıfına bakarak Traverse'un kök düğümde başlaması için 0 olduğunu bildirir, sonra her yinelemede o int'e ekleme yöntemini kullanır.
Edward

Belirli bir düğüm için tüm ağacı nasıl ararsınız?
mattpm

6

İşte benim:

class Program
{
    static void Main(string[] args)
    {
        var tree = new Tree<string>()
            .Begin("Fastfood")
                .Begin("Pizza")
                    .Add("Margherita")
                    .Add("Marinara")
                .End()
                .Begin("Burger")
                    .Add("Cheese burger")
                    .Add("Chili burger")
                    .Add("Rice burger")
                .End()
            .End();

        tree.Nodes.ForEach(p => PrintNode(p, 0));
        Console.ReadKey();
    }

    static void PrintNode<T>(TreeNode<T> node, int level)
    {
        Console.WriteLine("{0}{1}", new string(' ', level * 3), node.Value);
        level++;
        node.Children.ForEach(p => PrintNode(p, level));
    }
}

public class Tree<T>
{
    private Stack<TreeNode<T>> m_Stack = new Stack<TreeNode<T>>();

    public List<TreeNode<T>> Nodes { get; } = new List<TreeNode<T>>();

    public Tree<T> Begin(T val)
    {
        if (m_Stack.Count == 0)
        {
            var node = new TreeNode<T>(val, null);
            Nodes.Add(node);
            m_Stack.Push(node);
        }
        else
        {
            var node = m_Stack.Peek().Add(val);
            m_Stack.Push(node);
        }

        return this;
    }

    public Tree<T> Add(T val)
    {
        m_Stack.Peek().Add(val);
        return this;
    }

    public Tree<T> End()
    {
        m_Stack.Pop();
        return this;
    }
}

public class TreeNode<T>
{
    public T Value { get; }
    public TreeNode<T> Parent { get; }
    public List<TreeNode<T>> Children { get; }

    public TreeNode(T val, TreeNode<T> parent)
    {
        Value = val;
        Parent = parent;
        Children = new List<TreeNode<T>>();
    }

    public TreeNode<T> Add(T val)
    {
        var node = new TreeNode<T>(val, this);
        Children.Add(node);
        return node;
    }
}

Çıktı:

Fastfood
   Pizza
      Margherita
      Marinara
   Burger
      Cheese burger
      Chili burger
      Rice burger

4

Bu basit örneği deneyin.

public class TreeNode<TValue>
{
    #region Properties
    public TValue Value { get; set; }
    public List<TreeNode<TValue>> Children { get; private set; }
    public bool HasChild { get { return Children.Any(); } }
    #endregion
    #region Constructor
    public TreeNode()
    {
        this.Children = new List<TreeNode<TValue>>();
    }
    public TreeNode(TValue value)
        : this()
    {
        this.Value = value;
    }
    #endregion
    #region Methods
    public void AddChild(TreeNode<TValue> treeNode)
    {
        Children.Add(treeNode);
    }
    public void AddChild(TValue value)
    {
        var treeNode = new TreeNode<TValue>(value);
        AddChild(treeNode);
    }
    #endregion
}

2

Diğer insanlar için yararlı olabilecek bir Node sınıfı oluşturuyorum . Sınıf aşağıdaki özelliklere sahiptir:

  • çocuklar
  • Atalar
  • Torunları
  • Kardeşler
  • Düğüm seviyesi
  • ebeveyn
  • Kök
  • Vb.

Ayrıca, Id ve ParentId içeren düz bir öğe listesini ağaca dönüştürme imkanı da vardır. Düğümler hem çocuklara hem de ebeveyne referans verir, böylece yineleme düğümlerini oldukça hızlı hale getirir.



2

@Berezh tarafından paylaşılan kodu tamamladım.

  public class TreeNode<T> : IEnumerable<TreeNode<T>>
    {

        public T Data { get; set; }
        public TreeNode<T> Parent { get; set; }
        public ICollection<TreeNode<T>> Children { get; set; }

        public TreeNode(T data)
        {
            this.Data = data;
            this.Children = new LinkedList<TreeNode<T>>();
        }

        public TreeNode<T> AddChild(T child)
        {
            TreeNode<T> childNode = new TreeNode<T>(child) { Parent = this };
            this.Children.Add(childNode);
            return childNode;
        }

        public IEnumerator<TreeNode<T>> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return (IEnumerator)GetEnumerator();
        }
    }
    public class TreeNodeEnum<T> : IEnumerator<TreeNode<T>>
    {

        int position = -1;
        public List<TreeNode<T>> Nodes { get; set; }

        public TreeNode<T> Current
        {
            get
            {
                try
                {
                    return Nodes[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }


        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }


        public TreeNodeEnum(List<TreeNode<T>> nodes)
        {
            Nodes = nodes;
        }

        public void Dispose()
        {
        }

        public bool MoveNext()
        {
            position++;
            return (position < Nodes.Count);
        }

        public void Reset()
        {
            position = -1;
        }
    }

İyi tasarım. Ancak bir düğümün alt düğümünün bir sırası olup olmadığından emin değilim. Aşağıdakileri göz önünde bulundururum: Bir düğüm 'sıfır veya daha fazla alt düğüme sahiptir, bu nedenle bir düğüm bir alt düğüm dizisinden türetilmez, ancak alt düğümlerinin bir toplamasıdır (bileşim?)
Harald Coppoolse

2

İşte bir ağaç

public class Tree<T> : List<Tree<T>>
{
    public  T Data { get; private set; }

    public Tree(T data)
    {
        this.Data = data;
    }

    public Tree<T> Add(T data)
    {
        var node = new Tree<T>(data);
        this.Add(node);
        return node;
    }
}

Başlatıcıları bile kullanabilirsiniz:

    var tree = new Tree<string>("root")
    {
        new Tree<string>("sample")
        {
            "console1"
        }
    };

1

Çoğu ağaç işlediğiniz verilerden oluşur.

Diyelim ki personbirinin ayrıntılarını içeren bir sınıfınız var parents, “etki alanı sınıfınızın” bir parçası olarak ağaç yapısını mı tercih edersiniz yoksa kişi nesnelerinize bağlantılar içeren ayrı bir ağaç sınıfı mı kullanırsınız? Bütün alma gibi basit bir işlemle düşünün grandchildrena person, bu kod olmalıdır person sınıf veya kullanıcı gerektiği personsınıfında ayrı bir ağaç sınıfına hakkında bilmek var?

Başka bir örnek derleyicide bir ayrıştırma ağacı ...

Bu örneklerin her ikisinin de gösterdiği şey, bir ağaç kavramının verilerin etki alanının bir parçası olması ve ayrı bir genel amaçlı ağaç kullanılması, en az oluşturulan nesnelerin sayısını iki katına çıkarmanın yanı sıra API'yi tekrar programlamayı zorlaştırmaktadır.

İstediğimiz şey, standart ağaç işlemlerini kullanmak zorunda kalmadan standart ağaç işlemlerini tüm ağaçlar için yeniden uygulamak zorunda kalmadan yeniden kullanmanın bir yoludur. Boost, C ++ için bu tür bir sorunu çözmeye çalıştı, ancak henüz .NET için herhangi bir etki görmedim.


@Puchacz, üzgünüm C ++ ile ilgili verilerim 15 yıl dışında, Boost ve Templates bir göz var, birkaç zayıf çalışmadan sonra onları anlayabilirsiniz. Güç, yüksek öğrenme maliyetlerine sahiptir !!
Ian Ringrose

1

Komple çözüm ve yukarıdaki NTree sınıfı kullanarak örnek ekledim, "AddChild" yöntemi de eklendi ...

    public class NTree<T>
    {
        public T data;
        public LinkedList<NTree<T>> children;

        public NTree(T data)
        {
            this.data = data;
            children = new LinkedList<NTree<T>>();
        }

        public void AddChild(T data)
        {
            var node = new NTree<T>(data) { Parent = this };
            children.AddFirst(node);
        }

        public NTree<T> Parent { get; private set; }

        public NTree<T> GetChild(int i)
        {
            foreach (NTree<T> n in children)
                if (--i == 0)
                    return n;
            return null;
        }

        public void Traverse(NTree<T> node, TreeVisitor<T> visitor, string t, ref NTree<T> r)
        {
            visitor(node.data, node, t, ref r);
            foreach (NTree<T> kid in node.children)
                Traverse(kid, visitor, t, ref r);
        }
    }
    public static void DelegateMethod(KeyValuePair<string, string> data, NTree<KeyValuePair<string, string>> node, string t, ref NTree<KeyValuePair<string, string>> r)
    {
        string a = string.Empty;
        if (node.data.Key == t)
        {
            r = node;
            return;
        }
    }

kullanma

 NTree<KeyValuePair<string, string>> ret = null;
 tree.Traverse(tree, DelegateMethod, node["categoryId"].InnerText, ref ret);

Çaprazlama statik bir yöntem olabilir mi? Kendini kendi kendine geçiren bir örnek yöntem olarak çok garip görünüyor
Sinaesthetic

0

İşte benim BST uygulaması

class BST
{
    public class Node
    {
        public Node Left { get; set; }
        public object Data { get; set; }
        public Node Right { get; set; }

        public Node()
        {
            Data = null;
        }

        public Node(int Data)
        {
            this.Data = (object)Data;
        }

        public void Insert(int Data)
        {
            if (this.Data == null)
            {
                this.Data = (object)Data;
                return;
            }
            if (Data > (int)this.Data)
            {
                if (this.Right == null)
                {
                    this.Right = new Node(Data);
                }
                else
                {
                    this.Right.Insert(Data);
                }
            }
            if (Data <= (int)this.Data)
            {
                if (this.Left == null)
                {
                    this.Left = new Node(Data);
                }
                else
                {
                    this.Left.Insert(Data);
                }
            }
        }

        public void TraverseInOrder()
        {
            if(this.Left != null)
                this.Left.TraverseInOrder();
            Console.Write("{0} ", this.Data);
            if (this.Right != null)
                this.Right.TraverseInOrder();
        }
    }

    public Node Root { get; set; }
    public BST()
    {
        Root = new Node();
    }
}

0

Bu ağacı GUI'de görüntüleyecekseniz, TreeView ve TreeNode'u kullanabilirsiniz . (Teknik olarak bir GUI'ye koymadan bir TreeNode oluşturabileceğinizi varsayalım, ancak basit bir ev yapımı TreeNode uygulamasından daha fazla yükü var.)


-4

Daha az bellek kullanan bir köklü ağaç veri yapısı uygulamasına ihtiyacınız varsa, Node sınıfınızı aşağıdaki gibi yazabilirsiniz (C ++ uygulaması):

class Node {
       Node* parent;
       int item; // depending on your needs

       Node* firstChild; //pointer to left most child of node
       Node* nextSibling; //pointer to the sibling to the right
}

12
C ++ için bir soruya C ++ kodu göndermek en iyi fikir değil Jake. Özellikle işaretçiler içeren biri. İşaretçilerin C # 'da acımasızca avlandığını biliyorsunuz, değil mi? : p
ThunderGr

2
@ThunderGr bu adil değil. C # 'da cevap vermek daha iyi olurdu, ancak bu C ++ işaretçileri C # hoparlörleri tarafından referans olarak anlaşılabilirler (daha az güvenlidirler, tamam). David Boike, Aaron Gage, Ronnie Overby, Grzegorz Dev, Berezh ve Erik Nagel, temelde aynı veri yapısını sadece ifadede küçük farklılıklar ile sindirdikten sonra Jake, sadece bir tür düğüm ve kardeş gezinme. Yapıcı bir cevabı oylayarak C ++ 'dan hoşlanmadığınızı ifade etmeyin.
Migle

3
migle Cevabı küçümsemedim (ikisini de büyütmedim). Ve ben C ++ sevmiyorum. Cevabın, Jake'e cevabını neden ve nasıl iyileştireceği hakkında herhangi bir şey önermeden aşağı indirildiğini gördüm. "Daha iyi olmak" ile ilgili değil. Soru sadece C # için etiketlenmiştir. Yanıtları etiketten başka bir dilde yayınlamak önerilmez ve bazı kişiler oyları düşürür.
ThunderGr
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.