অ-পুনরাবৃত্ত গভীরতা প্রথম অনুসন্ধান অ্যালগরিদম


173

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


1
@ বার্ট কায়ার্স সাধারণভাবে একটি গাছ, ট্যাগ দ্বারা বিচার করে।
বাইজিক্লোপ

13
গভীরতা প্রথম অনুসন্ধানটি একটি পুনরাবৃত্ত আলগোরিদিম। নীচের উত্তরগুলি পুনরাবৃত্তভাবে নোডগুলি অন্বেষণ করছে, তারা কেবল তাদের পুনরাবৃত্তি করতে সিস্টেমের কল স্ট্যাক ব্যবহার করছে না এবং পরিবর্তে একটি স্পষ্ট স্ট্যাক ব্যবহার করছে।
নুল সেট

8
@ নুল সেট নং, এটি কেবল একটি লুপ। আপনার সংজ্ঞা অনুসারে, প্রতিটি কম্পিউটার প্রোগ্রাম পুনরাবৃত্ত হয়। (যেটি, শব্দের একটি নির্দিষ্ট অর্থে তারা আছে।)
biziclop

1
@ নুল সেট: একটি গাছ হ'ল পুনরাবৃত্ত তথ্য কাঠামো।
গাম্বো

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

উত্তর:


313

DFS:

list nodes_to_visit = {root};
while( nodes_to_visit isn't empty ) {
  currentnode = nodes_to_visit.take_first();
  nodes_to_visit.prepend( currentnode.children );
  //do something
}

এই বি:

list nodes_to_visit = {root};
while( nodes_to_visit isn't empty ) {
  currentnode = nodes_to_visit.take_first();
  nodes_to_visit.append( currentnode.children );
  //do something
}

দুজনের প্রতিসাম্যতা বেশ দুর্দান্ত।

আপডেট: হিসাবে উল্লেখ করা হয়েছে, সরানো take_first()এবং তালিকার প্রথম উপাদানটি প্রদান করে।


11
অ-পুনরাবৃত্তভাবে সম্পন্ন করার সময় দু'জনের কত মিল রয়েছে তা লক্ষ করার জন্য +1 (যেমন তারা পুনরাবৃত্তি হওয়ার সময় একেবারে আলাদা তবে এখনও ...)
কর্সিকা ২৩:৪৯

3
এবং তারপরে প্রতিসামতায় যুক্ত করতে, আপনি যদি এর পরিবর্তে নূন্যতম অগ্রাধিকারের সারিটি সৃজন হিসাবে ব্যবহার করেন তবে আপনার কাছে একক উত্সের সংক্ষিপ্ততম পথ সন্ধানকারী রয়েছে।
মার্ক পিটার্স

10
বিটিডাব্লু, .first()ফাংশনটি তালিকা থেকে উপাদানটি সরিয়ে দেয়। shift()অনেক ভাষায় পছন্দ । pop()এছাড়াও কাজ করে এবং বাম থেকে ডান পরিবর্তে ডান থেকে বাম ক্রমে শিশু নোডগুলি প্রদান করে।
এরিয়েল

5
আইএমও, ডিএফএস আলগো কিছুটা ভুল। 3 টি একে অপরের সাথে সংযুক্ত সমস্ত উল্লম্ব কল্পনা করুন। অগ্রগতি হওয়া উচিত : gray(1st)->gray(2nd)->gray(3rd)->blacken(3rd)->blacken(2nd)->blacken(1st). কিন্তু আপনার কোড উৎপন্ন: gray(1st)->gray(2nd)->gray(3rd)->blacken(2nd)->blacken(3rd)->blacken(1st)
ব্যাটম্যান

3
@ এলার্নার আমি আপনার উদাহরণটি ভুল বুঝে উঠতে পারি তবে তারা যদি একে অপরের সাথে সংযুক্ত থাকে তবে তা আসলে গাছ নয়।
বিজিকলপ

40

আপনি এমন স্ট্যাক ব্যবহার করবেন যা নোডগুলি ধারণ করে যা এখনও দেখা হয়নি:

