পুনরাবৃত্তভাবে প্রস্থের প্রথম অনুসন্ধান সম্পাদন করা হচ্ছে


152

ধরা যাক আপনি বার বার বাইনারি গাছের প্রস্থের প্রথম অনুসন্ধানটি পুনরাবৃত্তভাবে কার্যকর করতে চেয়েছিলেন । আপনি এটি সম্পর্কে কিভাবে যেতে হবে?

সহায়ক কল হিসাবে কেবল কল-স্ট্যাক ব্যবহার করা কি সম্ভব?


14
খুব ভাল প্রশ্ন। এটি মোটেই সহজ নয়। মূলত আপনি কেবল একটি স্ট্যাক ব্যবহার করে একটি বিএফএস বাস্তবায়ন করতে বলছেন।
সিসিস

4
পুনরাবৃত্তি কেবল একটি স্ট্যাক দিয়ে? এটা আমার মাথা ব্যাথা
কেভিন ফ্রিডহাইম

11
আমি পুনরাবৃত্ত আচরণগুলি অপসারণ করতে সাধারণত একটি স্ট্যাক ব্যবহার করি
নিউটোপিয়ান

আমি যদি একটি ম্যাক্সের স্তূপে বিএফএস ব্যবহার করি তবে আমি অবাক হয়েছি যে নীচের দেওয়া সমাধানগুলি সঠিকভাবে কাজ করে? কোন চিন্তা ?
জে ডি

উত্তর:


122

(আমি ধরে নিচ্ছি যে এটি কেবল এক ধরণের চিন্তার অনুশীলন, বা এমনকি কোনও কৌশল হোমওয়ার্ক / সাক্ষাত্কারের প্রশ্ন, তবে আমি মনে করি যে আমি এমন কিছু উদ্ভট পরিস্থিতি কল্পনা করতে পারি যেখানে আপনাকে কোনও কারণে কোনও গাদা জায়গার অনুমতি নেই [কিছুটা সত্যই খারাপ রীতিনীতি মেমোরি ম্যানেজার? কিছু উদ্ভট রানটাইম / ওএস সমস্যা?] আপনার কাছে এখনও স্ট্যাকের অ্যাক্সেস রয়েছে ...)

প্রস্থের প্রথম ট্র্যাভারসাল traditionতিহ্যগতভাবে স্ট্যাক নয়, একটি সারি ব্যবহার করে। একটি সারি এবং স্ট্যাকের প্রকৃতি একেবারেই বিপরীত, তাই কল স্ট্যাক (যা একটি স্ট্যাক, তাই নাম) হিসাবে ব্যবহার করার চেষ্টা করা হয়েছে কারণ সহায়ক স্টোরেজ (একটি সারি) ব্যর্থতা ডুবে গেছে, যদি না আপনি করছেন কল স্ট্যাকের সাথে বোকার মতো হাস্যকর কিছু যা আপনার হওয়া উচিত নয়।

একই টোকনে আপনি যে কোনও অ-লেজ পুনরাবৃত্তি বাস্তবায়নের চেষ্টা করছেন তা প্রকৃতপক্ষে অ্যালগরিদমে একটি স্ট্যাক যুক্ত করছে। এটি বাইনারি গাছের উপর প্রথম প্রস্থের আর আর প্রস্থ নয় এবং এভাবে রান-টাইম এবং traditionalতিহ্যবাহী বিএফএসের জন্য এখন আর সম্পূর্ণরূপে প্রয়োগ হয় না। অবশ্যই, আপনি সর্বদা তুচ্ছভাবে যেকোন লুপকে পুনরাবৃত্তির কলগুলিতে পরিণত করতে পারেন, তবে এটি কোনও ধরণের অর্থবহ পুনরাবৃত্তি নয়।

যাইহোক, অন্যদের দ্বারা প্রদর্শিত হিসাবে কিছু ব্যয়ে বিএফএস এর শব্দার্থবিজ্ঞান অনুসরণ করে এমন কিছু বাস্তবায়নের উপায় রয়েছে। যদি তুলনার ব্যয় ব্যয়বহুল তবে নোড ট্র্যাভারসাল সস্তা, তবে @ সিমন বুচান যেমন করেছিলেন, আপনি কেবল পুনরাবৃত্তির গভীরতা-প্রথম অনুসন্ধান চালাতে পারেন, কেবল পাতাগুলি প্রক্রিয়াকরণ করতে। এর অর্থ হ'ল হিপগুলিতে কোনও ক্রমবর্ধমান কিউ সঞ্চিত নেই, কেবল একটি স্থানীয় গভীরতার পরিবর্তনশীল, এবং গাছটি বার বার ট্র্যাশ করায় কল স্ট্যাকের উপর স্ট্যাকগুলি বার বার তৈরি করা হচ্ছে। এবং @ পেট্রিকের হিসাবে উল্লেখ করা হয়েছে যে অ্যারে দ্বারা সমর্থিত একটি বাইনারি গাছ সাধারণত প্রস্থের প্রথম ট্র্যাভারসাল ক্রমে সংরক্ষণ করা হয়, সুতরাং এটির জন্য প্রস্থের প্রথম অনুসন্ধানটি তুচ্ছ হবে, এছাড়াও একটি সহায়ক সারি প্রয়োজন ছাড়াই।


