17

これはインタビューの質問です

解決策を考えます。キューを使用します。

public Void BFS()    
{   
   Queue q = new Queue();    
   q.Enqueue(root);    
   Console.WriteLine(root.Value);  

   while (q.count > 0)  
   {  
      Node n = q.DeQueue();  
      if (n.left !=null)  
       {  
          Console.Writeln(n.left);  
          q.EnQueue(n.left);  
        }   
       if (n.right !=null)  
       {  
          Console.Writeln(n.right);  
          q.EnQueue(n.right);  
        }   
    }
}    

キューを使用しない、これよりも優れたソリューションを考えられるものはありますか?

4

12 に答える 12

39

レベルごとのトラバーサルは、幅優先トラバーサルとして知られています。これを行うには、キューを使用するのが適切な方法です。深さ優先探索を実行する場合は、スタックを使用します。

しかし、あなたがそれを持っている方法は完全に標準的ではありません。これがどうあるべきかです。

public Void BFS()    
{      
 Queue q = new Queue();
 q.Enqueue(root);//You don't need to write the root here, it will be written in the loop
 while (q.count > 0)
 {
    Node n = q.DeQueue();
    Console.Writeln(n.Value); //Only write the value when you dequeue it
    if (n.left !=null)
    {
        q.EnQueue(n.left);//enqueue the left child
    }
    if (n.right !=null)
    {
       q.EnQueue(n.right);//enque the right child
    }
 }
}

編集

これが機能しているアルゴリズムです。あなたがそのような木を持っていたとしましょう:

     1
    / \
   2   3
  /   / \
 4   5   6

まず、ルート(1)がキューに入れられます。その後、ループに入ります。キュー(1)の最初の項目は、キューから取り出されて印刷されます。1の子は左から右にエンキューされ、キューには{2、3}が含まれ、ループの開始に戻ります。キュー(2)の最初のアイテムはデキューされ、印刷されます。2の子は左から右にエンキューされ、キューには{3、 4}ループの開始に戻る..。

キューには、各ループでこれらの値が含まれます

1:{1}

2:{2、3}

3:{3、4}

4:{4、5、6}

5:{5、6}

6:{6}

7:{} //空、ループは終了します

出力:

1

2

3

4

5

6

于 2009-07-09T15:41:14.927 に答える
17

この質問ではレベルごとにツリーを出力する必要があるため、コンソールにいつ改行文字を出力するかを決定する方法が必要です。NewLineノードをキューに追加することで同じことをしようとする私のコードは次のとおりです。

void PrintByLevel(Node *root)
{
   Queue q;
   Node *newline = new Node("\n");
   Node *v;
   q->enque(root);
   q->enque(newline);

   while(!q->empty()) {
      v = q->deque();
      if(v == newline) {
         printf("\n");
         if(!q->empty())
            q->enque(newline);
      }
      else {
         printf("%s", v->val);
         if(v->Left)
            q-enque(v->left);
         if(v->right)
            q->enque(v->right);
      }
   }
   delete newline;
}
于 2012-05-05T03:53:14.490 に答える
5

いくつかの Scala ソリューションを見てみましょう。まず、非常に基本的なバイナリ ツリーを定義します。

case class Tree[+T](value: T, left: Option[Tree[T]], right: Option[Tree[T]])

次のツリーを使用します。

    1
   / \
  2   3
 /   / \
4   5   6

次のようにツリーを定義します。

val myTree = Tree(1, 
                  Some(Tree(2, 
                            Some(Tree(4, None, None)), 
                            None
                       )
                  ),
                  Some(Tree(3,
                            Some(Tree(5, None, None)),
                            Some(Tree(6, None, None))
                       )
                  )
             )

各要素に目的の関数を適用してツリーを走査する、breadthFirst 関数を定義します。これで、印刷関数を定義し、次のように使用します。

def printTree(tree: Tree[Any]) = 
  breadthFirst(tree, (t: Tree[Any]) => println(t.value))

printTree(myTree)

さて、Scala ソリューション、再帰的、リストはありますが、キューはありません:

def breadthFirst[T](t: Tree[T], f: Tree[T] => Unit): Unit = {
  def traverse(trees: List[Tree[T]]): Unit = trees match {
    case Nil => // do nothing
    case _ =>
      val children = for{tree <- trees
                         Some(child) <- List(tree.left, tree.right)} 
                         yield child
      trees map f
      traverse(children)
  }

  traverse(List(t))
}

次に、Scala ソリューション、キュー、再帰なし:

def breadthFirst[T](t: Tree[T], f: Tree[T] => Unit): Unit = {
  import scala.collection.mutable.Queue
  val queue = new Queue[Option[Tree[T]]]
  import queue._

  enqueue(Some(t))

  while(!isEmpty) 
    dequeue match {
      case Some(tree) => 
        f(tree)
        enqueue(tree.left)
        enqueue(tree.right)
      case None =>
    }
}

この再帰的なソリューションは完全に機能しますが、さらに単純化できるのではないかと不安に思っています。

キューバージョンは機能しませんが、非常に効果的です。オブジェクトのインポートについては、Scala では珍しいことですが、ここではうまく利用されています。