stack.push(root)
while !stack.isEmpty() do
    node = stack.pop()
    for each node.childNodes do
        stack.push(stack)
    endfor
    // …
endwhile

2
@ গম্বো আমি ভাবছি যে এটি যদি সাইক্রিস সহ একটি গ্রাফ হয়। এই কাজ করতে পারেন? আমি মনে করি আমি কেবল স্ট্যাকের মধ্যে dulplicated নোড যুক্ত করা এড়াতে পারি এবং এটি কাজ করতে পারে। আমি যা করব তা হ'ল নোডের সমস্ত প্রতিবেশী চিহ্নিত করা যা পপ আউট হয়ে গেছে এবং if (nodes are not marked)এটি স্ট্যাকের দিকে ঠেলাঠেলি করার জন্য অনুমোদনযোগ্য কিনা তা বিচার করার জন্য যুক্ত করুন। এটা কি কাজ করতে পারে?
অ্যালস্টন

1
@ স্টলম্যান আপনি যে নোডগুলি ইতিমধ্যে পরিদর্শন করেছেন তা মনে রাখতে পারেন। আপনি যদি এখনও কেবল সেই নোডগুলিতে যান যা আপনি এখনও যাননি তবে আপনি কোনও চক্র করবেন না।
গম্বো 25'14

@ গম্বো আপনি কী বলতে চাইছেন doing cycles? আমি মনে করি আমি কেবল ডিএফএসের আদেশ চাই। এটা ঠিক আছে কি না, ধন্যবাদ।
অ্যালস্টন

কেবল উল্লেখ করতে চেয়েছিলেন যে স্ট্যাক (LIFO) ব্যবহারের অর্থ গভীরতার প্রথম ট্র্যাভারসাল। আপনি যদি প্রস্থ-ফার্স্ট ব্যবহার করতে চান তবে পরিবর্তে একটি সারি (ফিফো) দিয়ে যান।
প্রতি লুন্ডবার্গ

3
এটি লক্ষণীয় যে সর্বাধিক জনপ্রিয় @ বিজিক্লপ উত্তর হিসাবে সমমানের কোডটি পেতে, আপনার চাইল্ড নোটগুলি বিপরীত ক্রমে ( for each node.childNodes.reverse() do stack.push(stack) endfor) চাপানো দরকার । এটিও সম্ভবত আপনি চান is এই ভিডিওটিতে এটির মতো কেন রয়েছে তা চমৎকার ব্যাখ্যা: youtube.com/watch?v=cZPXfl_tUkA শেষের জন্য
মারিউজ পাভেলস্কি

32

আপনার প্যারেন্ট নোডগুলিতে পয়েন্টার থাকলে আপনি অতিরিক্ত মেমরি ছাড়াই এটি করতে পারেন।

def dfs(root):
    node = root
    while True:
        visit(node)
        if node.first_child:
            node = node.first_child      # walk down
        else:
            while not node.next_sibling:
                if node is root:
                    return
                node = node.parent       # walk up ...
            node = node.next_sibling     # ... and right

মনে রাখবেন যে যদি চাইল্ড নোডগুলি ভাইবোন পয়েন্টারগুলির পরিবর্তে অ্যারে হিসাবে সংরক্ষণ করা হয় তবে পরবর্তী ভাইবোন হিসাবে এটি পাওয়া যাবে:

def next_sibling(node):
    try:
        i =    node.parent.child_nodes.index(node)
        return node.parent.child_nodes[i+1]
    except (IndexError, AttributeError):
        return None

এটি একটি ভাল সমাধান কারণ এটি কোনও তালিকা বা স্ট্যাকের অতিরিক্ত মেমরি বা হেরফের ব্যবহার করে না (পুনরাবৃত্তি এড়াতে কিছু ভাল কারণ)। তবে এটি কেবল তখনই সম্ভব যখন গাছের নোডগুলির পিতামাতার সাথে লিঙ্ক থাকে।
জোয়েটউইডেল

