深度优先实现 一
深度优先算法
- 原料:class LinkStack<T>;
步骤:
- 将起始顶点压入栈中
- 弹出栈顶顶点 v, 判断是否已经标记(比较:转2; 未标记:转3)
- 标记顶点, 并将顶点 v 的邻接顶点压入栈中
- 判断栈是否为空(非空:转2; 空:结束)
深度优先算法示例
编程实验:深度优先算法
文件:Graph.h
#ifndef GRAPH_H
#define GRAPH_H
#include "Object.h"
#include "SharedPointer.h"
#include "DynamicArray.h"
#include "LinkQueue.h"
#include "LinkStack.h"
namespace DTLib
{
template <typename E>
struct Edge : public Object
{
int b;
int e;
E data;
Edge(int i=-1, int j=-1) : b(i), e(j)
{
}
Edge(int i, int j, const E &value) : b(i), e(j), data(value)
{
}
bool operator == (const Edge &obj)
{
return (b == obj.b) && (e == obj.e);
}
bool operator != (const Edge &obj)
{
return !(*this == obj);
}
};
template <typename V, typename E>
class Graph : public Object
{
public:
virtual V getVertex(int i) const = 0;
virtual bool getVertex(int i, V &value) const = 0;
virtual bool setVertex(int i, const V &value) = 0;
virtual SharedPointer<Array<int>> getAdjacent(int i) const = 0;
virtual E getEdge(int i, int j) const = 0;
virtual bool getEdge(int i, int j, E &value) const = 0;
virtual bool setEdge(int i, int j, const E &value) = 0;
virtual bool removeEdge(int i, int j) = 0;
virtual int vCount() const = 0;
virtual int eCount() = 0;
virtual int OD(int i) = 0;
virtual int ID(int i) = 0;
virtual int TD(int i)
{
return OD(i) + ID(i);
}
SharedPointer<Array<int>> BFS(int i)
{
DynamicArray<int> *ret = nullptr;
if ((0 <= i) && (i < vCount()))
{
LinkQueue<int> q;
LinkQueue<int> r;
DynamicArray<bool> visited(vCount());
for (int j=0; j<visited.length(); ++j)
{
visited[j] = false;
}
q.add(i);
while (q.length() > 0)
{
int v = q.front();
q.remove();
if (!visited[v])
{
SharedPointer<Array<int>> aj = getAdjacent(v);
for (int j=0; j<aj->length(); ++j)
{
q.add((*aj)[j]);
}
r.add(v);
visited[v] = true;
}
}
ret = toArray(r);
}
else
{
THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
}
return ret;
}
SharedPointer<Array<int>> DFS(int i)
{
DynamicArray<int> *ret = nullptr;
if ((0 <= i) && (i < vCount()))
{
LinkStack<int> s;
LinkQueue<int> r;
DynamicArray<bool> visited(vCount());
for (int j=0; j<visited.length(); ++j)
{
visited[j] = false;
}
s.push(i);
while (s.size() > 0)
{
int v = s.top();
s.pop();
if (!visited[v])
{
SharedPointer<Array<int>> aj = getAdjacent(v);
for (int j=aj->length()-1; j>=0; --j)
{
s.push((*aj)[j]);
}
r.add(v);
visited[v] = true;
}
}
ret = toArray(r);
}
else
{
THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
}
return ret;
}
protected:
template <typename T>
DynamicArray<T>* toArray(LinkQueue<T> &queue)
{
DynamicArray<T> *ret = new DynamicArray<T>(queue.length());
if (ret != nullptr)
{
for (int i=0; i<ret->length(); ++i, queue.remove())
{
ret->set(i, queue.front());
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create ret obj ...");
}
return ret;
}
};
}
#endif // GRAPH_H
文件:main.cpp
#include <iostream>
#include "MatrixGraph.h"
using namespace std;
using namespace DTLib;
int main()
{
MatrixGraph<9, char, int> g;
const char* VD = "ABEDCGFHI";
for(int i=0; i<9; i++)
{
g.setVertex(0, VD[i]);
}
g.setEdge(0, 1, 0);
g.setEdge(1, 0, 0);
g.setEdge(0, 3, 0);
g.setEdge(3, 0, 0);
g.setEdge(0, 4, 0);
g.setEdge(4, 0, 0);
g.setEdge(1, 2, 0);
g.setEdge(2, 1, 0);
g.setEdge(1, 4, 0);
g.setEdge(4, 1, 0);
g.setEdge(2, 5, 0);
g.setEdge(5, 2, 0);
g.setEdge(3, 6, 0);
g.setEdge(6, 3, 0);
g.setEdge(4, 6, 0);
g.setEdge(6, 4, 0);
g.setEdge(6, 7, 0);
g.setEdge(7, 6, 0);
g.setEdge(7, 8, 0);
g.setEdge(8, 7, 0);
SharedPointer<Array<int>> sa = g.DFS(0);
for (int i=0; i<sa->length(); ++i)
{
cout << (*sa)[i] << " ";
}
cout << endl;
return 0;
};
输出:
0 1 2 5 4 6 3 7 8
深度优先实现 二
问题: 如何使用二叉树先序遍历的思想遍历图?
递归深度优先
G = v0
+ G'
DFG(G) = visited(v0
) + DFS(G')
(G'不为空,且 v0
到 G' 有连接)
定义功能: DFS(graph, vex)
- 以顶点 vex 为起始顶点深度优先遍历 graph
编程实验:递归版深度优先算法
文件:main.cpp
#include <iostream>
#include "BTreeNode.h"
#include "ListGraph.h"
#include "MatrixGraph.h"
using namespace std;
using namespace DTLib;
template <typename V, typename E>
void DFP(Graph<V, E> &graph, int i, DynamicArray<bool> &visited)
{
if (!visited[i])
{
cout << i << " ";
visited[i] = true;
SharedPointer<Array<int>> aj = graph.getAdjacent(i);
for (int j=0; j<aj->length(); ++j)
{
DFP(graph, (*aj)[j], visited);
}
}
}
template <typename V, typename E>
void DFP(Graph<V, E> &graph, int i)
{
if ((0 <= i) && (i < graph.vCount()))
{
DynamicArray<bool> visited(graph.vCount());
for (int j=0; j<graph.vCount(); ++j)
{
visited[j] = false;
}
DFP(graph, i, visited);
cout << endl;
}
else
{
THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
}
}
int main()
{
MatrixGraph<9, char, int> g;
const char* VD = "ABEDCGFHI";
for(int i=0; i<9; i++)
{
g.setVertex(0, VD[i]);
}
g.setEdge(0, 1, 0);
g.setEdge(1, 0, 0);
g.setEdge(0, 3, 0);
g.setEdge(3, 0, 0);
g.setEdge(0, 4, 0);
g.setEdge(4, 0, 0);
g.setEdge(1, 2, 0);
g.setEdge(2, 1, 0);
g.setEdge(1, 4, 0);
g.setEdge(4, 1, 0);
g.setEdge(2, 5, 0);
g.setEdge(5, 2, 0);
g.setEdge(3, 6, 0);
g.setEdge(6, 3, 0);
g.setEdge(4, 6, 0);
g.setEdge(6, 4, 0);
g.setEdge(6, 7, 0);
g.setEdge(7, 6, 0);
g.setEdge(7, 8, 0);
g.setEdge(8, 7, 0);
SharedPointer< Array<int> > sa = g.DFS(0);
for(int i=0; i<sa->length(); i++)
{
cout << (*sa)[i] << " ";
}
cout << endl;
DFP(g, 0);
return 0;
}
输出:
0 1 2 5 4 6 3 7 8
0 1 2 5 4 6 3 7 8
小结
- 深度优先按照"先序遍历的方式"对顶点进行访问
- 深度优先算法的核心是栈的使用
- 深度优先和广度优先的唯一不同在于栈或队列的使用
- 深度优先算法可以使用递归的方式实现
以上内容整理于狄泰软件学院系列课程,请大家保护原创!
[添加递归版深度优先算法]文件:Grap.h
#ifndef GRAPH_H
#define GRAPH_H
#include "Object.h"
#include "SharedPointer.h"
#include "DynamicArray.h"
#include "LinkQueue.h"
#include "LinkStack.h"
namespace DTLib
{
template <typename E>
struct Edge : public Object
{
int b;
int e;
E data;
Edge(int i=-1, int j=-1) : b(i), e(j)
{
}
Edge(int i, int j, const E &value) : b(i), e(j), data(value)
{
}
bool operator == (const Edge &obj)
{
return (b == obj.b) && (e == obj.e);
}
bool operator != (const Edge &obj)
{
return !(*this == obj);
}
};
template <typename V, typename E>
class Graph : public Object
{
public:
virtual V getVertex(int i) const = 0;
virtual bool getVertex(int i, V &value) const = 0;
virtual bool setVertex(int i, const V &value) = 0;
virtual SharedPointer<Array<int>> getAdjacent(int i) const = 0;
virtual E getEdge(int i, int j) const = 0;
virtual bool getEdge(int i, int j, E &value) const = 0;
virtual bool setEdge(int i, int j, const E &value) = 0;
virtual bool removeEdge(int i, int j) = 0;
virtual int vCount() const = 0;
virtual int eCount() = 0;
virtual int OD(int i) = 0;
virtual int ID(int i) = 0;
virtual int TD(int i)
{
return OD(i) + ID(i);
}
SharedPointer<Array<int>> BFS(int i)
{
DynamicArray<int> *ret = nullptr;
if ((0 <= i) && (i < vCount()))
{
LinkQueue<int> q;
LinkQueue<int> r;
DynamicArray<bool> visited(vCount());
for (int j=0; j<visited.length(); ++j)
{
visited[j] = false;
}
q.add(i);
while (q.length() > 0)
{
int v = q.front();
q.remove();
if (!visited[v])
{
SharedPointer<Array<int>> aj = getAdjacent(v);
for (int j=0; j<aj->length(); ++j)
{
q.add((*aj)[j]);
}
r.add(v);
visited[v] = true;
}
}
ret = toArray(r);
}
else
{
THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
}
return ret;
}
#ifdef DFS_R
SharedPointer<Array<int>> DFS(int i) // 递归版深度优先遍历
{
DynamicArray<int> *ret = nullptr;
if ((0 <= i) && (i < vCount()))
{
LinkQueue<int> r;
DynamicArray<bool> visited(vCount());
for (int j=0; j<vCount(); ++j)
{
visited[j] = false;
}
DFP(i, visited, r);
ret = toArray(r);
}
else
{
THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
}
return ret;
}
#else
SharedPointer<Array<int>> DFS(int i)
{
DynamicArray<int> *ret = nullptr;
if ((0 <= i) && (i < vCount()))
{
LinkStack<int> s;
LinkQueue<int> r;
DynamicArray<bool> visited(vCount());
for (int j=0; j<visited.length(); ++j)
{
visited[j] = false;
}
s.push(i);
while (s.size() > 0)
{
int v = s.top();
s.pop();
if (!visited[v])
{
SharedPointer<Array<int>> aj = getAdjacent(v);
for (int j=aj->length()-1; j>=0; --j)
{
s.push((*aj)[j]);
}
r.add(v);
visited[v] = true;
}
}
ret = toArray(r);
}
else
{
THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
}
return ret;
}
#endif
protected:
template <typename T>
DynamicArray<T>* toArray(LinkQueue<T> &queue)
{
DynamicArray<T> *ret = new DynamicArray<T>(queue.length());
if (ret != nullptr)
{
for (int i=0; i<ret->length(); ++i, queue.remove())
{
ret->set(i, queue.front());
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create ret obj ...");
}
return ret;
}
#ifdef DFS_R
void DFP(int i, DynamicArray<bool> &visited, LinkQueue<int>& queue)
{
if (!visited[i])
{
queue.add(i);
visited[i] = true;
SharedPointer<Array<int>> aj = getAdjacent(i);
for (int j=0; j<aj->length(); ++j)
{
DFP((*aj)[j], visited, queue);
}
}
}
#endif
};
}
#endif // GRAPH_H
以上内容整理于狄泰软件学院系列课程,请大家保护原创!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。