于 2009-07-09T23:03:10.853 に答える
3
public class LevelOrderTraversalQueue {     

    Queue<Nodes> qe = new LinkedList<Nodes>();

    public void printLevelOrder(Nodes root)     
    { 
        if(root == null) return;

        qe.add(root);
        int count = qe.size();

        while(count!=0)
        {   
            System.out.print(qe.peek().getValue());
            System.out.print("  ");
            if(qe.peek().getLeft()!=null) qe.add(qe.peek().getLeft());
            if(qe.peek().getRight()!=null) qe.add(qe.peek().getRight());
            qe.remove(); count = count -1;
            if(count == 0 )
            {
                System.out.println("  ");
                count = qe.size();
            }
        }           
    }

}
于 2014-11-12T07:53:37.293 に答える
1

これを試してください(完全なコード):

class HisTree
{
    public static class HisNode
    {
        private int data;
        private HisNode left;
        private HisNode right;

        public HisNode() {}
        public HisNode(int _data , HisNode _left , HisNode _right)
        {
            data = _data;
            right = _right;
            left = _left;
        }
        public HisNode(int _data)
        {
            data = _data;
        }
    }

    public static int height(HisNode root)
    {
        if (root == null)
        {
            return 0;
        }

        else
        {
            return 1 + Math.max(height(root.left), height(root.right));
        }
    }


    public static void main(String[] args)
    {
//          1
//         /  \ 
//        /    \
//       2      3
//      / \    / \  
//     4    5 6   7
//    /
//   21

        HisNode root1 = new HisNode(3 , new HisNode(6) , new HisNode(7));
        HisNode root3 = new HisNode(4 , new HisNode(21) , null);
        HisNode root2 = new HisNode(2 , root3 , new HisNode(5));
        HisNode root = new HisNode(1 , root2 , root1);
        printByLevels(root);
    }


    private static void printByLevels(HisNode root) {

        List<HisNode> nodes = Arrays.asList(root);
        printByLevels(nodes);

    }

    private static void printByLevels(List<HisNode> nodes)
    {
        if (nodes == null || (nodes != null && nodes.size() <= 0))
        {
            return;
        }
        List <HisNode> nodeList = new LinkedList<HisNode>();
        for (HisNode node : nodes)
        {
            if (node != null)
            {
                System.out.print(node.data);
                System.out.print(" , ");
                nodeList.add(node.left);
                nodeList.add(node.right);
            }
        }
        System.out.println();
        if (nodeList != null && !CheckIfNull(nodeList))
        {
            printByLevels(nodeList);    
        }
        else
        {
            return;
        }

    }


    private static boolean CheckIfNull(List<HisNode> list)
    {
        for(HisNode elem : list)
        {
            if (elem != null)
            {
                return false;
            }
        }
        return true;
    }
}
于 2015-09-03T23:08:27.823 に答える
1

レベルごとに出力するには、キューに追加するタプルとしてレベル情報をノードに格納できます。その後、レベルが変更されるたびに新しい行を印刷できます。そのための Python コードを次に示します。

from collections import deque
class BTreeNode:
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

    def printLevel(self):
        """ Breadth-first traversal, print out the data by level """
        level = 0
        lastPrintedLevel = 0
        visit = deque([])
        visit.append((self, level))
        while len(visit) != 0:
            item = visit.popleft()
            if item[1] != lastPrintedLevel:  #New line for a new level
                lastPrintedLevel +=1
                print
            print item[0].data,
            if item[0].left != None:
                visit.append((item[0].left, item[1] + 1))
            if item[0].right != None: 
                visit.append((item[0].right, item[1] + 1))
于 2012-04-30T22:35:12.847 に答える
0

nullノードを表示し、高さで出力するように答えを微調整しました。赤黒の木のバランスをテストするには、実際にはかなりまともでした。
印刷行に色を追加して、黒の高さを確認することもできます。

    Queue<node> q = new Queue<node>();
    int[] arr = new int[]{1,2,4,8,16,32,64,128,256};
    int i =0;
    int b = 0;
    int keeper = 0;
    public void BFS()
    {


        q.Enqueue(root);
        while (q.Count > 0)
        {

            node n = q.Dequeue();

            if (i == arr[b])
            {

                System.Diagnostics.Debug.Write("\r\n"+"("+n.id+")"); 
                b++;
                i =0 ;
            }
            else {

                System.Diagnostics.Debug.Write("(" + n.id + ")"); 

            }
            i++; 


            if (n.id != -1)
            {



                if (n.left != null)
                {

                    q.Enqueue(n.left);
                }
                else
                {
                    node c = new node();
                    c.id = -1;
                    c.color = 'b';
                    q.Enqueue(c);
                }

                if (n.right != null)
                {

                    q.Enqueue(n.right);
                }
                else
                {
                    node c = new node();
                    c.id = -1;
                    c.color = 'b';
                    q.Enqueue(c);

                }
            }

        }
        i = 0;
        b = 0;
        System.Diagnostics.Debug.Write("\r\n");
    }
于 2015-06-01T22:16:16.967 に答える