ধন্যবাদ. এই অ্যালগরিদম দুর্দান্ত। তবে এই সংস্করণে আপনি ভিজিট ফাংশনে নোডের স্মৃতি মুছতে পারবেন না। এই অ্যালগরিদম গাছটিকে "ফার্স্ট_চাইল্ড" পয়েন্টার ব্যবহার করে একক সংযুক্ত তালিকায় রূপান্তর করতে পারে। আপনি এর মধ্য দিয়ে চলতে পারেন এবং পুনরাবৃত্তি ছাড়াই নোডের স্মৃতি মুক্ত করতে পারেন।
পুচু

6
"আপনার যদি প্যারেন্ট নোডের পয়েন্টার থাকে তবে আপনি অতিরিক্ত মেমরি ছাড়াই এটি করতে পারেন": প্যারেন্ট নোডগুলিতে পয়েন্টার সংরক্ষণ করে কিছু "অতিরিক্ত মেমরি" ব্যবহার করা হয় ...
rptr

1
@ rptr87 যদি এটি পরিষ্কার না হয় তবে এই পয়েন্টারগুলি ছাড়া অতিরিক্ত মেমরি ছাড়াই।
অভিনব গৌনিয়াল

এটি আংশিক গাছগুলির জন্য ব্যর্থ হবে যেখানে নোড পরম মূল নয়, তবে সহজেই এটি ঠিক করা যায় while not node.next_sibling or node is root:
বাসেল শিশানী 14

5

আপনার নোডগুলি ট্র্যাক করতে একটি স্ট্যাক ব্যবহার করুন

Stack<Node> s;

s.prepend(tree.head);

while(!s.empty) {
    Node n = s.poll_front // gets first node

    // do something with q?

    for each child of n: s.prepend(child)

}

1
@ ডেভ ও। না, কারণ আপনি ইতিমধ্যে উপস্থিত সমস্ত কিছুর সামনে ভিজিট নোডের বাচ্চাদের পিছনে পিছনে চাপ দিন।
বিজিক্লোপ

আমি অবশ্যই পুশ_ব্যাকের শব্দার্থটির ভুল ব্যাখ্যা দিয়েছি
ডেভ ও।

@ ডেভ আপনার খুব ভাল পয়েন্ট আছে। আমি ভাবছিলাম এটি "বাকী সারিটি পিছনে চাপানো" নয় "পিছনে চাপুন"। আমি যথাযথভাবে সম্পাদনা করব।
কর্সিকা

আপনি যদি সামনে এগিয়ে যাচ্ছেন তবে এটি স্ট্যাক হওয়া উচিত।
ফ্লাইট

@ টিমি হ্যাঁ আমি নিশ্চিত না আমি সেখানে কী ভাবছিলাম। @ ক্যোসিভারসি আমরা সাধারণত একটি সারিবদ্ধভাবে ফিফোর সারি হিসাবে মনে করি। একটি স্ট্যাক একটি LIFO সারি হিসাবে সংজ্ঞায়িত করা হয়।
কর্সিকা

4

যদিও "স্ট্যাক ব্যবহার করুন" এটি সাক্ষাত্কারের স্বতন্ত্র প্রশ্নের উত্তর হিসাবে কাজ করতে পারে , বাস্তবে, এটি কেবল স্পষ্ট করে বলছে যে পুনরাবৃত্তির প্রোগ্রামগুলি পর্দার আড়ালে কী করে।

পুনরাবৃত্তি বিল্ট-ইন স্ট্যাকগুলি ব্যবহার করে। আপনি যখন কোনও ফাংশন কল করেন, এটি ফাংশনে আর্গুমেন্টগুলি স্ট্যাকের দিকে ঠেলে দেয় এবং যখন ফাংশনটি ফিরে আসে তখন প্রোগ্রাম স্ট্যাকটি পপিং করে does


7
থ্রেড স্ট্যাকটি মারাত্মকভাবে সীমাবদ্ধ এমন গুরুত্বপূর্ণ পার্থক্যের সাথে এবং অ-পুনরাবৃত্ত অ্যালগরিদম আরও বেশি স্কেলযোগ্য alaੇਰ ব্যবহার করবে।
ইয়াম মার্কোভিচ

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

