Struktur data pohon dalam C #


248

Saya sedang mencari struktur data pohon atau grafik di C # tapi saya kira tidak ada yang disediakan. Pemeriksaan Ekstensif Struktur Data Menggunakan C # 2.0 menjelaskan sedikit tentang mengapa. Apakah ada perpustakaan yang nyaman yang biasanya digunakan untuk menyediakan fungsionalitas ini? Mungkin melalui pola strategi untuk menyelesaikan masalah yang disajikan dalam artikel.

Saya merasa agak konyol menerapkan pohon saya sendiri, sama seperti saya akan mengimplementasikan ArrayList saya sendiri.

Saya hanya ingin pohon generik yang tidak seimbang. Pikirkan pohon direktori. C5 terlihat bagus, tetapi struktur pohon mereka tampaknya diimplementasikan sebagai pohon merah-hitam seimbang yang lebih cocok untuk dicari daripada mewakili hierarki node.


2
Pohon yang sedikit lebih ekstrem: stackoverflow.com/questions/196294/... ;-)
Tuomas Hietanen

Apakah ada alasan mengapa seseorang tidak dapat memasukkan TreeView dalam proyek dan menggunakannya? Tidak ada alasan untuk menunjukkannya kepada pengguna. Tentu saja ada beberapa bentuk proyek saat ini bukan pilihan. Satu selalu dapat membuat kelas baru yang mewarisi dari TreeNode contoh jika kompleksitas khusus diperlukan?
Cukup G.

9
Saya akan menganggap itu sebagai ide yang buruk untuk mengimpor seluruh perpustakaan UI untuk pohon yang sangat sederhana.
merangsang

1
Bisakah Anda memotivasi? Ini tidak seperti kebutuhan ruang harddisk sebenarnya adalah masalah lagi? Ceroboh? Seperti yang saya sebutkan sebelumnya, saya bisa mengerti bahwa ini bukan solusi untuk perangkat lunak khusus atau sesuatu tanpa antarmuka pengguna yang ada. Saya seorang programmer malas, jika saya bisa mendapatkan struktur gratis semuanya baik. Dan perpustakaan yang ada memang memiliki banyak gratis, orang dapat menemukan banyak kode dari orang yang menggunakannya untuk banyak hal.
Cukup G.

Saya tidak berdebat, saya hanya ingin tahu alasan Anda.
Cukup G.

Jawaban:


155

Saran terbaik saya adalah bahwa tidak ada struktur data pohon standar karena ada banyak cara Anda dapat mengimplementasikannya sehingga tidak mungkin untuk menutup semua pangkalan dengan satu solusi. Semakin spesifik suatu solusi, semakin kecil kemungkinannya untuk diterapkan pada masalah apa pun. Saya bahkan merasa terganggu dengan LinkedList - bagaimana jika saya ingin daftar tertaut melingkar?

Struktur dasar yang harus Anda implementasikan adalah kumpulan node, dan berikut adalah beberapa opsi untuk Anda mulai. Mari kita asumsikan bahwa kelas Node adalah kelas dasar dari seluruh solusi.

Jika Anda hanya perlu menavigasi turun pohon, maka kelas Node membutuhkan Daftar anak-anak.

Jika Anda perlu menavigasi pohon, maka kelas Node membutuhkan tautan ke simpul induknya.

Bangun metode AddChild yang menangani semua hal-hal kecil dari dua poin ini dan semua logika bisnis lain yang harus diterapkan (batas anak, pemilahan anak-anak, dll.)


5
secara pribadi saya tidak akan keberatan semacam pohon biner self-balancing yang akan ditambahkan ke perpustakaan karena ini adalah beberapa pekerjaan tambahan daripada hanya menggunakan daftar adjaceny.
jk.

8
@ jk Saya percaya bahwa SortedDictionary dan SortedSet dibangun di atas pohon merah / hitam, jadi menggunakan ini harus bekerja.
jonp

Lihatlah pola komposit ;-) Persis apa yang Anda cari
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);
    }
}