10
এটি প্রকৃতপক্ষে কেবল একটি চিন্তার অনুশীলন। আপনি বাস্তবে এটি করতে চাইলে এমন পরিস্থিতি আমি সত্যিই কল্পনা করতে পারি না। সুচিন্তিত উত্তরের জন্য ধন্যবাদ!
নট

2
" তবে আমি মনে করি আমি এমন কিছু উদ্ভট পরিস্থিতিটি কল্পনা করতে পারি যেখানে আপনাকে কোনও কারণে কোনও গাদা জায়গার অনুমতি নেই ": হ্যাঁ, আমি এমন একটি এমবেডেড পরিবেশের কল্পনা করতে পারি যেখানে কেবল স্ট্যাক (কেবল কোনও পঠনযোগ্য মেমরির স্থান সহ) উপলব্ধ থাকে (এটি আপনার প্রোগ্রামটি কী করতে চলেছে ঠিক তা যদি আপনি জানেন তবে এমবেডেড সফ্টওয়্যারটিতে সাধারণত এমনটি হয় তবে হিপটি ব্যবহার না করেই সফ্টওয়্যার লিখতে আসলে বেশ সহজ এবং দক্ষ) সুতরাং এটি আমার কাছে "উদ্ভট" নয়। অস্বাভাবিক, সম্ভবত, তবে উদ্ভট নয়।
টমাস

আমি মনে করি যে আপনার উত্তরটিতে এই নিবন্ধটির একটি উল্লেখ থাকতে পারে ( ibm.com/developerworks/aix/library/au-aix-stack-tree-traversal )। এটি আপনার উত্তরের দ্বিতীয় অংশে আপনি যা লিখেছেন সে সম্পর্কে একটি বাস্তবায়ন দেখায়
55

25

আপনি যদি বাইনারি গাছের পিছনে পিছনে অ্যারে ব্যবহার করেন তবে আপনি পরবর্তী নোড বীজগণিতভাবে নির্ধারণ করতে পারেন। যদি iনোড হয় তবে তার বাচ্চাদের 2i + 1(বাম নোডের জন্য) এবং 2i + 2(ডান নোডের জন্য) পাওয়া যাবে। কোনও নোডের পরবর্তী প্রতিবেশী দ্বারা প্রদত্ত হয় i + 1, যদি না এর iশক্তি থাকে2

অ্যারে ব্যাকড বাইনারি সার্চ ট্রিতে প্রস্থের প্রথম সন্ধানের খুব নিখুঁত বাস্তবায়নের জন্য এখানে সিউডোকোড। এটি একটি স্থির আকারের অ্যারে এবং সেইজন্য একটি নির্দিষ্ট গভীরতার গাছ ধরে নেয়। এটি প্যারেন্টলেস নোডগুলির দিকে নজর দেবে এবং এটি একটি নিয়ন্ত্রণহীনভাবে বড় স্ট্যাক তৈরি করতে পারে।

bintree-bfs(bintree, elt, i)
    if (i == LENGTH)
        return false

    else if (bintree[i] == elt)
        return true

    else 
        return bintree-bfs(bintree, elt, i+1)        

1
খুশী হলাম। আমরা একটি বাইনারি গাছের সাথে কাজ করছি এই বিষয়টি আমি উপেক্ষা করেছি। সূচকগুলি ডিএফএস ব্যবহার করে নির্ধারিত হতে পারে। বিটিডাব্লু, আপনি প্রথম ক্ষেত্রে মিথ্যা রিটার্ন ভুলে গেছেন।
সিসিস

আমি মনে করি যে আমি সারিবদ্ধ পদ্ধতিটি পছন্দ করি; পি। যুক্ত মিথ্যা প্রত্যাবর্তন।
প্যাট্রিক ম্যাকমার্চি

1
চালাক। একটি অ্যারেতে নোডগুলি সংরক্ষণ এবং বীজগণিতভাবে তাদের উল্লেখ করার ধারণা আমার কাছে আসেনি।
নট

19

এটি সম্পূর্ণ পুনরাবৃত্ত করার কোনও উপায় আমি খুঁজে পাইনি (কোনও সহায়ক ডেটা-কাঠামো ছাড়াই)। তবে যদি সারি কিউ রেফারেন্স দিয়ে চলে যায় তবে আপনার নীচের মূ tail় লেজ পুনরাবৃত্ত ফাংশন থাকতে পারে:

BFS(Q)
{
  if (|Q| > 0)
     v <- Dequeue(Q)
     Traverse(v)
     foreach w in children(v)
        Enqueue(Q, w)    

     BFS(Q)
}

6
পরিষ্কার এবং সঠিক ফাংশনটিতে পুনরাবৃত্তিকে যুক্ত করার জন্য এটি অপ্রাকৃত উপায়।
রহস্যময়

সম্পূর্ণরূপে একমত নয় - আমি এটি আরও প্রাকৃতিক বলে মনে করি - এবং আরও দরকারী;
গোল্ডেন

15

