Diyelim ki, bir ikili ağacın enine aramasını yinelemeli olarak gerçekleştirmek istediğinizi varsayalım . Nasıl devam edersin?
Yedek depolama olarak yalnızca çağrı yığınını kullanmak mümkün mü?
Diyelim ki, bir ikili ağacın enine aramasını yinelemeli olarak gerçekleştirmek istediğinizi varsayalım . Nasıl devam edersin?
Yedek depolama olarak yalnızca çağrı yığınını kullanmak mümkün mü?
Yanıtlar:
(Bunun sadece bir tür düşünce alıştırması, hatta aldatıcı bir ev ödevi / mülakat sorusu olduğunu varsayıyorum, ancak sanırım herhangi bir nedenle yığın alanına izin verilmeyen tuhaf bir senaryo hayal edebiliyorum [gerçekten kötü bir gelenek bellek yöneticisi? bazı tuhaf çalışma zamanı / işletim sistemi sorunları?] hala yığına erişiminiz varken ...)
Enine geçiş geleneksel olarak bir yığın değil bir kuyruk kullanır. Bir kuyruğun ve bir yığının doğası hemen hemen zıttır, bu nedenle çağrı yığınını (bir yığın, dolayısıyla adıdır) yardımcı depolama (bir kuyruk) olarak kullanmaya çalışmak, yapmadığınız sürece başarısızlığa mahkumdur. olmaman gereken çağrı yığınıyla ilgili aptalca saçma bir şey.
Aynı belirteçte, uygulamaya çalıştığınız herhangi bir kuyruk olmayan özyinelemenin doğası, aslında algoritmaya bir yığın eklemektir. Bu, artık bir ikili ağaçta enine ilk aramayı yapmamasını sağlar ve bu nedenle, geleneksel BFS için çalışma zamanı ve hiçbir şey artık tamamen geçerli değildir. Tabii ki, herhangi bir döngüyü her zaman önemsiz bir şekilde özyinelemeli çağrıya dönüştürebilirsiniz, ancak bu herhangi bir anlamlı özyineleme değildir.
Bununla birlikte, başkalarının da gösterdiği gibi, BFS'nin anlambilimini bir miktar maliyetle izleyen bir şeyi uygulamanın yolları vardır. Karşılaştırma maliyeti pahalıysa ancak düğüm geçişi ucuzsa , @ Simon Buchan'ın yaptığı gibi , yalnızca yaprakları işleyerek derinlemesine yinelemeli bir arama çalıştırabilirsiniz. Bu, yığında saklanan büyüyen bir kuyruk olmadığı anlamına gelir, yalnızca yerel bir derinlik değişkeni ve ağaç defalarca dolaşırken çağrı yığını üzerinde yığınlar tekrar tekrar oluşturulur. Ve @Patrick'in belirttiği gibi, bir dizi tarafından desteklenen bir ikili ağaç, yine de genellikle genişlik-ilk geçiş sırasına göre depolanır, bu nedenle, bunun üzerinde bir yardımcı kuyruğa ihtiyaç duymadan kapsamlı bir ilk arama önemsiz olacaktır.
İkili ağacı desteklemek için bir dizi kullanırsanız, bir sonraki düğümü cebirsel olarak belirleyebilirsiniz. i
bir düğüm ise , alt öğeleri 2i + 1
(sol düğüm için) ve 2i + 2
(sağ düğüm için) bulunabilir. Bir düğümün sonraki komşusu, gücü i + 1
olmadığı sürece tarafından verilir i
.2
Burada, dizi destekli ikili arama ağacında genişlik ilk aramanın çok naif bir uygulaması için sözde kod var. Bu, sabit boyutlu bir dizi ve dolayısıyla sabit bir derinlik ağacı varsayar. Ebeveyn olmayan düğümlere bakacak ve yönetilemeyecek kadar büyük bir yığın oluşturabilir.
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)
Tamamen özyinelemeli yapmanın bir yolunu bulamadım (herhangi bir yardımcı veri yapısı olmadan). Ancak, Q kuyruğu referans olarak geçerse, aşağıdaki aptalca kuyruk özyinelemeli işlevine sahip olabilirsiniz:
BFS(Q)
{
if (|Q| > 0)
v <- Dequeue(Q)
Traverse(v)
foreach w in children(v)
Enqueue(Q, w)
BFS(Q)
}
Aşağıdaki yöntem, belirli bir derinlikteki tüm düğümleri almak için bir DFS algoritması kullanmıştır - bu, o seviye için BFS yapmakla aynıdır. Ağacın derinliğini bulursanız ve bunu tüm seviyeler için yaparsanız, sonuçlar BFS ile aynı olacaktır.
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);
}
Bir ağacın derinliğini bulmak çocuk oyuncağı:
public int MaxDepth(Tree root) {
if (root == null) {
return 0;
} else {
return Math.Max(MaxDepth(root.Left), MaxDepth(root.Right)) + 1;
}
}
level
sıfır olana kadar dönmez .
Java'da basit bir BFS ve DFS özyinelemesi:
Yığın / kuyruktaki ağacın kök düğümünü itin / sunun ve bu işlevleri çağırın.
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);
}
Çok güzel özyinelemeli (hatta işlevsel) Genişlik-İlk geçişle ilgili algoritma buldum. Benim fikrim değil ama bence bu konuya değinilmesi gerekiyor.
Chris Okasaki, ICFP 2000'den gelen ilk numaralandırma algoritmasını http://okasaki.blogspot.de/2008/07/breadth-first-numbering-algorithm-in.html adresinde yalnızca 3 resimle çok net bir şekilde açıklıyor .
Http://debasishg.blogspot.de/2008/09/breadth-first-numbering-okasakis.html adresinde bulduğum Debasish Ghosh'un Scala uygulaması :
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
}
Aptalca yol:
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;
}
İşte kısa Scala çözümü:
def bfs(nodes: List[Node]): List[Node] = {
if (nodes.nonEmpty) {
nodes ++ bfs(nodes.flatMap(_.children))
} else {
List.empty
}
}
Geri dönüş değerini biriktirici olarak kullanma fikri çok uygundur. Diğer dillerde de benzer şekilde uygulanabilir, sadece özyinelemeli işlev sürecinizin düğüm listesinin olduğundan emin olun .
Test kodu listesi (@marco test ağacını kullanarak):
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())))
}
}
Çıktı:
List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
İşte bir python uygulaması:
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)
İşte yinelemeli BFS'nin bir Scala 2.11.4 uygulaması. Kısalık için kuyruk arama optimizasyonunu feda ettim, ancak TCOd sürümü çok benzer. Ayrıca @snv'nin gönderisine bakın .
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]
}
Aşağıdakiler Haskell kullanarak bana oldukça doğal görünüyor. Ağacın seviyeleri üzerinde yinelemeli olarak yineleyin (burada ağaçtaki yolu göstermek için adları büyük sıralı bir dizede topluyorum):
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])
İşte döngü içermeyen bir grafik için çalışan bir BFS yinelemeli geçiş Python uygulaması.
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 = []
Kuruşlarımı eklemek istiyorum üst yanıta , eğer dil jeneratör gibi bir şeyi destekliyorsa, bfs eş-özyinelemeli olarak yapılabilir.
Başlangıç olarak @ Tanzelax'ın cevabı şu şekildedir:
Enine geçiş geleneksel olarak bir yığın değil bir kuyruk kullanır. Bir kuyruğun ve bir yığının doğası hemen hemen zıttır, bu nedenle çağrı yığınını (bir yığın, dolayısıyla adıdır) yardımcı depolama (bir kuyruk) olarak kullanmaya çalışmak hemen hemen başarısızlığa mahkumdur.
Aslında, sıradan işlev çağrısının yığını, normal bir yığın gibi davranmaz. Ancak jeneratör işlevi, işlevin yürütülmesini askıya alır, bu nedenle bize düğümün daha derin torunlarına girmeden bir sonraki düğüm çocuklarını verme şansı verir.
Aşağıdaki kod Python'da özyinelemeli bfs'dir.
def bfs(root):
yield root
for n in bfs(root):
for c in n.children:
yield c
Buradaki sezgi şudur:
BFS siparişinde çıktı veren bir yığın geçişi uygulamak zorunda kaldım. Aslında BFS değildir, ancak aynı görevi yerine getirir.
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;
}
V başlangıç noktası olsun
G söz konusu grafik olsun
Sırayı kullanmadan sözde kod aşağıdadır
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)
Bir ikili (veya n-ary) ağaç için BFS, aşağıdaki gibi sıralar olmadan özyinelemeli olarak yapılabilir (burada Java'da):
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;
}
}
Artan sırada 1-12 numaralı bir çapraz baskı numarası örneği:
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));
}
#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;
}
Burada, Önce Derinlik özyinelemeli İlk Genişlik Geçişini taklit eden bir JavaScript Uygulaması var. Düğüm değerlerini bir karmanın içinde bir dizi içinde her derinlikte depoluyorum. Bir seviye zaten mevcutsa (bir çarpışmamız varsa), bu yüzden sadece o seviyedeki diziyi itiyoruz. Seviyelerimiz sayısal olduğundan ve dizi indeksleri olarak hizmet edebildiğinden, JavaScript nesnesi yerine bir dizi de kullanabilirsiniz. Düğümleri, değerleri döndürebilir, Bağlantılı Listeye dönüştürebilir veya istediğiniz her şeyi yapabilirsiniz. Basitlik uğruna değerleri döndürüyorum.
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 ] } */
Yinelemeli bir yaklaşım kullanan gerçek İlk Genişlik Geçişinin bir örneğini burada bulabilirsiniz.
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
Aşağıda, döngü ve kuyruk kullanmadan çift yönlü bir grafiğin enine ilk aramasının tamamen yinelemeli uygulaması için kodum yer almaktadır.
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);
}
}
Bir ikili ağaç için özyinelemeli genişlik ilk arama algoritmasının C # uygulaması.
İkili ağaç veri görselleştirme
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 })));
}
Algoritmanın yalnızca ikili ağaçla değil, aynı başka düğüme işaret eden iki veya daha fazla düğüme sahip olabilecek grafiklerle çalışmasını istiyorsanız, önceden ziyaret edilen düğümlerin listesini tutarak kendi kendine döngüyü önlemek zorundasınız. Uygulama şuna benziyor olabilir.
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();
});
}
C ++ kullanarak ortak ve ayrık grafikte de çalışan bir program yaptım.
#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;
}