4

বিজিকলপসের দুর্দান্ত উত্তরের উপর ভিত্তি করে একটি ES6 বাস্তবায়ন:

root = {
  text: "root",
  children: [{
    text: "c1",
    children: [{
      text: "c11"
    }, {
      text: "c12"
    }]
  }, {
    text: "c2",
    children: [{
      text: "c21"
    }, {
      text: "c22"
    }]
  }, ]
}

console.log("DFS:")
DFS(root, node => node.children, node => console.log(node.text));

console.log("BFS:")
BFS(root, node => node.children, node => console.log(node.text));

function BFS(root, getChildren, visit) {
  let nodesToVisit = [root];
  while (nodesToVisit.length > 0) {
    const currentNode = nodesToVisit.shift();
    nodesToVisit = [
      ...nodesToVisit,
      ...(getChildren(currentNode) || []),
    ];
    visit(currentNode);
  }
}

function DFS(root, getChildren, visit) {
  let nodesToVisit = [root];
  while (nodesToVisit.length > 0) {
    const currentNode = nodesToVisit.shift();
    nodesToVisit = [
      ...(getChildren(currentNode) || []),
      ...nodesToVisit,
    ];
    visit(currentNode);
  }
}


3
PreOrderTraversal is same as DFS in binary tree. You can do the same recursion 
taking care of Stack as below.

    public void IterativePreOrder(Tree root)
            {
                if (root == null)
                    return;
                Stack s<Tree> = new Stack<Tree>();
                s.Push(root);
                while (s.Count != 0)
                {
                    Tree b = s.Pop();
                    Console.Write(b.Data + " ");
                    if (b.Right != null)
                        s.Push(b.Right);
                    if (b.Left != null)
                        s.Push(b.Left);

                }
            }

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


2

ES6 জেনারেটর ব্যবহার করে নন-রিকার্সিভ ডিএফএস

class Node {
  constructor(name, childNodes) {
    this.name = name;
    this.childNodes = childNodes;
    this.visited = false;
  }
}

function *dfs(s) {
  let stack = [];
  stack.push(s);
  stackLoop: while (stack.length) {
    let u = stack[stack.length - 1]; // peek
    if (!u.visited) {
      u.visited = true; // grey - visited
      yield u;
    }

    for (let v of u.childNodes) {
      if (!v.visited) {
        stack.push(v);
        continue stackLoop;
      }
    }

    stack.pop(); // black - all reachable descendants were processed 
  }    
}

প্রদত্ত নোডের সমস্ত পৌঁছনযোগ্য বংশধর যখন প্রক্রিয়াভুক্ত হয়েছিল এবং তালিকা / স্ট্যাকের বর্তমান পথ বজায় রাখতে এটি সহজে সনাক্ত করতে এটি সাধারণ অ-পুনরাবৃত্ত ডিএফএস থেকে বিচ্যুত হয় ।


1

মনে করুন গ্রাফের প্রতিটি নোড পরিদর্শন করা হলে আপনি কোনও বিজ্ঞপ্তি কার্যকর করতে চান। সহজ পুনরাবৃত্তি বাস্তবায়ন হ'ল:

void DFSRecursive(Node n, Set<Node> visited) {
  visited.add(n);
  for (Node x : neighbors_of(n)) {  // iterate over all neighbors
    if (!visited.contains(x)) {
      DFSRecursive(x, visited);
    }
  }
  OnVisit(n);  // callback to say node is finally visited, after all its non-visited neighbors
}

ঠিক আছে, এখন আপনি স্ট্যাক-ভিত্তিক বাস্তবায়ন চান কারণ আপনার উদাহরণটি কাজ করে না। জটিল গ্রাফগুলির উদাহরণস্বরূপ এটি আপনার প্রোগ্রামের স্ট্যাককে ফুঁ দিয়ে উঠতে পারে এবং আপনাকে একটি পুনরাবৃত্ত সংস্করণ প্রয়োগ করতে হবে। সবচেয়ে বড় বিষয়টি হ'ল নোটিফিকেশন কখন জারি করতে হবে তা জানা।

