C # में ट्री डेटा संरचना


248

मैं C # में एक ट्री या ग्राफ़ डेटा संरचना की तलाश कर रहा था, लेकिन मुझे लगता है कि कोई भी उपलब्ध नहीं है। C # 2.0 का उपयोग करते हुए डेटा स्ट्रक्चर्स की एक विस्तृत परीक्षा इस बारे में थोड़ा बताती है कि क्यों। क्या एक सुविधाजनक पुस्तकालय है जो आमतौर पर इस कार्यक्षमता को प्रदान करने के लिए उपयोग किया जाता है? शायद लेख में प्रस्तुत मुद्दों को हल करने के लिए एक रणनीति पैटर्न के माध्यम से।

मुझे लगता है कि मैं अपने खुद के ArrayList को लागू करने के लिए अपने पेड़ को लागू करने में थोड़ा मूर्खतापूर्ण महसूस कर रहा हूं।

मुझे सिर्फ एक जेनेरिक पेड़ चाहिए जो असंतुलित हो सकता है। एक निर्देशिका पेड़ के बारे में सोचो। सी 5 निफ्टी दिखता है, लेकिन उनके पेड़ की संरचना को संतुलित लाल-काले पेड़ों के रूप में कार्यान्वित किया गया लगता है जो नोड्स के पदानुक्रम का प्रतिनिधित्व करने की तुलना में खोज के लिए बेहतर अनुकूल हैं।


2
थोड़ा और अधिक चरम पेड़: stackoverflow.com/questions/196294/… ;-)
Tuomas Hietanen

क्या कोई कारण है कि कोई इस परियोजना में एक ट्री व्यू को शामिल नहीं कर सकता है और इसका उपयोग कर सकता है? वास्तव में इसे उपयोगकर्ता को दिखाने का कोई कारण नहीं है। बेशक, जब यह कोई विकल्प नहीं होता है तो कई तरह की परियोजनाएँ होती हैं। एक हमेशा नई कक्षाएं बना सकते हैं जो उदाहरण के लिए ट्रीनोड से विरासत में मिली हैं यदि विशेष जटिलता की आवश्यकता है?
बस जी।

9
मैं इसे बहुत ही सरल पेड़ के लिए पूरे यूआई लाइब्रेरी को आयात करने के लिए एक बुरा विचार मानूंगा।
उत्तेजित करता है

1
क्या आप प्रेरित कर सकते हैं? इसकी वास्तविक हार्डड्राइव अंतरिक्ष आवश्यकता की तरह अब एक मुद्दा नहीं है? अनाड़ी? जैसा कि मैंने पहले उल्लेख किया है, मैं समझ सकता हूं कि यह एक विशेष सॉफ्टवेयर या मौजूदा उपयोगकर्ता इंटरफ़ेस के बिना कुछ के लिए एक समाधान नहीं है। मैं एक आलसी प्रोग्रामर हूं, अगर मुझे इसकी सभी अच्छी चीजों के लिए एक संरचना मिल सकती है। और एक मौजूदा लाइब्रेरी में मुफ्त में बहुत कुछ होता है, जो बहुत से लोगों के लिए बहुत से कोड का उपयोग कर सकते हैं।
बस जी।

मैं बहस नहीं कर रहा हूं, मैं सिर्फ आपका तर्क जानना चाहता हूं।
बस जी 10

जवाबों:


155

मेरी सबसे अच्छी सलाह यह होगी कि कोई मानक पेड़ डेटा संरचना नहीं है क्योंकि वहाँ बहुत सारे तरीके हैं जो आप इसे लागू कर सकते हैं कि सभी ठिकानों को एक समाधान के साथ कवर करना असंभव होगा। अधिक विशिष्ट समाधान, किसी भी समस्या के लिए कम संभावना है। मुझे लिंक्डलिस्ट से भी चिढ़ है - अगर मुझे एक सर्कुलर लिंक्ड लिस्ट चाहिए तो क्या होगा?

बुनियादी संरचना जिसे आपको लागू करने की आवश्यकता होगी, नोड्स का एक संग्रह होगा, और यहां कुछ विकल्प दिए गए हैं ताकि आप शुरू कर सकें। मान लेते हैं कि वर्ग नोड संपूर्ण समाधान का आधार वर्ग है।

यदि आपको केवल पेड़ को नीचे फेंकने की आवश्यकता है, तो एक नोड वर्ग को बच्चों की सूची की आवश्यकता है।

