2021-1 从文件构建有向图API 测试单点和多点可达 c++实现

API

在这里插入图片描述
和无向图Graph.h比较,只改动了几个地方,一个翻转图,添加边时只是单向添加。

在这里插入图片描述

一个改动

返回整个list<int>可能导致Stack Overflow,索性只返回一个指向堆的指针。另外,用一个宏定义简化书写。

//原来是
list<int> adj(int v){
    
    
	return *((*m_adj)[v]);
}

//可以这样调用邻接点
for(auto &next : G.adj(v)){
    
     .....next; }

//现在改为返回指针
ListPtr Digraph::adj(int v)
{
    
    
	return (m_adj->at(v));
}

//这样调用
for(auto &next: *G.adj(v)){
    
    
	next.....;
}
//或者调用
ListPtr p=G.adj(v);
for(auto it=p->begin();it!=p->end();++it){
    
    
	.......(*it);
}


//如果设计一个宏定义
#define forIt(ListPtr) for(auto it=ListPtr->begin();it!=ListPtr->end();++it)

//最后这样写
forIt(G.adj(v)){
    
    
	........(*it)....;
}

代码

//Digraph.h
#pragma once

#include<iostream>
#include<list>
#include<vector>
#include<fstream>

using namespace std;

#define out(x) cout<<x<<" "
#define hh printf_s("\n")
#define forIt(ListPtr) for(auto it=ListPtr->begin();it!=ListPtr->end();++it)


/*******************如无必要,勿增实体************************/
typedef list<int>* ListPtr;

class Digraph
{
    
    
public:
	Digraph(int V);
	Digraph(string file);

	void addEdge(int v, int w);
	ListPtr adj(int v);
	int V() {
    
     return m_V; }
	int E() {
    
     return m_E; }
	Digraph& reverse();//在堆上开辟,返回引用避免复制
	string toString();
private:
	int m_V=0;
	int m_E=0;
	vector<ListPtr>* m_adj=nullptr;

	void initGraph(int V);
	bool isParallel_edges_self_loop(int v, int w);
	string intToStr(int n);
};



void testDigraph();
#include "Digraph.h"

Digraph::Digraph(int V)
{
    
    
	m_V = V;
	m_E = 0;

	m_adj = new vector<ListPtr>(V, nullptr);
	for (int i = 0; i < V; i++)
	{
    
    
		m_adj->at(i) = new list<int>(0);
	}
}

Digraph::Digraph(string file)
{
    
    
	ifstream in(file, ios::in);
	if (!in) {
    
    
		printf_s("file open error.");
		return;
	}

	int V, E;
	in >> V;
	initGraph(V);
	in >> E;//不一定等于最后的边数,因为可能不包含自环和平行边
	int w, v;
	for (int i = 0; i < E; i++)
	{
    
    
		in >> w >> v;
		addEdge(w, v);
	}
	in.close();
}

void Digraph::addEdge(int v, int w)
{
    
    
	//if (isParallel_edges_self_loop(v, w)) return;
	(*m_adj)[v]->push_front(w);
	m_E++;
}

ListPtr Digraph::adj(int v)
{
    
    
	return (m_adj->at(v));
}

Digraph& Digraph::reverse()
{
    
    
	Digraph* rG = new Digraph(m_V);
	for (int i = 0; i < m_V; ++i) {
    
    
		forIt(m_adj->at(i)) {
    
    
			rG->addEdge(*it, i);
		}
	}
	return *rG;
}

string Digraph::toString()
{
    
    

	string s = intToStr(m_V) + " vertices, " + intToStr(m_E) + " edges\n";

	for (int i = 0; i < m_V; i++)
	{
    
    
		s += intToStr(i) + ": ";
		for (auto adj : *(m_adj->at(i)))
		{
    
    
			s += intToStr(adj) + " ";
		}
		s += "\n";
	}
	return s;
}

string
inline Digraph::intToStr(int n)
{
    
    
	char int_s[20] = {
    
     0 };//末尾加上'\0'
	_itoa_s(n, int_s, 10);// 10 表示十进制
	return string(int_s);
}

void
inline Digraph::initGraph(int V)
{
    
    
	m_V = V;
	m_E = 0;

	m_adj = new vector<ListPtr>(V, nullptr);
	for (int i = 0; i < V; i++)
	{
    
    
		m_adj->at(i) = new list<int>(0);
	}
}

inline
bool Digraph::isParallel_edges_self_loop(int v, int w)
{
    
    
	if (v == w) return true;
	for (auto& n : *(m_adj->at(v))) {
    
    
		if (n == w) {
    
    
			return true;
		}
	}
	return false;
}

void testDigraph()
{
    
    
	Digraph dG("tinyDG.txt");
	out(dG.toString()), hh;
	Digraph rG=dG.reverse();
	out(rG.toString()),hh;
}

tinyDG.txt

13
22
 4  2
 2  3
 3  2
 6  0
 0  1
 2  0
11 12
12  9
 9 10
 9 11
 7  9
10 12
11  4
 4  3
 3  5
 6  8
 8  6
 5  4
 0  5
 6  4
 6  9
 7  6

DFS搜索可达性

#pragma once
#include"Digraph.h"
class DirectedDFS
{
    
    
public:
	DirectedDFS(Digraph& G,int s);//搜索单点可达
	DirectedDFS(Digraph& G, list<int> sources);//标记多点可达的点

	bool marked(int v);
private:
	vector<bool>* m_marked = nullptr;
	void dfs(Digraph& G, int s);
};

void testDFS();


#include "DirectedDFS.h"

DirectedDFS::DirectedDFS(Digraph& G, int s)
{
    
    
	m_marked = new vector<bool>(G.V(), false);
	dfs(G, s);
}

DirectedDFS::DirectedDFS(Digraph& G, list<int> sources)
{
    
    
	m_marked = new vector<bool>(G.V(), false);
	for (auto& s : sources) {
    
    
		if (!m_marked->at(s)) {
    
    
			dfs(G, s);
		}
	}
}

bool DirectedDFS::marked(int v)
{
    
    
	return m_marked->at(v);
}

void DirectedDFS::dfs(Digraph& G, int s)
{
    
    
	m_marked->at(s) = true;
	forIt (G.adj(s)) {
    
    
		if (!m_marked->at(*it)) {
    
    
			dfs(G, *it);
		}
	}
}

void testDFS()
{
    
    
	Digraph G("tinyDG.txt");
	list<int> sources = {
    
     2,6,8 };
	DirectedDFS dfs(G, sources);
	out("can reach :");
	for (int i = 0; i < G.V(); ++i) {
    
    
		if (dfs.marked(i)) {
    
    
			 out(i);
		}
	}
	hh;
}

猜你喜欢

转载自blog.csdn.net/qq_34890856/article/details/112990201
今日推荐