নিম্নলিখিত সিউডো কোড কাজ করে (পঠনযোগ্যতার জন্য জাভা এবং সি ++ এর মিশ্রণ):

void DFS(Node root) {
  Set<Node> visited;
  Set<Node> toNotify;  // nodes we want to notify

  Stack<Node> stack;
  stack.add(root);
  toNotify.add(root);  // we won't pop nodes from this until DFS is done
  while (!stack.empty()) {
    Node current = stack.pop();
    visited.add(current);
    for (Node x : neighbors_of(current)) {
      if (!visited.contains(x)) {
        stack.add(x);
        toNotify.add(x);
      }
    }
  }
  // Now issue notifications. toNotifyStack might contain duplicates (will never
  // happen in a tree but easily happens in a graph)
  Set<Node> notified;
  while (!toNotify.empty()) {
  Node n = toNotify.pop();
  if (!toNotify.contains(n)) {
    OnVisit(n);  // issue callback
    toNotify.add(n);
  }
}

এটি জটিল দেখায় তবে বিজ্ঞপ্তিগুলি জারি করার জন্য অতিরিক্ত যুক্তি উপস্থিত রয়েছে কারণ আপনাকে ভিজিটের বিপরীত ক্রমে অবহিত করতে হবে - ডিএফএস মূল থেকে শুরু হয় তবে এটি শেষের দিকে অবহিত করে, এটি বাস্তবায়নের পক্ষে খুব সহজ।

কিকের জন্য, নিম্নলিখিত গ্রাফটি ব্যবহার করে দেখুন: নোডগুলি হ'ল এস, টি, ভি এবং ডাব্লু। নির্দেশিত প্রান্তগুলি হ'ল: s-> t, s-> v, t-> w, v-> w, এবং v-> t। আপনার নিজের ডিএফএসের বাস্তবায়ন চালান এবং নোডগুলি যে ক্রমে পরিদর্শন করা উচিত সেগুলি অবশ্যই হওয়া উচিত: ডাব্লু, টি, ভি, এস ডিএফএসের একটি আনাড়ি বাস্তবায়ন সম্ভবত প্রথমে টিটি অবহিত করবে এবং এটি একটি বাগ নির্দেশ করে indicates ডিএফএসের একটি পুনরাবৃত্তিমূলক বাস্তবায়ন সর্বদা সর্বশেষে শেষের দিকে পৌঁছায়।


1

স্ট্যাক ছাড়াই ওয়ার্কিং কোডের সম্পূর্ণ উদাহরণ:

import java.util.*;

class Graph {
private List<List<Integer>> adj;

Graph(int numOfVertices) {
    this.adj = new ArrayList<>();
    for (int i = 0; i < numOfVertices; ++i)
        adj.add(i, new ArrayList<>());
}

void addEdge(int v, int w) {
    adj.get(v).add(w); // Add w to v's list.
}

void DFS(int v) {
    int nodesToVisitIndex = 0;
    List<Integer> nodesToVisit = new ArrayList<>();
    nodesToVisit.add(v);
    while (nodesToVisitIndex < nodesToVisit.size()) {
        Integer nextChild= nodesToVisit.get(nodesToVisitIndex++);// get the node and mark it as visited node by inc the index over the element.
        for (Integer s : adj.get(nextChild)) {
            if (!nodesToVisit.contains(s)) {
                nodesToVisit.add(nodesToVisitIndex, s);// add the node to the HEAD of the unvisited nodes list.
            }
        }
        System.out.println(nextChild);
    }
}

void BFS(int v) {
    int nodesToVisitIndex = 0;
    List<Integer> nodesToVisit = new ArrayList<>();
    nodesToVisit.add(v);
    while (nodesToVisitIndex < nodesToVisit.size()) {
        Integer nextChild= nodesToVisit.get(nodesToVisitIndex++);// get the node and mark it as visited node by inc the index over the element.
        for (Integer s : adj.get(nextChild)) {
            if (!nodesToVisit.contains(s)) {
                nodesToVisit.add(s);// add the node to the END of the unvisited node list.
            }
        }
        System.out.println(nextChild);
    }
}

public static void main(String args[]) {
    Graph g = new Graph(5);

    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 2);
    g.addEdge(2, 0);
    g.addEdge(2, 3);
    g.addEdge(3, 3);
    g.addEdge(3, 1);
    g.addEdge(3, 4);

    System.out.println("Breadth First Traversal- starting from vertex 2:");
    g.BFS(2);
    System.out.println("Depth First Traversal- starting from vertex 2:");
    g.DFS(2);
}}