यदि आपको पेड़ को नेविगेट करने की आवश्यकता है, तो नोड वर्ग को अपने मूल नोड के लिंक की आवश्यकता है।

एक AddChild विधि का निर्माण करें जो इन दो बिंदुओं के सभी minutia और किसी भी अन्य व्यावसायिक तर्क को लागू करता है जिसे लागू किया जाना चाहिए (बाल सीमाएं, बच्चों को छांटना, आदि)


5
व्यक्तिगत रूप से मुझे किसी प्रकार के स्व-संतुलन वाले बाइनरी ट्री को लाइब्रेरी में शामिल करने का मन नहीं होगा क्योंकि यह केवल एक आसन्न सूची का उपयोग करने की तुलना में कुछ अतिरिक्त काम है।
जे.के.

8
@ jk मेरा मानना ​​है कि SortedDictionary और SortedSet लाल / काले पेड़ों के ऊपर बनाया गया है, इसलिए इन का उपयोग कर काम करना चाहिए।
जोंप

समग्र पैटर्न पर एक नज़र;; आप वास्तव में क्या देख रहे हैं;
निकोलस वोरोन

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

सरल पुनरावर्ती कार्यान्वयन ... <40 कोड की पंक्तियाँ ... आपको बस कक्षा के बाहर पेड़ की जड़ का संदर्भ रखने की आवश्यकता है, या इसे किसी अन्य कक्षा में लपेटना होगा, शायद ट्रीनोड का नाम बदल दिया जाए ??


22
इस मामले में, सी # में, आप अपने स्वयं के प्रतिनिधि लिखने से बच सकते हैं और पूर्व-निर्मित Action<T>प्रतिनिधि का उपयोग कर सकते हैं public void traverse(NTree<T> node, Action<T> visitor):। कार्रवाई <> का हस्ताक्षर है void Action<T>( T obj ):। 0 से 4 विभिन्न मापदंडों के संस्करण भी हैं। कार्यों के लिए एक अनुरूप प्रतिनिधि भी कहा जाता है Func<>
बेनी जोबिगन

2
मैं इस प्रतिनिधि को कैसे बुलाऊंगा?
अजीब तरह से

3
अनुप्रस्थ विधि को स्थिर करना या संभवतः पुनरावर्ती प्रकृति को छिपाने के लिए इसे लपेटना एक अच्छा विचार होगा, लेकिन यह आसान है: अनुप्रस्थ करना: प्रतिनिधि के हस्ताक्षर के साथ एक विधि बनाएं अर्थात एक पेड़ की जड़ के लिए: शून्य myvisitor_impl (int datum) - यदि आप की जरूरत है, तो इसे स्थिर बनाएं, एक डेलगेट को तत्काल करें: ट्रीविसिटर <int> my_visitor = my_visitor_impl; और फिर रूट नोड या NTree वर्ग पर आह्वान करें यदि आप इसे स्थिर बनाते हैं: NTree <int> .Traverse (my_tree, my_visitor)
हारून गेज़

10
AddChild () बनाकर NTree जो इसे जोड़ा गया है वह एक पेड़ में डेटा जोड़ने के लिए इसे अच्छा बना देगा। (जब तक कि मैं एक नए जोड़े गए बच्चे == getChild (1)?)
रोरी

1
मुझे लगता है कि यह बयान --i == 0केवल एकल मामले में कार्य करेगा? क्या ये सच है। इसने मुझे भ्रमित कर दिया
वसीम अहमद नईम

57

यहाँ मेरा है, जो कि मेरी राय में आरोन गेज़ के समान है , बस थोड़ा अधिक पारंपरिक है। अपने उद्देश्यों के लिए, मैं किसी भी प्रदर्शन के मुद्दों के साथ नहीं भागा हूं List<T>। जरूरत पड़ने पर लिंक्डलिस्ट में स्विच करना काफी आसान होगा।


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

जब आप इसे निर्माता में सेट कर रहे हैं, तो आपकी मूल्य संपत्ति क्यों उजागर होती है? कि यह हेरफेर के लिए खुला छोड़ देता है? निजी सेट होना चाहिए?
पॉजिटिव

ज़रूर, इसे अपरिवर्तनीय क्यों नहीं बनाया जाए? संपादित।
रॉनी ओवरबी

धन्यवाद! मुझे खुद लिखना पसंद नहीं था। (फिर भी यह विश्वास नहीं हो सकता कि यह ऐसी चीज़ है जो मूल रूप से मौजूद है। मैंने हमेशा सोचा था कि .net, या कम से कम .net 4.0, सब कुछ था ।)
13'13

