2016-03-30 9 views
12

में एक द्विआधारी खोज वृक्ष प्रदर्शित करें मैं सरल द्विआधारी खोज वृक्ष हैसी # कंसोल

public class BNode 
{ 
    public int item; 
    public BNode right; 
    public BNode left; 

    public BNode(int item) 
    { 
     this.item = item; 
    } 
} 

public class BTree 
{ 
    private BNode _root; 
    private int _count; 
    private IComparer<int> _comparer = Comparer<int>.Default; 


    public BTree() 
    { 
     _root = null; 
     _count = 0; 
    } 


    public bool Add(int Item) 
    { 
     if (_root == null) 
     { 
      _root = new BNode(Item); 
      _count++; 
      return true; 
     } 
     else 
     { 
      return Add_Sub(_root, Item); 
     } 
    } 

    private bool Add_Sub(BNode Node, int Item) 
    { 
     if (_comparer.Compare(Node.item, Item) < 0) 
     { 
      if (Node.right == null) 
      { 
       Node.right = new BNode(Item); 
       _count++; 
       return true; 
      } 
      else 
      { 
       return Add_Sub(Node.right, Item); 
      } 
     } 
     else if (_comparer.Compare(Node.item, Item) > 0) 
     { 
      if (Node.left == null) 
      { 
       Node.left = new BNode(Item); 
       _count++; 
       return true; 
      } 
      else 
      { 
       return Add_Sub(Node.left, Item); 
      } 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public void Print() 
    { 
     Print(_root, 4); 
    } 

    public void Print(BNode p, int padding) 
    { 
     if (p != null) 
     { 
      if (p.right != null) 
      { 
       Print(p.right, padding + 4); 
      } 
      if (padding > 0) 
      { 
       Console.Write(" ".PadLeft(padding)); 
      } 
      if (p.right != null) 
      { 
       Console.Write("/\n"); 
       Console.Write(" ".PadLeft(padding)); 
      } 
      Console.Write(p.item.ToString() + "\n "); 
      if (p.left != null) 
      { 
       Console.Write(" ".PadLeft(padding) + "\\\n"); 
       Print(p.left, padding + 4); 
      } 
     } 
    } 
} 

मैं कहाँ की तरह

BTree btr = new BTree(); 
btr.Add(6); 
btr.Add(2); 
btr.Add(3); 
btr.Add(11); 
btr.Add(30); 
btr.Add(9); 
btr.Add(13); 
btr.Add(18); 

मैं अपने सांत्वना आवेदन के भीतर मेरी पेड़ प्रदर्शित करना चाहते हैं मान सम्मिलित कर सकते हैं। मेरे पास btr.Print(); है जो मेरे पेड़ को बाएं से दाएं (6 रूट) दिखाता है - लेकिन मैं इससे खुश नहीं हूं।

enter image description here

प्रश्न: वहाँ एक सांत्वना आवेदन के भीतर इस पेड़ प्रदर्शित करने के लिए एक बेहतर तरीका है? यहां तक ​​कि Print() का सुधार भी मेरी मदद करेगा।

+0

मैं इस अन्य लिंक में दृष्टिकोण अच्छे लग रहा है लगता है और अधिक कॉम्पैक्ट: http://stackoverflow.com/a/1649223/831138। इस तथ्य में "कॉम्पैक्ट" कि एक ही स्क्रीन स्पेस में अधिक जानकारी फिट कर सकता है ... बेशक यह इसे लंबवत रूप से फैलाने जा रहा है, लेकिन कंसोल की स्क्रॉलबार का उपयोग करना कोई समस्या नहीं होनी चाहिए ... क्षैतिज से बाहर चलना अंतरिक्ष एक समस्या है। –

+0

[ट्री विज़ुअलाइजेशन एल्गोरिदम] का संभावित डुप्लिकेट (http://stackoverflow.com/questions/8368386/tree-visualization-algorithm) – mbeckish

+0

http://stackoverflow.com/questions/801740/c-how-to-draw-a -बिनरी-पेड़-टू-द-कंसोल – fubo

उत्तर

14

मैं निम्न विधि है कि आप मनमाने ढंग से सबट्री प्रिंट करने देता है के साथ समाप्त हो गया है:

public static class BTreePrinter 
{ 
    class NodeInfo 
    { 
     public BNode Node; 
     public string Text; 
     public int StartPos; 
     public int Size { get { return Text.Length; } } 
     public int EndPos { get { return StartPos + Size; } set { StartPos = value - Size; } } 
     public NodeInfo Parent, Left, Right; 
    } 

    public static void Print(this BNode root, string textFormat = "0", int spacing = 1, int topMargin = 2, int leftMargin = 2) 
    { 
     if (root == null) return; 
     int rootTop = Console.CursorTop + topMargin; 
     var last = new List<NodeInfo>(); 
     var next = root; 
     for (int level = 0; next != null; level++) 
     { 
      var item = new NodeInfo { Node = next, Text = next.item.ToString(textFormat) }; 
      if (level < last.Count) 
      { 
       item.StartPos = last[level].EndPos + spacing; 
       last[level] = item; 
      } 
      else 
      { 
       item.StartPos = leftMargin; 
       last.Add(item); 
      } 
      if (level > 0) 
      { 
       item.Parent = last[level - 1]; 
       if (next == item.Parent.Node.left) 
       { 
        item.Parent.Left = item; 
        item.EndPos = Math.Max(item.EndPos, item.Parent.StartPos - 1); 
       } 
       else 
       { 
        item.Parent.Right = item; 
        item.StartPos = Math.Max(item.StartPos, item.Parent.EndPos + 1); 
       } 
      } 
      next = next.left ?? next.right; 
      for (; next == null; item = item.Parent) 
      { 
       int top = rootTop + 2 * level; 
       Print(item.Text, top, item.StartPos); 
       if (item.Left != null) 
       { 
        Print("/", top + 1, item.Left.EndPos); 
        Print("_", top, item.Left.EndPos + 1, item.StartPos); 
       } 
       if (item.Right != null) 
       { 
        Print("_", top, item.EndPos, item.Right.StartPos - 1); 
        Print("\\", top + 1, item.Right.StartPos - 1); 
       } 
       if (--level < 0) break; 
       if (item == item.Parent.Left) 
       { 
        item.Parent.StartPos = item.EndPos + 1; 
        next = item.Parent.Node.right; 
       } 
       else 
       { 
        if (item.Parent.Left == null) 
         item.Parent.EndPos = item.StartPos - 1; 
        else 
         item.Parent.StartPos += (item.StartPos - 1 - item.Parent.EndPos)/2; 
       } 
      } 
     } 
     Console.SetCursorPosition(0, rootTop + 2 * last.Count - 1); 
    } 

    private static void Print(string s, int top, int left, int right = -1) 
    { 
     Console.SetCursorPosition(left, top); 
     if (right < 0) right = left + s.Length; 
     while (Console.CursorLeft < right) Console.Write(s); 
    } 
} 

आप देख सकते हैं, मैं मैंने कुछ पैरामीटर जोड़े जो स्वरूपण को प्रभावित करते हैं। डिफ़ॉल्ट रूप से यह सबसे कॉम्पैक्ट प्रतिनिधित्व पैदा करता है।

ताकि इसे साथ खेलने के लिए में, मैं BTree वर्ग संशोधित कर लिया है इस प्रकार है:

btr.Root.Print();

enter image description here

:

public class BTree 
{ 
    // ... 

    public BNode Root { get { return _root; } } 

    public void Print() 
    { 
     Root.Print(); 
    } 
} 

अपने नमूना डेटा का उपयोग करना, यहाँ कुछ परिणाम हैं

btr.Root.Print(textFormat: "(0)", spacing: 2);

enter image description here

अद्यतन: IMO ऊपर डिफ़ॉल्ट प्रारूप कॉम्पैक्ट और पठनीय है, लेकिन सिर्फ मनोरंजन के लिए, एल्गोरिथ्म अधिक "चित्रमय" उत्पादन का उत्पादन करने के लिए (textFormat और spacing पैरामीटर निकाल दिए) समायोजित:

public static class BTreePrinter 
{ 
    class NodeInfo 
    { 
     public BNode Node; 
     public string Text; 
     public int StartPos; 
     public int Size { get { return Text.Length; } } 
     public int EndPos { get { return StartPos + Size; } set { StartPos = value - Size; } } 
     public NodeInfo Parent, Left, Right; 
    } 

    public static void Print(this BNode root, int topMargin = 2, int leftMargin = 2) 
    { 
     if (root == null) return; 
     int rootTop = Console.CursorTop + topMargin; 
     var last = new List<NodeInfo>(); 
     var next = root; 
     for (int level = 0; next != null; level++) 
     { 
      var item = new NodeInfo { Node = next, Text = next.item.ToString(" 0 ") }; 
      if (level < last.Count) 
      { 
       item.StartPos = last[level].EndPos + 1; 
       last[level] = item; 
      } 
      else 
      { 
       item.StartPos = leftMargin; 
       last.Add(item); 
      } 
      if (level > 0) 
      { 
       item.Parent = last[level - 1]; 
       if (next == item.Parent.Node.left) 
       { 
        item.Parent.Left = item; 
        item.EndPos = Math.Max(item.EndPos, item.Parent.StartPos); 
       } 
       else 
       { 
        item.Parent.Right = item; 
        item.StartPos = Math.Max(item.StartPos, item.Parent.EndPos); 
       } 
      } 
      next = next.left ?? next.right; 
      for (; next == null; item = item.Parent) 
      { 
       Print(item, rootTop + 2 * level); 
       if (--level < 0) break; 
       if (item == item.Parent.Left) 
       { 
        item.Parent.StartPos = item.EndPos; 
        next = item.Parent.Node.right; 
       } 
       else 
       { 
        if (item.Parent.Left == null) 
         item.Parent.EndPos = item.StartPos; 
        else 
         item.Parent.StartPos += (item.StartPos - item.Parent.EndPos)/2; 
       } 
      } 
     } 
     Console.SetCursorPosition(0, rootTop + 2 * last.Count - 1); 
    } 

    private static void Print(NodeInfo item, int top) 
    { 
     SwapColors(); 
     Print(item.Text, top, item.StartPos); 
     SwapColors(); 
     if (item.Left != null) 
      PrintLink(top + 1, "┌", "┘", item.Left.StartPos + item.Left.Size/2, item.StartPos); 
     if (item.Right != null) 
      PrintLink(top + 1, "└", "┐", item.EndPos - 1, item.Right.StartPos + item.Right.Size/2); 
    } 

    private static void PrintLink(int top, string start, string end, int startPos, int endPos) 
    { 
     Print(start, top, startPos); 
     Print("─", top, startPos + 1, endPos); 
     Print(end, top, endPos); 
    } 

    private static void Print(string s, int top, int left, int right = -1) 
    { 
     Console.SetCursorPosition(left, top); 
     if (right < 0) right = left + s.Length; 
     while (Console.CursorLeft < right) Console.Write(s); 
    } 

    private static void SwapColors() 
    { 
     var color = Console.ForegroundColor; 
     Console.ForegroundColor = Console.BackgroundColor; 
     Console.BackgroundColor = color; 
    } 
} 

और परिणाम है:

enter image description here

+3

वास्तव में इस कोड को पसंद है, अच्छा काम है। बहुत साफ और पठनीय। – Jacobr365

+1

धन्यवाद, यही वह है जो मैं ढूंढ रहा था - महान काम – fubo

7

यह इस पर मेरी ले है:

मैं BNode को PrintPretty जोड़ दिया है, और मैं दूसरे Print समारोह आप BTREE में था हटा दिया है।

(संपादित करें: मैं मूल वर्ण बदलने के पेड़ की शाखाओं आकर्षित करने के लिए से पेड़ अधिक lisible बनाया) (जैसा कि मैंने उल्लेख किया है, अधिक कॉम्पैक्ट)

static void Main(string[] args) 
    { 
     BTree btr = new BTree(); 
     btr.Add(6); 
     btr.Add(2); 
     btr.Add(3); 
     btr.Add(11); 
     btr.Add(30); 
     btr.Add(9); 
     btr.Add(13); 
     btr.Add(18); 

     btr.Print(); 

    } 

    public class BNode 
    { 
     public int item; 
     public BNode right; 
     public BNode left; 

     public BNode(int item) 
     { 
      this.item = item; 
     } 

     public void PrintPretty(string indent, bool last) 
     { 

      Console.Write(indent); 
      if (last) 
      { 
       Console.Write("└─"); 
       indent += " "; 
      } 
      else 
      { 
       Console.Write("├─"); 
       indent += "| "; 
      } 
      Console.WriteLine(item); 

      var children = new List<BNode>(); 
      if (this.left != null) 
       children.Add(this.left); 
      if (this.right != null) 
       children.Add(this.right); 

      for (int i = 0; i < children.Count; i++) 
       children[i].PrintPretty(indent, i == children.Count - 1); 

     } 

    } 

    public class BTree 
    { 
     private BNode _root; 
     private int _count; 
     private IComparer<int> _comparer = Comparer<int>.Default; 


     public BTree() 
     { 
      _root = null; 
      _count = 0; 
     } 


     public bool Add(int Item) 
     { 
      if (_root == null) 
      { 
       _root = new BNode(Item); 
       _count++; 
       return true; 
      } 
      else 
      { 
       return Add_Sub(_root, Item); 
      } 
     } 

     private bool Add_Sub(BNode Node, int Item) 
     { 
      if (_comparer.Compare(Node.item, Item) < 0) 
      { 
       if (Node.right == null) 
       { 
        Node.right = new BNode(Item); 
        _count++; 
        return true; 
       } 
       else 
       { 
        return Add_Sub(Node.right, Item); 
       } 
      } 
      else if (_comparer.Compare(Node.item, Item) > 0) 
      { 
       if (Node.left == null) 
       { 
        Node.left = new BNode(Item); 
        _count++; 
        return true; 
       } 
       else 
       { 
        return Add_Sub(Node.left, Item); 
       } 
      } 
      else 
      { 
       return false; 
      } 
     } 

     public void Print() 
     { 
      _root.PrintPretty("", true); 
     } 

    } 

यह परिणाम है:

enter image description here


संपादित करें: निम्नलिखित कोड आदेश बाएं अधिकार के बारे में जानकारी दिखाने के लिए संशोधित किया गया है:

static void Main(string[] args) 
    { 
     BTree btr = new BTree(); 
     btr.Add(6); 
     btr.Add(2); 
     btr.Add(3); 
     btr.Add(11); 
     btr.Add(30); 
     btr.Add(9); 
     btr.Add(13); 
     btr.Add(18); 

     btr.Print(); 

    } 

    public enum NodePosition 
    { 
     left, 
     right, 
     center 
    } 

    public class BNode 
    { 
     public int item; 
     public BNode right; 
     public BNode left; 

     public BNode(int item) 
     { 
      this.item = item; 
     } 

     private void PrintValue(string value, NodePosition nodePostion) 
     { 
      switch (nodePostion) 
      { 
       case NodePosition.left: 
        PrintLeftValue(value); 
        break; 
       case NodePosition.right: 
        PrintRightValue(value); 
        break; 
       case NodePosition.center: 
        Console.WriteLine(value); 
        break; 
       default: 
        throw new NotImplementedException(); 
      } 
     } 

     private void PrintLeftValue(string value) 
     { 
      Console.ForegroundColor = ConsoleColor.Magenta; 
      Console.Write("L:"); 
      Console.ForegroundColor = (value == "-") ? ConsoleColor.Red : ConsoleColor.Gray; 
      Console.WriteLine(value); 
      Console.ForegroundColor = ConsoleColor.Gray; 
     } 

     private void PrintRightValue(string value) 
     { 
      Console.ForegroundColor = ConsoleColor.Green; 
      Console.Write("R:"); 
      Console.ForegroundColor = (value == "-") ? ConsoleColor.Red : ConsoleColor.Gray; 
      Console.WriteLine(value); 
      Console.ForegroundColor = ConsoleColor.Gray; 
     } 

     public void PrintPretty(string indent, NodePosition nodePosition, bool last, bool empty) 
     { 

      Console.Write(indent); 
      if (last) 
      { 
       Console.Write("└─"); 
       indent += " "; 
      } 
      else 
      { 
       Console.Write("├─"); 
       indent += "| "; 
      } 

      var stringValue = empty ? "-" : item.ToString(); 
      PrintValue(stringValue, nodePosition); 

      if(!empty && (this.left != null || this.right != null)) 
      { 
       if (this.left != null) 
        this.left.PrintPretty(indent, NodePosition.left, false, false); 
       else 
        PrintPretty(indent, NodePosition.left, false, true); 

       if (this.right != null) 
        this.right.PrintPretty(indent, NodePosition.right, true, false); 
       else 
        PrintPretty(indent, NodePosition.right, true, true); 
      } 
     } 

    } 

    public class BTree 
    { 
     private BNode _root; 
     private int _count; 
     private IComparer<int> _comparer = Comparer<int>.Default; 


     public BTree() 
     { 
      _root = null; 
      _count = 0; 
     } 


     public bool Add(int Item) 
     { 
      if (_root == null) 
      { 
       _root = new BNode(Item); 
       _count++; 
       return true; 
      } 
      else 
      { 
       return Add_Sub(_root, Item); 
      } 
     } 

     private bool Add_Sub(BNode Node, int Item) 
     { 
      if (_comparer.Compare(Node.item, Item) < 0) 
      { 
       if (Node.right == null) 
       { 
        Node.right = new BNode(Item); 
        _count++; 
        return true; 
       } 
       else 
       { 
        return Add_Sub(Node.right, Item); 
       } 
      } 
      else if (_comparer.Compare(Node.item, Item) > 0) 
      { 
       if (Node.left == null) 
       { 
        Node.left = new BNode(Item); 
        _count++; 
        return true; 
       } 
       else 
       { 
        return Add_Sub(Node.left, Item); 
       } 
      } 
      else 
      { 
       return false; 
      } 
     } 

     public void Print() 
     { 
      _root.PrintPretty("", NodePosition.center, true, false); 
     } 

    } 

परिणाम:

enter image description here

+0

ठीक है यह बदनाम रूप से एक बेहतर और अधिक कॉम्पैक्ट संस्करण +1 है - लेकिन यह एक जानकारी खो देता है - यदि कोई बच्चा नोड बाईं ओर है (मान पैरेंट नोड से कम है) या चालू दाहिने तरफ (मान अधिक है) – fubo

+0

@fubo आप बिल्कुल सही हैं, मैंने इसे पोस्ट करने के बाद कल इसके बारे में सोचा था, लेकिन मेरे पास इसे सही करने का कोई समय नहीं था ... अब मैंने बाएं के बारे में जानकारी दिखाने के लिए कोड को थोड़ा बदल दिया है और सही। एक चीज जो कंसोल में उपयोग कर सकती है क्रम में रंगों के साथ खेलने के लिए और अधिक दृश्य जानकारी जोड़ना है, और यह कुछ भी है जिसे मैंने इस नए संस्करण में जोड़ा है। –

संबंधित मुद्दे