একটি নির্দিষ্ট গভীরতায় সমস্ত নোড পেতে নিম্নলিখিত পদ্ধতিটি একটি ডিএফএস অ্যালগরিদম ব্যবহার করেছে - যা স্তরের জন্য বিএফএস করার মতো same আপনি যদি গাছের গভীরতা সন্ধান করেন এবং সব স্তরের জন্য এটি করেন, ফলাফলগুলি বিএফএসের মতো হবে।

public void PrintLevelNodes(Tree root, int level) {
    if (root != null) {
        if (level == 0) {
            Console.Write(root.Data);
            return;
        }
        PrintLevelNodes(root.Left, level - 1);
        PrintLevelNodes(root.Right, level - 1);
    }
}

for (int i = 0; i < depth; i++) {
    PrintLevelNodes(root, i);
}

গাছের গভীরতা সন্ধান করা একটি কেকের টুকরো:

public int MaxDepth(Tree root) {
    if (root == null) {
        return 0;
    } else {
        return Math.Max(MaxDepth(root.Left), MaxDepth(root.Right)) + 1;
    }
}

আপনার কোড গঠনে দয়া করে একটু বেশি মনোযোগ দিন। আমি কিছু পরিবর্তন করেছি।
মিচা

তবে ধরুন ... এটি কি বিএফএসের চেয়ে ডিএফএস? কারণ মুদ্রণভেলনোডগুলি levelশূন্য না হওয়া পর্যন্ত ফিরে আসে না ।
হেরিংটন দারখোলমে

1
পুনঃটুইট এটি ডিএফএস অনুসন্ধান করে তবে আউটপুট মানগুলি যেমন কোনও স্তরের জন্য কোনও বিএফএস করে। এটি নির্দেশ করার জন্য ধন্যবাদ।
সানজ

1
@ সঞ্জয়, ডিএফএস-অর্ডারে নোডগুলিতে কীভাবে কেউ কিছু কার্য সম্পাদন করতে পারে তার পক্ষে এটি সত্যিই একটি ভাল প্রদর্শন। এটি কীভাবে ডিএফএস-ক্রমে নোডগুলিকে "স্পর্শ" করতে পারে তা অগত্যা নয়, তবে অবশ্যই ডিএফএস ক্রমে নোডগুলিতে পুনরাবৃত্তভাবে "কাজ" করার অনুমতি দেবে, এই ক্ষেত্রে তাদের মানগুলি মুদ্রণ করে।
বুঙ্কারডাইভ

8

জাভাতে একটি সাধারণ বিএফএস এবং ডিএফএস পুনরাবৃত্তি:
কেবল স্ট্যাক / সারিতে গাছের মূল নোডটি চাপ / অফার করুন এবং এই ফাংশনগুলিকে কল করুন।

public static void breadthFirstSearch(Queue queue) {

    if (queue.isEmpty())
        return;

    Node node = (Node) queue.poll();

    System.out.println(node + " ");

    if (node.right != null)
        queue.offer(node.right);

    if (node.left != null)
        queue.offer(node.left);

    breadthFirstSearch(queue);
}

public static void depthFirstSearch(Stack stack) {

    if (stack.isEmpty())
        return;

    Node node = (Node) stack.pop();

    System.out.println(node + " ");

    if (node.right != null)
        stack.push(node.right);

    if (node.left != null)
        stack.push(node.left);

    depthFirstSearch(stack);
}

4
ডিএফএসের জন্য প্যারামিটার হিসাবে স্ট্যাকটি পাস করা কিছুটা অদ্ভুত কারণ আপনার ইতিমধ্যে সেখানে অন্তর্নিহিত স্ট্যাক রয়েছে। এছাড়াও প্রশ্নটি কেবলমাত্র ডেটা কাঠামো হিসাবে কল স্ট্যাক ব্যবহার করার ছিল।
ভ্লাদিচ

4

আমি একটি খুব সুন্দর পুনরাবৃত্তির (এমনকি ক্রিয়ামূলক) প্রস্থ-প্রথম ট্র্যাভারসাল সম্পর্কিত আলগোরিদম পেয়েছি। আমার ধারণা নয়, তবে আমি মনে করি এটি এই বিষয়টিতে উল্লেখ করা উচিত।

ক্রিস ওকাসাকি আইসিএফপি 2000 থেকে তাঁর প্রস্থের প্রথম সংখ্যা নির্ধারণের অ্যালগরিদমটি http://okasaki.blogspot.de/2008/07/breadth-first-numbering-algorithm-in.html তে মাত্র 3 টি ছবি সহ খুব স্পষ্টভাবে ব্যাখ্যা করেছেন।

দেবাশীষ ঘোষের স্কেল বাস্তবায়ন, যা আমি http://debasishg.blogspot.de/2008/09/breadth-first-numbering-okasakis.html এ খুঁজে পেয়েছি :

trait Tree[+T]
case class Node[+T](data: T, left: Tree[T], right: Tree[T]) extends Tree[T]
case object E extends Tree[Nothing]

def bfsNumForest[T](i: Int, trees: Queue[Tree[T]]): Queue[Tree[Int]] = {
  if (trees.isEmpty) Queue.Empty
  else {
    trees.dequeue match {
      case (E, ts) =>
        bfsNumForest(i, ts).enqueue[Tree[Int]](E)
      case (Node(d, l, r), ts) =>
        val q = ts.enqueue(l, r)
        val qq = bfsNumForest(i+1, q)
        val (bb, qqq) = qq.dequeue
        val (aa, tss) = qqq.dequeue
        tss.enqueue[org.dg.collection.BFSNumber.Tree[Int]](Node(i, aa, bb))
    }
  }
}