Implementasi rekursif sederhana ... <40 baris kode ... Anda hanya perlu menyimpan referensi ke akar pohon di luar kelas, atau membungkusnya di kelas lain, mungkin mengubah nama menjadi TreeNode ??


22
Dalam hal ini, di C # pula, Anda bisa menghindari menulis delegasi Anda sendiri dan menggunakan pra-dibuat Action<T>delegasi: public void traverse(NTree<T> node, Action<T> visitor). Aksi <> tanda tangan adalah: void Action<T>( T obj ). Ada juga versi dari 0 hingga 4 parameter yang berbeda. Ada juga delegasi analog untuk fungsi-fungsi yang disebut Func<>.
Benny Jobigan

2
bagaimana saya memanggil delegasi ini?
Freakishly

3
mengubah metode traverse menjadi statis atau mungkin membungkusnya untuk menyembunyikan sifat rekursif akan menjadi ide yang baik, tetapi mudah untuk dilintasi: membuat metode dengan tanda tangan delegasi yaitu untuk pohon int: void my_visitor_impl (int datum) - buat itu statis jika Anda perlu, instantiate delgate: TreeVisitor <int> my_visitor = my_visitor_impl; dan kemudian memohon pada simpul akar atau kelas NTree jika Anda membuatnya statis: NTree <int> .traverse (my_tree, my_visitor)
Aaron Gage

10
Membuat addChild () mengembalikan NTree yang ditambahkan akan membuatnya lebih baik untuk menambahkan data ke pohon. (Kecuali saya kehilangan cara licik untuk membangun pohon dengan ini, tanpa bergantung pada detail implementasi bahwa anak yang baru ditambahkan == getChild (1)?)
Rory

1
Saya pikir pernyataan ini hanya --i == 0akan berfungsi pada satu kasus? Apakah ini benar. Ini membuat saya bingung
Waseem Ahmad Naeem

57

Ini milik saya, yang sangat mirip dengan milik Aaron Gage , hanya sedikit lebih konvensional, menurut pendapat saya. Untuk tujuan saya, saya belum pernah mengalami masalah kinerja List<T>. Akan cukup mudah untuk beralih ke LinkedList jika diperlukan.


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()));
        }
    }
}

mengapa properti Value Anda diekspos saat Anda menetapkannya di konstruktor? yang membuatnya terbuka untuk manipulasi SETELAH Anda sudah mengaturnya melalui konstruktor, kan? Haruskah set pribadi?
PositiveGuy

Tentu, mengapa tidak membuatnya tidak berubah? Diedit.
Ronnie Overby

Terima kasih! Saya cukup suka tidak harus menulis sendiri. (Masih tidak percaya itu bukan benda yang ada secara asli. Saya selalu berpikir .net, atau setidaknya .net 4.0, memiliki segalanya .)
neminem

3
Saya menyukai solusi ini. Saya juga menemukan saya perlu memasukkan, saya menambahkan metode berikut untuk melakukan itu. 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

Namun struktur pohon lain:

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
}

Penggunaan sampel:

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
Lihat pohon lengkap dengan:

  • iterator
  • mencari
  • Java / C #

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


Bagaimana saya menggunakan pencarian dalam contoh kode Anda? Dari mana datangnya node? Apakah itu berarti saya harus beralih di atas pohon untuk menggunakan kode pencarian?
BadmintonCat

@GrzegorzDev Mungkin -1 karena tidak mengimplementasikan semua IEnumerable<>anggota, jadi tidak dapat dikompilasi.
Uwe Keim

1
@ UweKeim Good Job, lain kali coba gunakan kode dengan usings sebenarnya.
szab.kel

Satu-satunya masalah yang saya lihat adalah bahwa itu tidak akan benar serial dengan dasar JsonConvert karena mengimplementasikan IEnumerable <>
Rakiah

22

Perpustakaan Koleksi Umum C5 yang sangat bagus memiliki beberapa struktur data berbasis pohon yang berbeda, termasuk set, tas dan kamus. Kode sumber tersedia jika Anda ingin mempelajari detail implementasi mereka. (Saya telah menggunakan koleksi C5 dalam kode produksi dengan hasil yang baik, meskipun saya belum menggunakan struktur pohon secara khusus.)