3
मुझे यह समाधान पसंद आया। मैंने यह भी पाया कि मुझे सम्मिलित करने की आवश्यकता है, मैंने ऐसा करने के लिए निम्न विधि जोड़ी। 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

अभी तक एक और पेड़ संरचना:

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
}

नमूना उपयोग:

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

बोनस
पूरी तरह से पेड़ के साथ देखें:

  • इटरेटर
  • खोज कर
  • जावा / सी #

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


मैं आपके कोड उदाहरण में खोज का उपयोग कैसे करूं? कहाँ nodeसे आता है? क्या इसका मतलब है कि मुझे खोज कोड का उपयोग करने के लिए पेड़ पर खुजलाना होगा?
बैडमिंटनकैट

@GrzegorzDev शायद -1 क्योंकि यह सभी IEnumerable<>सदस्यों को लागू नहीं करता है , इसलिए यह संकलन नहीं करता है।
उवे कीम

1
@UweKeim अच्छा काम, अगली बार वास्तविक उपयोग के साथ कोड का उपयोग करने का प्रयास करें।
szab.kel

केवल समस्या मैं देख रहा हूँ कि यह बुनियादी JsonConvert के साथ सही ढंग से क्रमबद्ध नहीं होगा क्योंकि यह IEnumerable <> को लागू करता है
Rakiah

22

आम तौर पर उत्कृष्ट C5 जेनेरिक कलेक्शन लाइब्रेरी में कई अलग-अलग पेड़-आधारित डेटा संरचनाएं हैं, जिनमें सेट, बैग और शब्दकोश शामिल हैं। यदि आप उनके कार्यान्वयन विवरण का अध्ययन करना चाहते हैं तो स्रोत कोड उपलब्ध है। (मैंने अच्छे परिणाम के साथ उत्पादन कोड में C5 संग्रह का उपयोग किया है, हालांकि मैंने विशेष रूप से किसी भी पेड़ संरचना का उपयोग नहीं किया है।)


7
नहीं जानते कि क्या शायद चीजें बदल गई हैं, लेकिन अभी सी 5 साइट से पीडीएफ के रूप में डाउनलोड करने के लिए पुस्तक स्वतंत्र रूप से उपलब्ध है।
Oskar

4
प्रलेखन की कमी कोई ज्यादा चिंता की बात नहीं है क्योंकि लाइब्रेरी को पूरक करने के लिए 272 पृष्ठों लंबा पीडीएफ है ... कोड गुणवत्ता पर टिप्पणी नहीं कर सकता है, लेकिन डॉक्टर की गुणवत्ता को देखते हुए, मैं वास्तव में इस रात में खुदाई करने के लिए उत्सुक हूं!
फ्लोरियन डॉयन

2
मैं जो समझता हूं, इस सी 5 लाइब्रेरी में पेड़ नहीं हैं, लेकिन केवल कुछ पेड़-व्युत्पन्न डेटा संरचनाएं हैं।
20'14

10

Http://quickgraph.codeplex.com/ देखें

QuickGraph .Net 2.0 और ऊपर के लिए जेनेरिक निर्देशित / अप्रत्यक्ष ग्राफ़ डेटास्ट्रक्चर और एल्गोरिदम प्रदान करता है। क्विकग्राफ एल्गोरिदम के साथ आता है जैसे गहराई पहले सीच, सांस पहले खोज, ए * खोज, सबसे छोटा रास्ता, के-सबसे छोटा रास्ता, अधिकतम प्रवाह, न्यूनतम फैले पेड़, कम से कम सामान्य पूर्वजों, आदि ... QuickGraph MSAGL, GLEE, और ग्राफविज़ का समर्थन करता है ग्राफ़ को प्रस्तुत करना, ग्राफएमएल को क्रमबद्ध करना, आदि ...


8

यदि आप अपना स्वयं का लिखना चाहते हैं, तो आप सी # 2.0 डेटा संरचनाओं के प्रभावी उपयोग का विस्तार करते हुए और सी # में डेटा संरचनाओं के अपने कार्यान्वयन के विश्लेषण के बारे में जाने के लिए इस छह-भाग के दस्तावेज़ के साथ शुरू कर सकते हैं। प्रत्येक लेख के उदाहरण और नमूने के साथ एक इंस्टॉलर है जिसका आप अनुसरण कर सकते हैं।