def bfsNumTree[T](t: Tree[T]): Tree[Int] = {
  val q = Queue.Empty.enqueue[Tree[T]](t)
  val qq = bfsNumForest(1, q)
  qq.dequeue._1
}

সুন্দর অ্যালগরিদমের জন্য +1। তবে, আমি এটি এখনও একটি সারি ব্যবহার করে দেখতে পেলাম। "বিধি 3" এর বাম দিকটি হ'ল প্রকৃতপক্ষে ডেলিউ এবং এনক্যু অপারেশন operations
লুক

3

বোবা উপায়:

template<typename T>
struct Node { Node* left; Node* right; T value; };

template<typename T, typename P>
bool searchNodeDepth(Node<T>* node, Node<T>** result, int depth, P pred) {
    if (!node) return false;
    if (!depth) {
        if (pred(node->value)) {
            *result = node;
        }
        return true;
    }
    --depth;
    searchNodeDepth(node->left, result, depth, pred);
    if (!*result)
        searchNodeDepth(node->right, result, depth, pred);
    return true;
}

template<typename T, typename P>
Node<T>* searchNode(Node<T>* node, P pred) {
    Node<T>* result = NULL;
    int depth = 0;
    while (searchNodeDepth(node, &result, depth, pred) && !result)
        ++depth;
    return result;
}

int main()
{
    // a c   f
    //  b   e
    //    d
    Node<char*>
        a = { NULL, NULL, "A" },
        c = { NULL, NULL, "C" },
        b = { &a, &c, "B" },
        f = { NULL, NULL, "F" },
        e = { NULL, &f, "E" },
        d = { &b, &e, "D" };

    Node<char*>* found = searchNode(&d, [](char* value) -> bool {
        printf("%s\n", value);
        return !strcmp((char*)value, "F");
    });

    printf("found: %s\n", found->value);

    return 0;
}

3

এখানে সংক্ষিপ্ত স্কেলা সমাধান:

  def bfs(nodes: List[Node]): List[Node] = {
    if (nodes.nonEmpty) {
      nodes ++ bfs(nodes.flatMap(_.children))
    } else {
      List.empty
    }
  }

রিটার্ন ভ্যালু সংগ্রহকারী হিসাবে ব্যবহারের ধারণাটি উপযুক্ত suited অন্যান্য ভাষায় একইভাবে প্রয়োগ করা যেতে পারে, কেবল আপনার পুনরাবৃত্ত ফাংশন প্রক্রিয়াটি নিশ্চিত করুন নোডের তালিকা

টেস্ট কোড তালিকা (@ মার্কো টেস্ট ট্রি ব্যবহার করে):

import org.scalatest.FlatSpec

import scala.collection.mutable

class Node(val value: Int) {

  private val _children: mutable.ArrayBuffer[Node] = mutable.ArrayBuffer.empty

  def add(child: Node): Unit = _children += child

  def children = _children.toList

  override def toString: String = s"$value"
}

class BfsTestScala extends FlatSpec {

  //            1
  //          / | \
  //        2   3   4
  //      / |       | \
  //    5   6       7  8
  //  / |           | \
  // 9  10         11  12
  def tree(): Node = {
    val root = new Node(1)
    root.add(new Node(2))
    root.add(new Node(3))
    root.add(new Node(4))
    root.children(0).add(new Node(5))
    root.children(0).add(new Node(6))
    root.children(2).add(new Node(7))
    root.children(2).add(new Node(8))
    root.children(0).children(0).add(new Node(9))
    root.children(0).children(0).add(new Node(10))
    root.children(2).children(0).add(new Node(11))
    root.children(2).children(0).add(new Node(12))
    root
  }

  def bfs(nodes: List[Node]): List[Node] = {
    if (nodes.nonEmpty) {
      nodes ++ bfs(nodes.flatMap(_.children))
    } else {
      List.empty
    }
  }

  "BFS" should "work" in {
    println(bfs(List(tree())))
  }
}

আউটপুট:

List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)

2

এখানে একটি অজগর বাস্তবায়ন:

graph = {'A': ['B', 'C'],
         'B': ['C', 'D'],
         'C': ['D'],
         'D': ['C'],
         'E': ['F'],
         'F': ['C']}

def bfs(paths, goal):
    if not paths:
        raise StopIteration

    new_paths = []
    for path in paths:
        if path[-1] == goal:
            yield path

        last = path[-1]
        for neighbor in graph[last]:
            if neighbor not in path:
                new_paths.append(path + [neighbor])
    yield from bfs(new_paths, goal)


for path in bfs([['A']], 'D'):
    print(path)

2

এখানে পুনরাবৃত্ত বিএফএসের একটি স্কেল 2.11.4 প্রয়োগ রয়েছে। আমি ব্রিভিটির জন্য টেল-কল অপ্টিমাইজেশানকে ত্যাগ করেছি, তবে টিসিওডি সংস্করণটি খুব একই রকম। @ এসএনভি'র পোস্টটিও দেখুন ।