7
Tidak tahu apakah mungkin ada yang berubah, tetapi saat ini buku tersedia secara gratis untuk diunduh sebagai PDF dari situs C5.
Oskar

4
Kurangnya dokumentasi tidak lagi menjadi masalah karena ada pdf sepanjang 272 halaman yang melengkapi perpustakaan ... Tidak dapat mengomentari kualitas kode, tetapi menilai dari kualitas dokumen, saya benar-benar berharap untuk menggali malam ini!
Florian Doyon

2
Dari apa yang saya mengerti, perpustakaan C5 ini tidak memiliki pohon sama sekali, tetapi hanya beberapa struktur data yang diturunkan dari pohon.
roim

10

Lihat http://quickgraph.codeplex.com/

QuickGraph menyediakan datastructures dan algoritma grafik yang diarahkan / tidak diarahkan secara umum untuk .Net 2.0 dan yang lebih tinggi. QuickGraph hadir dengan algoritme seperti pencarian kedalaman pertama, pencarian pertama nafas, pencarian A *, jalur terpendek, jalur terpendek k, aliran maksimum, pohon rentang minimum, leluhur paling tidak umum, dll. QuickGraph mendukung MSAGL, GLEE, dan Graphviz untuk render grafik, serialisasi ke GraphML, dll ...


8

Jika Anda ingin menulis sendiri, Anda dapat mulai dengan dokumen enam bagian ini yang merinci penggunaan efektif struktur data C # 2.0 dan bagaimana cara menganalisis implementasi struktur data Anda dalam C #. Setiap artikel memiliki contoh dan installer dengan sampel yang dapat Anda ikuti.

"Pemeriksaan Ekstensif Struktur Data Menggunakan C # 2.0" oleh Scott Mitchell


7

Saya punya sedikit ekstensi untuk solusi.

Dengan menggunakan deklarasi generik rekursif dan subclass turunan, Anda dapat lebih berkonsentrasi pada target Anda yang sebenarnya.

Perhatikan, ini berbeda dari implementasi non generik, Anda tidak perlu menggunakan 'node' di 'NodeWorker'.

Inilah contoh saya:

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);  
}  

apa kedalaman dan dari mana dan bagaimana Anda mendapatkannya?
PositiveGuy

@ WeDoTDD.com melihat kelasnya yang Anda lihat Traverse mendeklarasikannya sebagai 0 untuk memulai pada node root, kemudian menggunakan metode traverse yang menambahkan int setiap iterasi.
Edward

Bagaimana Anda mencari seluruh pohon untuk simpul tertentu?
mattpm

6

Ini milik saya:

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;
    }
}

Keluaran:

Fastfood
   Pizza
      Margherita
      Marinara
   Burger
      Cheese burger
      Chili burger
      Rice burger

4

Coba contoh sederhana ini.

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

Saya membuat kelas Node yang bisa membantu orang lain. Kelas memiliki properti seperti:

  • Anak-anak
  • Leluhur
  • Keturunan
  • Saudara kandung
  • Tingkat simpul
  • Induk
  • Akar
  • Dll

Ada juga kemungkinan untuk mengonversi daftar datar item dengan Id dan ParentId ke pohon. Node memegang referensi untuk anak-anak dan orang tua, sehingga membuat node pengulangan cukup cepat.



2

Saya telah menyelesaikan kode yang dibagikan @Berezh.

  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;
        }
    }

Desain yang bagus. Namun saya tidak yakin apakah simpul 'adalah' urutan simpul anaknya. Saya akan mempertimbangkan yang berikut: sebuah node 'memiliki' nol atau lebih node anak, jadi sebuah node tidak berasal dari urutan node anak, tetapi merupakan agregasi (komposisi?) Dari simpul anak-anaknya
Harald Coppoolse

2

Ini Pohon

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;
    }
}

Anda bahkan dapat menggunakan inisialisasi:

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

