#include <iostream>
#include "Graph.cpp"
#include "Stack.cpp"
#include "Queue.cpp"

using namespace std;

#ifndef GRAPHTRAVERSAL_CLASS_INCLUDED
#define GRAPHTRAVERSAL_CLASS_INCLUDED

/*
	Graph Traversal Class
	LastModification : 2008. 5. 5
	Version : 1.0.0
	myllyj(myllyj at myllyj dot com) / http://program.myllyj.com

	Requirements:
		require Graph class
		require Stack class
		require Queue class

	Comment:
		BFS¿Í DFS¸¦ ÇÒ ¶§ ¿©·¯°³ÀÇ Child°¡ ÀÖÀ»°æ¿ì, °í¸£´Â ¿ì¼± ¼øÀ§´Â
		±×Àú ¸ÕÀú edge¸¦ ¿¬°áÇÑ °ÍÀ¸·Î ÇÑ´Ù.
		Æ¯Á¤ ¿¬°áÀÌ ¾î¶² ´Ù¸¥ ¿¬°áº¸´Ù ¿ì¼±½Ã ÇÑ´Ù´Â °­ÇÑ ¿¬°á °°Àº
		±â´ÉÀº ¾ø´Ù.
		¹Ý´ë·Î ÀÌ¾ß±â ÇÏ¸é, °­ÇÑ ¿¬°áÀÌ¶ó¸é ±×º¸´Ù ¾àÇÑ ¿¬°á º¸´Ù
		¸ÕÀú ¿¬°á ÇÏ¸é µÈ´Ù.

*/

template <class T>
class GraphTraversal
{

private:
	Queue<T>* queue;
	Stack<T>* stack;
	LinkedList<T>* visited;

public:
	GraphTraversal();
	void DepthFirstSearch(Graph<T>* graph);
	void BreadthFirstSearch(Graph<T>* graph);
	void PrintVisited();

};

template <class T>
GraphTraversal<T>::GraphTraversal()
{
	queue = new Queue<T>();
	stack = new Stack<T>();
	visited = new LinkedList<T>();
}

// ÁöÁ¤ÇÑ ±×·¡ÇÁ¿¡ ´ëÇØ¼­ ±íÀÌ ¿ì¼± Å½»ö(DFS)¸¦ ½Ç½ÃÇÕ´Ï´Ù.
template <class T>
void GraphTraversal<T>::DepthFirstSearch(Graph<T>* graph)
{
	stack->Clear();
	visited->Clear();
	// Ã¹¹øÂ° ³ëµå ³Ö¾îÁÜ
	stack->Push(graph->GetFirstVertex());

	while(stack->Count() > 0)
	{
		bool flag = false;

		// ÀÛ¾÷ vertex »Ì°í
		T nowVertex = stack->Top();
		// ½ºÅÃ¿¡ ÀÖ´Â °Í Áß¿¡¼­ ÀÌ¹Ì ¹æ¹®ÇÑ °Íµµ ÀÖ´Âµ¥,
		// ¹æ¹®ÇÑ°Å ¶Ç Ãß°¡ ÇÏ¸é ¾ÈµÈ´Ù.
		if (!visited->Contains(nowVertex)) visited->AddLast(nowVertex);

		//child°¡ ÀÖ´ÂÁö °Ë»çÇÑ´Ù
		LinkedList<T>* tmpList = graph->GetVertics(nowVertex);
		tmpList->MoveFirst();
		tmpList->MoveNext();
		while(!tmpList->IsHeaderNode())
		{
			// ¹æ¹® ¾ÈÇÑ ³ëµå Áß ÇÏ³ª¸¸ Ã£¾Æ¼­ Ãß°¡ÇÏ°í
			// ±× ³ëµå¿¡ ´ëÇÑ Å½»ö ½ÃÀÛ.
			if (!visited->Contains(tmpList->Get()))
			{
				stack->Push(tmpList->Get());
				flag = true;
				break;
			}
			tmpList->MoveNext();
		}

		if (!flag) stack->Pop();
	}

	// visited ¿¡ ±â·ÏµÈ°Å ¼ø¼­´ë·Î ´Ù Áý¾î ²ô³½´Ù.
	this->PrintVisited();

}

// ÁöÁ¤ÇÑ ±×·¡ÇÁ¿¡ ´ëÇØ¼­ °ø°£ ¿ì¼± Å½»ö(BFS)¸¦ ½Ç½ÃÇÕ´Ï´Ù.
template <class T>
void GraphTraversal<T>::BreadthFirstSearch(Graph<T>* graph)
{
	queue->Clear();
	visited->Clear();
	// Ã¹¹øÂ° ³ëµå ³Ö¾îÁÜ
	queue->Enqueue(graph->GetFirstVertex());
	visited->AddLast(graph->GetFirstVertex());

	while(queue->Count() > 0)
	{
		T nowVertex = queue->Dequeue();

		//child°¡ ÀÖ´ÂÁö °Ë»çÇÑ´Ù
		LinkedList<T>* tmpList = graph->GetVertics(nowVertex);
		tmpList->MoveFirst();
		tmpList->MoveNext();
		while(!tmpList->IsHeaderNode())
		{
			if (!visited->Contains(tmpList->Get()))
			{
				queue->Enqueue(tmpList->Get());
				visited->AddLast(tmpList->Get());
			}
			tmpList->MoveNext();
		}

	}

	// visited ¿¡ ±â·ÏµÈ°Å ¼ø¼­´ë·Î ´Ù Áý¾î ²ô³½´Ù.
	this->PrintVisited();

}

// ±×·¡ÇÁ Å½»öÀÇ °á°ú¸¦ Ãâ·ÂÇÕ´Ï´Ù.
template <class T>
void GraphTraversal<T>::PrintVisited()
{
	visited->MoveFirst();
	while (!visited->IsHeaderNode())
	{
		cout << visited->Get() << " ";
		visited->MoveNext();
	}
}

#endif