import scala.collection.immutable.Queue

object RecursiveBfs {
  def bfs[A](tree: Tree[A], target: A): Boolean = {
    bfs(Queue(tree), target)
  }

  private def bfs[A](forest: Queue[Tree[A]], target: A): Boolean = {
    forest.dequeueOption exists {
      case (E, tail) => bfs(tail, target)
      case (Node(value, _, _), _) if value == target => true
      case (Node(_, l, r), tail) => bfs(tail.enqueue(List(l, r)), target)
    }
  }

  sealed trait Tree[+A]
  case class Node[+A](data: A, left: Tree[A], right: Tree[A]) extends Tree[A]
  case object E extends Tree[Nothing]
}

2

নীচে আমার কাছে হাস্কেল ব্যবহার করে খুব স্বাভাবিক মনে হয়েছে। গাছের স্তরের উপরে পুনরাবৃত্তভাবে ইট্রেট করুন (এখানে আমি গাছের মধ্য দিয়ে রাস্তাটি দেখানোর জন্য একটি বড় অর্ডারযুক্ত স্ট্রিংয়ের মধ্যে নাম সংগ্রহ করি):

data Node = Node {name :: String, children :: [Node]}
aTree = Node "r" [Node "c1" [Node "gc1" [Node "ggc1" []], Node "gc2" []] , Node "c2" [Node "gc3" []], Node "c3" [] ]
breadthFirstOrder x = levelRecurser [x]
    where levelRecurser level = if length level == 0
                                then ""
                                else concat [name node ++ " " | node <- level] ++ levelRecurser (concat [children node | node <- level])

2

এখানে কোনও বিএফএস রিকার্সিভ ট্র্যাভারসাল পাইথন বাস্তবায়ন, কোনও চক্রবিহীন গ্রাফের জন্য কাজ করা।

def bfs_recursive(level):
    '''
     @params level: List<Node> containing the node for a specific level.
    '''
    next_level = []
    for node in level:
        print(node.value)
        for child_node in node.adjency_list:
            next_level.append(child_node)
    if len(next_level) != 0:
        bfs_recursive(next_level)


class Node:
    def __init__(self, value):
        self.value = value
        self.adjency_list = []

2

আমি আমার সেন্টসটিকে উপরের উত্তরে যুক্ত করতে চাই যে ভাষাটি যদি জেনারেটরের মতো কোনও কিছুকে সমর্থন করে তবে বিএফএস সহ-পুনরাবৃত্তভাবে করা যেতে পারে।

শুরু করার জন্য, @ তানজেল্যাক্সের উত্তরটি পড়ে:

প্রস্থের প্রথম ট্র্যাভারসাল traditionতিহ্যগতভাবে স্ট্যাক নয়, একটি সারি ব্যবহার করে। একটি সারি এবং স্ট্যাকের প্রকৃতি অনেকটা বিপরীত, তাই কল স্ট্যাক (যা একটি স্ট্যাক, তাই নাম) হিসাবে অ্যাসোসিলারি স্টোরেজ (একটি সারি) হিসাবে ব্যবহার করার চেষ্টা ব্যর্থতার পক্ষে প্রায় ডুবে গেছে

প্রকৃতপক্ষে, সাধারণ ফাংশন কলের স্ট্যাক একটি সাধারণ স্ট্যাকের মতো আচরণ করবে না। তবে জেনারেটর ফাংশনটি ফাংশনটির কার্য সম্পাদন স্থগিত করবে সুতরাং এটি নোডের গভীর বংশধরদের মধ্যে না গিয়েই নোডের বাচ্চাদের পরবর্তী স্তরের উত্পাদন করার সুযোগ দেয়।

নীচের কোডটি পাইথনে পুনরাবৃত্ত বিএফএস।

def bfs(root):
  yield root
  for n in bfs(root):
    for c in n.children:
      yield c

এখানে স্বজ্ঞাতটি হ'ল:

  1. বিএফএস প্রথমে প্রথম ফলাফল হিসাবে মূলটি ফেরত দেবে
  2. ধরুন আমাদের কাছে ইতিমধ্যে বিএফএস ক্রম রয়েছে, বিএফএসে উপাদানগুলির পরবর্তী স্তরটি হল ক্রমের পূর্ববর্তী নোডের তাত্ক্ষণিক শিশু
  3. উপরোক্ত দুটি পদ্ধতি পুনরাবৃত্তি করুন

আমি পাইথন জানি না তবে আমি মনে করি আপনার কোডটি এই সি # কোডে অনুবাদ করে । এটি বিএফএসের ট্র্যাভারসাল করে তবে স্ট্যাকওভারফ্লো ব্যতিক্রম সহ ক্র্যাশ করে। আমি এখনও পর্যন্ত কেন খুঁজে বের করতে পারেনি। যাইহোক, আমি অ্যালগরিদমটি পরিবর্তন করেছি যাতে এটি বন্ধ হয়ে যায় (এবং সম্ভবত আরও ভাল সম্পাদন করে)। আপনি আমার কাজের নমুনা এখানে পাবেন
অ্যাডাম সাইমন

1