स्कॉट मिशेल द्वारा "डेटा संरचनाओं का एक व्यापक परीक्षा C # 2.0 का उपयोग करना"


7

मेरे पास समाधानों का थोड़ा विस्तार है।

एक पुनरावर्ती सामान्य घोषणा और एक उप-उपवर्ग का उपयोग करके आप अपने वास्तविक लक्ष्य पर बेहतर ध्यान केंद्रित कर सकते हैं।

ध्यान दें, यह एक गैर-सामान्य कार्यान्वयन से अलग है, आपको 'नोडवॉकर' में 'नोड' डालने की आवश्यकता नहीं है।

यहाँ मेरा उदाहरण है:

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

गहराई क्या है और आप इसे कहाँ से और कैसे प्राप्त करते हैं?
पॉजिटिव

@ WeDoTDD.com आपको उसकी कक्षा को देखकर लगता है कि Traverse इसे रूट नोड पर शुरू करने के लिए 0 के रूप में घोषित करता है, फिर प्रत्येक पुनरावृत्ति को जोड़ने वाली विधि traverse का उपयोग करता है।
एडवर्ड

आप एक विशेष नोड के लिए पूरे पेड़ की खोज कैसे करेंगे?
मटका 05

6

यहाँ मेरा अपना है:

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

आउटपुट:

Fastfood
   Pizza
      Margherita
      Marinara
   Burger
      Cheese burger
      Chili burger
      Rice burger

4

इस सरल नमूने का प्रयास करें।

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

मैं एक नोड वर्ग बनाता हूं जो अन्य लोगों के लिए सहायक हो सकता है। वर्ग में गुण होते हैं जैसे:

  • बच्चे
  • पूर्वजों
  • वंशज
  • एक माँ की संताने
  • नोड का स्तर
  • माता-पिता
  • जड़
  • आदि।

एक आईडी और एक पेरेंटआईड के साथ वस्तुओं की एक फ्लैट सूची को एक पेड़ में बदलने की संभावना भी है। नोड्स बच्चों और माता-पिता दोनों के लिए एक संदर्भ रखते हैं, जिससे यह नोड्स को बहुत तेज़ बनाता है।


2

क्योंकि यह उल्लेख नहीं है कि मैं चाहूंगा कि आप अब जारी किए गए .net कोड-बेस पर ध्यान आकर्षित करें: विशेष रूप से SortedSetउस लाल-काले-पेड़ को लागू करने वाले कोड के लिए :

https://github.com/Microsoft/referencesource/blob/master/System/compmod/system/collections/generic/sortedset.cs

हालांकि, यह एक संतुलित वृक्ष संरचना है। तो मेरा जवाब यह है कि मुझे विश्वास है कि नेट कोर लाइब्रेरी में केवल मूल वृक्ष-संरचना है।


2

मैंने वह कोड पूरा कर लिया है जो @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;
        }
    }

सुंदर डिजाइन। हालाँकि मुझे यकीन नहीं है कि एक नोड 'अपने बच्चे के नोड का एक क्रम है। मैं निम्नलिखित पर विचार करता हूं: एक नोड में 'शून्य या अधिक बच्चे नोड्स होते हैं, इसलिए एक नोड बच्चे के नोड्स के अनुक्रम से उत्पन्न नहीं होता है, लेकिन यह अपने बच्चे के नोड्स का एक एकत्रीकरण (रचना?) है
हैराल्ड कोपलस

2

यहाँ एक पेड़ है

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

तुम भी initializers का उपयोग कर सकते हैं:

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

1

अधिकांश पेड़ उस डेटा से बनते हैं जिसे आप संसाधित कर रहे हैं।

मान लें कि आपके पास एक ऐसा personवर्ग है, जिसमें किसी के विवरण शामिल हैं parents, क्या आप अपने "डोमेन वर्ग" के हिस्से के रूप में पेड़ की संरचना करेंगे, या एक अलग पेड़ वर्ग का उपयोग कर सकते हैं जिसमें आपके व्यक्ति ऑब्जेक्ट्स के लिंक शामिल थे? सब हो रही की तरह एक सरल ऑपरेशन के बारे में सोचो grandchildrenएक की person, इस कोड में होना चाहिए person वर्ग, या के उपयोगकर्ता चाहिए personवर्ग एक अलग पेड़ वर्ग के बारे में पता करने के लिए है?

एक अन्य उदाहरण एक संकलक में एक पेड़ है ...