আউটপুট: প্রস্থ প্রথম ট্র্যাভারসাল- শীর্ষস্থান 2: 2 0 3 1 4 গভীরতা প্রথম ট্র্যাভারসাল- প্রান্ত 2: 2 3 4 1 0 থেকে শুরু


0

আপনি একটি স্ট্যাক ব্যবহার করতে পারেন। আমি অ্যাডজেসেন্সি ম্যাট্রিক্স সহ গ্রাফগুলি প্রয়োগ করেছি:

void DFS(int current){
    for(int i=1; i<N; i++) visit_table[i]=false;
    myStack.push(current);
    cout << current << "  ";
    while(!myStack.empty()){
        current = myStack.top();
        for(int i=0; i<N; i++){
            if(AdjMatrix[current][i] == 1){
                if(visit_table[i] == false){ 
                    myStack.push(i);
                    visit_table[i] = true;
                    cout << i << "  ";
                }
                break;
            }
            else if(!myStack.empty())
                myStack.pop();
        }
    }
}

0

জাভাতে ডিএফএস পুনরাবৃত্তি:

//DFS: Iterative
private Boolean DFSIterative(Node root, int target) {
    if (root == null)
        return false;
    Stack<Node> _stack = new Stack<Node>();
    _stack.push(root);
    while (_stack.size() > 0) {
        Node temp = _stack.peek();
        if (temp.data == target)
            return true;
        if (temp.left != null)
            _stack.push(temp.left);
        else if (temp.right != null)
            _stack.push(temp.right);
        else
            _stack.pop();
    }
    return false;
}

প্রশ্ন স্পষ্টভাবে একটি বাইনারি গাছের
user3743222

অসীম লুপ এড়াতে আপনার একটি পরিদর্শন করা মানচিত্রের প্রয়োজন
স্পায়ারলমুন

0

http://www.youtube.com/watch?v=zLZhSSXAwxI

সবেমাত্র এই ভিডিওটি দেখেছেন এবং বাস্তবায়ন নিয়ে এসেছেন। এটা বুঝতে আমার পক্ষে সহজ মনে হচ্ছে। এটি সমালোচনা করুন।

visited_node={root}
stack.push(root)
while(!stack.empty){
  unvisited_node = get_unvisited_adj_nodes(stack.top());
  If (unvisited_node!=null){
     stack.push(unvisited_node);  
     visited_node+=unvisited_node;
  }
  else
     stack.pop()
}

0

ব্যবহার করে Stack, অনুসরণ করার পদক্ষেপগুলি এখানে: স্ট্যাকের উপর প্রথম ভার্টেক্সটি পুশ করুন,

  1. যদি সম্ভব হয় তবে একটি সংলগ্ন অপরিবর্তিত প্রান্তিক অঞ্চলটি দেখুন, এটি চিহ্নিত করুন এবং স্ট্যাকের উপরে চাপ দিন।
  2. আপনি যদি পদক্ষেপ 1 অনুসরণ করতে না পারেন, তবে, সম্ভব হলে, স্ট্যাকের বাইরে একটি শীর্ষবিন্দুটি পপ করুন।
  3. আপনি যদি পদক্ষেপ 1 বা দ্বিতীয় পদক্ষেপ অনুসরণ করতে না পারেন তবে আপনি সম্পন্ন করেছেন।

উপরের পদক্ষেপগুলি অনুসরণ করে এখানে জাভা প্রোগ্রামটি দেওয়া হল:

public void searchDepthFirst() {
    // begin at vertex 0
    vertexList[0].wasVisited = true;
    displayVertex(0);
    stack.push(0);
    while (!stack.isEmpty()) {
        int adjacentVertex = getAdjacentUnvisitedVertex(stack.peek());
        // if no such vertex
        if (adjacentVertex == -1) {
            stack.pop();
        } else {
            vertexList[adjacentVertex].wasVisited = true;
            // Do something
            stack.push(adjacentVertex);
        }
    }
    // stack is empty, so we're done, reset flags
    for (int j = 0; j < nVerts; j++)
            vertexList[j].wasVisited = false;
}

0
        Stack<Node> stack = new Stack<>();
        stack.add(root);
        while (!stack.isEmpty()) {
            Node node = stack.pop();
            System.out.print(node.getData() + " ");

            Node right = node.getRight();
            if (right != null) {
                stack.push(right);
            }

            Node left = node.getLeft();
            if (left != null) {
                stack.push(left);
            }
        }

0

@ বিজিক্লপের উত্তরের ভিত্তিতে সিউডো-কোড:

  • কেবলমাত্র মৌলিক কাঠামো ব্যবহার করে: ভেরিয়েবল, অ্যারে, যদি, যখন এবং এর জন্য
  • ফাংশন getNode(id)এবংgetChildren(id)
  • নোডের পরিচিত সংখ্যা ধরে নেওয়া N

দ্রষ্টব্য: আমি 0 থেকে নয়, 1 থেকে অ্যারে-ইনডেক্সিং ব্যবহার করি।

ধর্ষকের প্রথম

S = Array(N)
S[1] = 1; // root id
cur = 1;
last = 1
while cur <= last
    id = S[cur]
    node = getNode(id)
    children = getChildren(id)

    n = length(children)
    for i = 1..n
        S[ last+i ] = children[i]
    end
    last = last+n
    cur = cur+1

    visit(node)
end

গভীরতা প্রথম

S = Array(N)
S[1] = 1; // root id
cur = 1;
while cur > 0
    id = S[cur]
    node = getNode(id)
    children = getChildren(id)

    n = length(children)
    for i = 1..n
        // assuming children are given left-to-right
        S[ cur+i-1 ] = children[ n-i+1 ] 

        // otherwise
        // S[ cur+i-1 ] = children[i] 
    end
    cur = cur+n-1

    visit(node)
end

0

এখানে একটি জাভা উভয় reccursive এবং অ reccursive পদ্ধতি এবং এছাড়াও গণক নিম্নলিখিত DFS দেখাচ্ছে প্রোগ্রাম একটি লিঙ্ক আবিষ্কারের এবং ফিনিস সময়, কিন্তু কোন প্রান্ত laleling।

    public void DFSIterative() {
    Reset();
    Stack<Vertex> s = new Stack<>();
    for (Vertex v : vertices.values()) {
        if (!v.visited) {
            v.d = ++time;
            v.visited = true;
            s.push(v);
            while (!s.isEmpty()) {
                Vertex u = s.peek();
                s.pop();
                boolean bFinished = true;
                for (Vertex w : u.adj) {
                    if (!w.visited) {
                        w.visited = true;
                        w.d = ++time;
                        w.p = u;
                        s.push(w);
                        bFinished = false;
                        break;
                    }
                }
                if (bFinished) {
                    u.f = ++time;
                    if (u.p != null)
                        s.push(u.p);
                }
            }
        }
    }
}

এখানে সম্পূর্ণ উত্স ।


0

সলিউশনগুলির দীর্ঘ তালিকায় আমার অজগর বাস্তবায়নটি কেবল যুক্ত করতে চেয়েছিলেন। এই পুনরাবৃত্তিযোগ্য অ্যালগরিদমটির আবিষ্কার এবং সমাপ্ত ইভেন্ট রয়েছে।


worklist = [root_node]
visited = set()
while worklist:
    node = worklist[-1]
    if node in visited:
        # Node is finished
        worklist.pop()
    else:
        # Node is discovered
        visited.add(node)
        for child in node.children:
            worklist.append(child)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.