আমাকে একটি হিপ ট্র্যাভারসাল বাস্তবায়ন করতে হয়েছিল যা বিএফএসের অর্ডারে আউটপুট দেয়। এটি আসলে বিএফএস নয় তবে একই কাজটি সম্পাদন করে।

private void getNodeValue(Node node, int index, int[] array) {
    array[index] = node.value;
    index = (index*2)+1;

    Node left = node.leftNode;
    if (left!=null) getNodeValue(left,index,array);
    Node right = node.rightNode;
    if (right!=null) getNodeValue(right,index+1,array);
}

public int[] getHeap() {
    int[] nodes = new int[size];
    getNodeValue(root,0,nodes);
    return nodes;
}

2
অন্যান্য দর্শকদের জন্য: এটি অ্যারেতে একটি সম্পূর্ণ গাছ বাস্তবায়নের উদাহরণ ; বিশেষত, @ জাস্টিন একটি প্রি-অর্ডার ট্র্যাভারসাল করছে, সেই সময়ে তিনি নোড মানগুলি সংরক্ষণ করে (বিএফএস ক্রমে) উপযুক্ত বিএফএস সূচকে একটি অ্যারেতে। এটি কলিং ফাংশনটি বিএফএস ক্রমে মুদ্রণের মানগুলিতে অ্যারের মধ্য দিয়ে রৈখিকভাবে পুনরাবৃত্তি করতে দেয়। এই সাধারণ বিবরণটি দেখুন দ্রষ্টব্য: কলিং ফাংশনটি অবশ্যই সম্পূর্ণ-সম্পূর্ণ গাছের ক্ষেত্রে পরিচালনা করবে।
বুঙ্কারদ্বীপ

1

চলুন শুরু করা যাক v

জি প্রশ্নে গ্রাফ হতে দিন

সারি ব্যবহার না করে নীচে সিউডো কোডটি দেওয়া হল

Initially label v as visited as you start from v
BFS(G,v)
    for all adjacent vertices w of v in G:
        if vertex w is not visited:
            label w as visited
    for all adjacent vertices w of v in G:
        recursively call BFS(G,w)

আমি মনে করি এটি একটি অসীম লুপে আটকে যেতে পারে - শীর্ষগুলি পরিদর্শন করা হিসাবে চিহ্নিত করা হচ্ছে, তবে পুনরাবৃত্তি করার আগে সেগুলি কখনও ভিজিট-নেসের জন্য পরীক্ষা করা হয় না।

এই স্নিপেট
বিএফএসের

1

বাইনারি (বা এন-অ্যারি) গাছের জন্য বিএফএস নীচে (জাভাতে এখানে) সারি ছাড়াই পুনরাবৃত্তভাবে করা যেতে পারে:

public class BreathFirst {

    static class Node {
        Node(int value) {
            this(value, 0);
        }
        Node(int value, int nChildren) {
            this.value = value;
            this.children = new Node[nChildren];
        }
        int value;
        Node[] children;
    }

    static void breathFirst(Node root, Consumer<? super Node> printer) {
        boolean keepGoing = true;
        for (int level = 0; keepGoing; level++) {
            keepGoing = breathFirst(root, printer, level);
        }
    }

    static boolean breathFirst(Node node, Consumer<? super Node> printer, int depth) {
        if (depth < 0 || node == null) return false;
        if (depth == 0) {
            printer.accept(node);
            return true;
        }
        boolean any = false;
        for (final Node child : node.children) {
            any |= breathFirst(child, printer, depth - 1);
        }
        return any;
    }
}

উত্সাহীন ক্রমে ট্র্যাভার্সাল প্রিন্টিংয়ের 1-2 উদাহরণ:

public static void main(String... args) {
    //            1
    //          / | \
    //        2   3   4
    //      / |       | \
    //    5   6       7  8
    //  / |           | \
    // 9  10         11  12

    Node root = new Node(1, 3);
    root.children[0] = new Node(2, 2);
    root.children[1] = new Node(3);
    root.children[2] = new Node(4, 2);
    root.children[0].children[0] = new Node(5, 2);
    root.children[0].children[1] = new Node(6);
    root.children[2].children[0] = new Node(7, 2);
    root.children[2].children[1] = new Node(8);
    root.children[0].children[0].children[0] = new Node(9);
    root.children[0].children[0].children[1] = new Node(10);
    root.children[2].children[0].children[0] = new Node(11);
    root.children[2].children[0].children[1] = new Node(12);

    breathFirst(root, n -> System.out.println(n.value));
}

0
#include <bits/stdc++.h>
using namespace std;
#define Max 1000

vector <int> adj[Max];
bool visited[Max];

void bfs_recursion_utils(queue<int>& Q) {
    while(!Q.empty()) {
        int u = Q.front();
        visited[u] = true;
        cout << u << endl;
        Q.pop();
        for(int i = 0; i < (int)adj[u].size(); ++i) {
            int v = adj[u][i];
            if(!visited[v])
                Q.push(v), visited[v] = true;
        }
        bfs_recursion_utils(Q);
    }
}

void bfs_recursion(int source, queue <int>& Q) {
    memset(visited, false, sizeof visited);
    Q.push(source);
    bfs_recursion_utils(Q);
}