इन दोनों उदाहरणों से पता चलता है कि एक पेड़ की अवधारणा डोमेन का हिस्सा है डेटा का और एक अलग सामान्य प्रयोजन के पेड़ का उपयोग करके कम से कम वस्तुओं की संख्या दोगुनी हो जाती है और साथ ही एपीआई को फिर से प्रोग्राम करने के लिए कठिन बना दिया जाता है।

हम जो चाहते हैं, वह सभी पेड़ों के लिए उन्हें फिर से लागू किए बिना, मानक पेड़ के संचालन का पुन: उपयोग करने का एक तरीका है, जबकि एक ही समय में, मानक वृक्ष वर्ग का उपयोग नहीं करना है। बूस्ट ने सी ++ के लिए इस तरह की समस्या को हल करने की कोशिश की है, लेकिन मुझे अभी तक .NET के लिए किसी भी प्रभाव को देखने के लिए अनुकूलित किया गया है।


@Puchacz, क्षमा करें, मैं C ++ पर डेटा से 15 वर्ष बाहर हूं, Boost और Templates पर एक नज़र है, अध्ययन के कुछ कमजोर होने के बाद आप उन्हें समझ सकते हैं। बिजली की उच्च शिक्षा लागत है !!
इयान रिंगरोस

1

मैंने NTree वर्ग का उपयोग करके पूरा समाधान और उदाहरण जोड़ा है, "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;
        }
    }

का उपयोग करते हुए

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

क्या ट्रैवर्स को एक स्थिर विधि होना चाहिए? यह बहुत ही अजीब लगता है एक उदाहरण विधि के रूप में खुद को खुद से गुजरते हुए
सिनास्टेटिक

0

यहाँ मेरा BST का कार्यान्वयन है

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

यदि आप इस पेड़ को GUI पर प्रदर्शित करने जा रहे हैं, तो आप TreeView और TreeNode का उपयोग कर सकते हैं । (मुझे लगता है कि तकनीकी रूप से आप एक GUI पर डाले बिना एक ट्रीनोड बना सकते हैं, लेकिन इसमें एक साधारण होमग्रोन ट्रीनोड कार्यान्वयन की तुलना में अधिक ओवरहेड है।)


-4

यदि आपको किसी रूट किए गए ट्री डेटा संरचना कार्यान्वयन की आवश्यकता होती है जो कम मेमोरी का उपयोग करता है, तो आप अपना नोड वर्ग निम्नानुसार लिख सकते हैं (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
विशेष रूप से C # के लिए एक प्रश्न पर C ++ कोड पोस्ट करना सबसे अच्छा विचार नहीं है, जेक। विशेष रूप से एक जिसमें संकेत शामिल हैं। आप जानते हैं कि सी #, सही में निर्दयता से शिकार किए जा रहे हैं? : पी
थंडरग्रास

2
@ThunderGr जो उचित नहीं है। C # में उत्तर देना बेहतर होता, लेकिन उन C ++ पॉइंटर्स को C # -स्पीकर द्वारा संदर्भ के रूप में समझा जा सकता है (वे कम सुरक्षित हैं, ठीक है)। डेविड बोइक, आरोन गेज, रोनी ओवरबी, ग्रेज़गोरज़ देव, बेरेज़ और एरिक नगेल के बाद मूल रूप से अभिव्यक्ति में मामूली अंतर के साथ मूल रूप से एक ही डेटा संरचना के साथ, जेक ने केवल एक प्रकार के नोड के साथ एक सरल संरचनाओं की रक्षा करते हुए लिंक की गई सूची को तोड़ दिया। भाई-बहनों की योग्यता एक रचनात्मक जवाब को वोट करके सी ++ के अपने नापसंद को व्यक्त न करें।
migle

3
@ मिगले मैंने जवाब नहीं दिया (या तो अपवोट नहीं किया)। और मुझे C ++ नापसंद नहीं है। मैंने देखा कि जेक के बारे में किसी को कुछ भी सुझाव दिए बिना उत्तर को अस्वीकार कर दिया गया था कि वह अपने उत्तर में सुधार क्यों और कैसे करेगा। यह "बेहतर होने" के बारे में नहीं है। प्रश्न केवल C # के लिए टैग किया गया है। टैग की तुलना में किसी अन्य भाषा में उत्तर पोस्ट करने की अनुशंसा नहीं की गई है और कुछ लोग इसे छोड़ देंगे।
ThunderGr
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.