1

Sebagian besar pohon dibentuk oleh data yang Anda proses.

Katakanlah Anda memiliki personkelas yang mencakup detail seseorang parents, apakah Anda lebih suka memiliki struktur pohon sebagai bagian dari "kelas domain" Anda, atau menggunakan kelas pohon terpisah yang berisi tautan ke objek orang Anda? Pikirkan tentang operasi sederhana seperti mendapatkan semua grandchildrendari person, haruskah kode ini berada di person kelas, atau haruskah pengguna personkelas harus tahu tentang kelas pohon yang terpisah?

Contoh lain adalah pohon parse di kompiler ...

Apa yang ditunjukkan kedua contoh ini adalah bahwa konsep pohon adalah bagian dari domain data dan menggunakan pohon tujuan umum yang terpisah setidaknya menggandakan jumlah objek yang dibuat serta membuat API lebih sulit untuk diprogram lagi.

Apa yang kita inginkan adalah cara untuk menggunakan kembali operasi pohon standar, tanpa harus mengimplementasikannya kembali untuk semua pohon, sementara pada saat yang sama, tidak harus menggunakan kelas pohon standar. Boost telah mencoba menyelesaikan masalah jenis ini untuk C ++, tetapi saya belum melihat efek apa pun untuk .NET diadaptasi.


@ Puchacz, maaf saya 15 tahun kehabisan data pada C ++, lihat Boost and Templates, setelah beberapa studi lemah Anda mungkin mengerti mereka. Kekuasaan memiliki biaya belajar yang tinggi !!
Ian Ringrose

1

Saya telah menambahkan solusi lengkap dan contoh menggunakan kelas NTree di atas, juga menambahkan metode "AddChild" ...

    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;
        }
    }

menggunakan

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

Haruskah melintasi mungkin menjadi metode statis? Tampaknya sangat canggung sebagai metode instan yang masuk sendiri
Sinaesthetic

0

Inilah implementasi BST saya

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

Jika Anda akan menampilkan pohon ini pada GUI, Anda dapat menggunakan TreeView dan TreeNode . (Saya kira secara teknis Anda dapat membuat TreeNode tanpa meletakkannya di GUI, tetapi ia memiliki lebih banyak overhead daripada implementasi TreeNode sederhana buatan sendiri.)


-4

Jika Anda membutuhkan implementasi struktur data pohon yang di-rooting yang menggunakan lebih sedikit memori, Anda dapat menulis kelas Node Anda sebagai berikut (implementasi C ++):

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
Memposting kode C ++ pada pertanyaan khusus untuk C # bukan ide terbaik, Jake. Terutama yang termasuk pointer. Anda tahu bahwa pointer sedang diburu tanpa ampun dalam C #, kan? : p
ThunderGr

2
@ThunderGr itu tidak adil. Menjawab dalam C # akan lebih baik, tetapi pointer C ++ tersebut dapat dipahami oleh C # -speaker sebagai referensi (mereka kurang aman, ok). Setelah David Boike, Aaron Gage, Ronnie Overby, Grzegorz Dev, Berezh dan Erik Nagel semua memiliki sugested pada dasarnya struktur data yang sama dengan perbedaan kecil hanya dalam ekspresi, Jake menyarankan memecah daftar terkait menghasilkan struktur yang lebih sederhana dengan hanya satu jenis node dan kemampuan navigasi saudara Jangan ungkapkan ketidaksukaan Anda terhadap C ++ dengan memilih secara turun-bawah jawaban yang membangun.
migle

3
@migle Saya tidak downvote jawabannya (juga tidak upvote). Dan saya tidak suka C ++. Saya melihat bahwa jawabannya dibatalkan tanpa ada yang menyarankan apa pun kepada Jake tentang mengapa dan bagaimana ia akan meningkatkan jawabannya. Ini bukan tentang "menjadi lebih baik". Pertanyaan hanya ditandai untuk C #. Posting jawaban dalam bahasa lain dari pada tag tidak disarankan dan beberapa orang akan downvote.
ThunderGr
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.