int main(void) {
    queue <int> Q;
    adj[1].push_back(2);
    adj[1].push_back(3);
    adj[1].push_back(4);

    adj[2].push_back(5);
    adj[2].push_back(6);

    adj[3].push_back(7);

    bfs_recursion(1, Q);
    return 0;
}

0

এখানে একটি জাভাস্ক্রিপ্ট বাস্তবায়ন যা গভীরতা প্রথম পুনরাবৃত্তির সাথে প্রস্থের প্রথম ট্র্যাভারসালকে নকল করে। আমি ন্যাশ মানগুলি হ্যাশের ভিতরে একটি অ্যারের অভ্যন্তরে প্রতিটি গভীরতার সাথে সঞ্চয় করছি oring যদি একটি স্তর ইতিমধ্যে উপস্থিত থাকে (আমাদের একটি সংঘর্ষ রয়েছে), সুতরাং আমরা কেবলমাত্র সেই স্তরের অ্যারেতে ঠেলাঠেলি করি। আপনি একটি জাভাস্ক্রিপ্ট অবজেক্টের পরিবর্তে একটি অ্যারে ব্যবহার করতে পারেন যেহেতু আমাদের স্তরগুলি সংখ্যাযুক্ত এবং অ্যারে সূচক হিসাবে পরিবেশন করতে পারে। আপনি নোডগুলি, মানগুলি, কোনও লিঙ্কযুক্ত তালিকায় রূপান্তর করতে পারেন বা যা কিছু চান তা ফিরিয়ে দিতে পারেন। আমি কেবল সরলতার জন্য মানগুলি ফিরিয়ে দিচ্ছি।

BinarySearchTree.prototype.breadthFirstRec = function() {

    var levels = {};

    var traverse = function(current, depth) {
        if (!current) return null;
        if (!levels[depth]) levels[depth] = [current.value];
        else levels[depth].push(current.value);
        traverse(current.left, depth + 1);
        traverse(current.right, depth + 1);
    };

    traverse(this.root, 0);
    return levels;
};


var bst = new BinarySearchTree();
bst.add(20, 22, 8, 4, 12, 10, 14, 24);
console.log('Recursive Breadth First: ', bst.breadthFirstRec());
/*Recursive Breadth First:  
{ '0': [ 20 ],
  '1': [ 8, 22 ],
  '2': [ 4, 12, 24 ],
  '3': [ 10, 14 ] } */

এখানে পুনরাবৃত্তি পদ্ধতির ব্যবহার করে প্রকৃত প্রশস্ত ফার্স্ট ট্র্যাভারসালের একটি উদাহরণ।

BinarySearchTree.prototype.breadthFirst = function() {

    var result = '',
        queue = [],
        current = this.root;

    if (!current) return null;
    queue.push(current);

    while (current = queue.shift()) {
        result += current.value + ' ';
        current.left && queue.push(current.left);
        current.right && queue.push(current.right);
    }
    return result;
};

console.log('Breadth First: ', bst.breadthFirst());
//Breadth First:  20 8 22 4 12 24 10 14

0

লুপ এবং সারি ব্যবহার না করে একটি দ্বিদলিত গ্রাফের প্রস্থ-প্রথম-সন্ধানের সম্পূর্ণ পুনরাবৃত্তির প্রয়োগের জন্য আমার কোডটি নিম্নরূপ।

public class Graph { public int V; public LinkedList<Integer> adj[]; Graph(int v) { V = v; adj = new LinkedList[v]; for (int i=0; i<v; ++i) adj[i] = new LinkedList<>(); } void addEdge(int v,int w) { adj[v].add(w); adj[w].add(v); } public LinkedList<Integer> getAdjVerted(int vertex) { return adj[vertex]; } public String toString() { String s = ""; for (int i=0;i<adj.length;i++) { s = s +"\n"+i +"-->"+ adj[i] ; } return s; } } //BFS IMPLEMENTATION public static void recursiveBFS(Graph graph, int vertex,boolean visited[], boolean isAdjPrinted[]) { if (!visited[vertex]) { System.out.print(vertex +" "); visited[vertex] = true; } if(!isAdjPrinted[vertex]) { isAdjPrinted[vertex] = true; List<Integer> adjList = graph.getAdjVerted(vertex); printAdjecent(graph, adjList, visited, 0,isAdjPrinted); } } public static void recursiveBFS(Graph graph, List<Integer> vertexList, boolean visited[], int i, boolean isAdjPrinted[]) { if (i < vertexList.size()) { recursiveBFS(graph, vertexList.get(i), visited, isAdjPrinted); recursiveBFS(graph, vertexList, visited, i+1, isAdjPrinted); } } public static void printAdjecent(Graph graph, List<Integer> list, boolean visited[], int i, boolean isAdjPrinted[]) { if (i < list.size()) { if (!visited[list.get(i)]) { System.out.print(list.get(i)+" "); visited[list.get(i)] = true; } printAdjecent(graph, list, visited, i+1, isAdjPrinted); } else { recursiveBFS(graph, list, visited, 0, isAdjPrinted); } }


0

গ # বাইনারি গাছের জন্য পুনরাবৃত্ত প্রস্থের প্রথম অনুসন্ধান অ্যালগরিদমের সি # কার্যকরকরণ।

