图的数据结构

1.简介

图包括很多种类型,该文章仅介绍无向图与有向图

首先,我们必须有一个Bag数组来装下图

2.Bag的实现

由于仅展示

#include<vector>
class Bag
{
private:
	class Node
	{
	public:
		int val;
		Node* next;
		Node(int v, Node* x) :
			val(v), next(x) {}
	};
	Node* head;
public:
	Bag():head(nullptr){}
	~Bag()
	{
		while (head)
		{
			Node*temp = head;
			head = head->next;
			delete temp;
		}
	}
	void put(int val)
	{
		Node*temp = new Node(val, head);
		head = temp;
	}
	std::vector<int> Travel()
	{
		Node*temp = head;
		std::vector<int>result;
		while (temp)
		{
			result.push_back(temp->val);
			temp = temp->next;
		}
		return result;
	}
};

最简单的链表形式,不提供删除等操作

3.无向图

3.1 Graph类

无向图,顾名思义,没有方向,一条路径是双向的

class Graph
{
protected:  //成员设为保护成员方便继承使用
	int V;//顶点个数
	int E;//边的数目  
	Bag *adj;
public:
	Graph(int v);
	virtual ~Graph();
	int GetV() { return V; }
	int GetE() { return E; }
	virtual void AddEdge(int w, int v);
	std::vector<int> GetBagValve(int w);
};

3.2 其他方法的实现

Graph::Graph(int v)
{
	V = v;
	adj = new Bag[V]();
}
void Graph::AddEdge(int w, int v)
{
	adj[w].put(v);
	adj[v].put(w);
	++E;
}
Graph::~Graph()
{
	delete[] adj;
}
std::vector<int> Graph::GetBagValve(int w)
{
	return adj[w].Travel();

因为比较简单,此处不进行解释

4.有向图

4.1 DirectGraph类的实现

class DirectGraph :public Graph
{
public:
	DirectGraph(int v) :
		Graph(v) {}
	void AddEdge(int w, int v) override;
	DirectGraph reverse();
};

DirGraph类直接继承于Graph类,有效防止了重复代码的书写

4.2 方法的实现

void DirectGraph::AddEdge(int w, int v)
{
	adj[w].put(v);
	++E;
}
DirectGraph DirectGraph::reverse()  //提供了反转方法,这在后续的拓扑排序中有用
{
	DirectGraph R(V);
	for (int v = 0; v < V; v++)
	{
		std::vector<int>temp = GetBagValve(v);
		for (int i = 0; i < temp.size(); ++i)
			R.AddEdge(temp[i], v);
	}
	return R;
}

5. BFS与DFS类的base类实现

5.1类的实现

class base
{
protected:
	bool*marked;  // 标记数组
	int*EdgeTo; //从哪条边访问的?
	int s; //起点
public:
	base() = default;
	base(int s, Graph &G);
	virtual ~base() //析构函数
	{
		delete[] marked;
		delete[] EdgeTo;
	}
	bool HasPathTo(int v);  是否有起点s到v的路径?
	std::stack<int>PathTo(int v);  取路径
};

5.2 类方法的实现

bool base::HasPathTo(int v)
{
	return marked[v];
}
std::stack<int> base::PathTo(int v)
{
	if (HasPathTo(v))
		return std::stack<int>();
	std::stack<int>temp;
	while (v != s)
	{
		temp.push(v);
		v = EdgeTo[v];
	}
	temp.push(s);
	return temp;
}
base::base(int s, Graph & G)   //构造函数
{
	marked = new bool[G.GetV()]{ 0 };
	EdgeTo = new int[G.GetV()];
	this->s = s;
}
void BFS::bfs(Graph&G,int s)
{
	std::queue<int>q;
	q.push(s);
	cout << s << endl;
	marked[s] = true;
	while (!q.empty())
	{
		s = q.front();
		q.pop();
		std::vector<int>temp = G.GetBagValve(s);
		for (auto it = temp.begin(); it != temp.end(); ++it)
			if (!marked[*it])
			{
				cout << *it << endl;
				EdgeTo[*it] = s;
				marked[*it] = true;
				q.push(*it);
			}
	}
}

6.深度优先搜索DFS类的实现

6.1 class的实现

class DFS:public base
{
public:
	DFS(int s, Graph &G)   //构造函数,开始搜索
		:base(s, G) {dfs(G, s);}  
	void dfs(Graph&G, int w);
};

6.2 类方法的实现

void DFS::dfs(Graph & G, int w)
{
	cout << w << endl;
	marked[w] = true;
	std::vector<int> temp = G.GetBagValve(w);
	for (int i = 0; i < temp.size(); ++i)
		if (!marked[temp[i]])
		{
			EdgeTo[temp[i]] = w;
			dfs(G, temp[i]);
		}
}

7 广度优先搜索bfs类的实现

7.1 类的实现

class BFS:public base
{
public:
	BFS(int x,Graph&G):
		base(x, G) {bfs(G, x);}
	void bfs(Graph&G,int x);
};

与BFS类大同小异

7.2 bfs方法的实现

void BFS::bfs(Graph&G,int s)
{
	std::queue<int>q;
	q.push(s);
	cout << s << endl;
	marked[s] = true;
	while (!q.empty())
	{
		s = q.front();
		q.pop();
		std::vector<int>temp = G.GetBagValve(s);
		for (auto it = temp.begin(); it != temp.end(); ++it)
			if (!marked[*it])
			{
				cout << *it << endl;
				EdgeTo[*it] = s;
				marked[*it] = true;
				q.push(*it);
			}
	}
}

有没有很熟悉,没错,二叉树的层序遍历便是dfs

posted @ 2017-09-24 00:44  vhyz  阅读(274)  评论(0编辑  收藏  举报