বাইনারি ট্রি ডেটা ভিজ্যুয়ালাইজেশন

IDictionary<string, string[]> graph = new Dictionary<string, string[]> {
    {"A", new [] {"B", "C"}},
    {"B", new [] {"D", "E"}},
    {"C", new [] {"F", "G"}},
    {"E", new [] {"H"}}
};

void Main()
{
    var pathFound = BreadthFirstSearch("A", "H", new string[0]);
    Console.WriteLine(pathFound); // [A, B, E, H]

    var pathNotFound = BreadthFirstSearch("A", "Z", new string[0]);
    Console.WriteLine(pathNotFound); // []
}

IEnumerable<string> BreadthFirstSearch(string start, string end, IEnumerable<string> path)
{
    if (start == end)
    {
        return path.Concat(new[] { end });
    }

    if (!graph.ContainsKey(start)) { return new string[0]; }    

    return graph[start].SelectMany(letter => BreadthFirstSearch(letter, end, path.Concat(new[] { start })));
}

আপনি যদি অ্যালগরিদমটি কেবল বাইনারি-ট্রি দ্বারা নয় বরং গ্রাফগুলি নিয়ে কাজ করতে চান তবে এমন দুটি এবং আরও বেশি নোড থাকতে পারে যা ইতিমধ্যে পরিদর্শন করা নোডের তালিকা ধরে স্ব-সাইক্লিং এড়াতে হবে। বাস্তবায়ন দেখতে এইরকম হতে পারে।

গ্রাফ ডেটা ভিজ্যুয়ালাইজেশন

IDictionary<string, string[]> graph = new Dictionary<string, string[]> {
    {"A", new [] {"B", "C"}},
    {"B", new [] {"D", "E"}},
    {"C", new [] {"F", "G", "E"}},
    {"E", new [] {"H"}}
};

void Main()
{
    var pathFound = BreadthFirstSearch("A", "H", new string[0], new List<string>());
    Console.WriteLine(pathFound); // [A, B, E, H]

    var pathNotFound = BreadthFirstSearch("A", "Z", new string[0], new List<string>());
    Console.WriteLine(pathNotFound); // []
}

IEnumerable<string> BreadthFirstSearch(string start, string end, IEnumerable<string> path, IList<string> visited)
{
    if (start == end)
    {
        return path.Concat(new[] { end });
    }

    if (!graph.ContainsKey(start)) { return new string[0]; }


    return graph[start].Aggregate(new string[0], (acc, letter) =>
    {
        if (visited.Contains(letter))
        {
            return acc;
        }

        visited.Add(letter);

        var result = BreadthFirstSearch(letter, end, path.Concat(new[] { start }), visited);
        return acc.Concat(result).ToArray();
    });
}

0

আমি সি ++ ব্যবহার করে একটি প্রোগ্রাম তৈরি করেছি যা যৌথভাবে কাজ করছে এবং গ্রাফটিও বিচ্ছিন্ন করে।

    #include <queue>
#include "iostream"
#include "vector"
#include "queue"

using namespace std;

struct Edge {
    int source,destination;
};

class Graph{
    int V;
    vector<vector<int>> adjList;
public:

    Graph(vector<Edge> edges,int V){
        this->V = V;
        adjList.resize(V);
        for(auto i : edges){
            adjList[i.source].push_back(i.destination);
            //     adjList[i.destination].push_back(i.source);
        }
    }
    void BFSRecursivelyJoinandDisjointtGraphUtil(vector<bool> &discovered, queue<int> &q);
    void BFSRecursivelyJointandDisjointGraph(int s);
    void printGraph();


};

void Graph :: printGraph()
{
    for (int i = 0; i < this->adjList.size(); i++)
    {
        cout << i << " -- ";
        for (int v : this->adjList[i])
            cout <<"->"<< v << " ";
        cout << endl;
    }
}


void Graph ::BFSRecursivelyJoinandDisjointtGraphUtil(vector<bool> &discovered, queue<int> &q) {
    if (q.empty())
        return;
    int v = q.front();
    q.pop();
    cout << v <<" ";
    for (int u : this->adjList[v])
    {
        if (!discovered[u])
        {
            discovered[u] = true;
            q.push(u);
        }
    }
    BFSRecursivelyJoinandDisjointtGraphUtil(discovered, q);

}

void Graph ::BFSRecursivelyJointandDisjointGraph(int s) {
    vector<bool> discovered(V, false);
    queue<int> q;

    for (int i = s; i < V; i++) {
        if (discovered[i] == false)
        {
            discovered[i] = true;
            q.push(i);
            BFSRecursivelyJoinandDisjointtGraphUtil(discovered, q);
        }
    }
}

int main()
{

    vector<Edge> edges =
            {
                    {0, 1}, {0, 2}, {1, 2}, {2, 0}, {2,3},{3,3}
            };

    int V = 4;
    Graph graph(edges, V);
 //   graph.printGraph();
    graph.BFSRecursivelyJointandDisjointGraph(2);
    cout << "\n";




    edges = {
            {0,4},{1,2},{1,3},{1,4},{2,3},{3,4}
    };

    Graph graph2(edges,5);

    graph2.BFSRecursivelyJointandDisjointGraph(0);
    return 0;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.