输入格式
不需要知道边数,也没有直接给出顶点数。但是,通过两次扫描文件routes.txt
,建立
- 符号表
Sting -> id
从【机场名】找到标志符【ID】 - 反向索引,从【ID】 找到【机场名】,即数组
keys[]
- 存储【ID】的无向图
API
SymbolGraph.h
#pragma once
#include<map>
#include<sstream>
#include"Graph.h"
#include"Paths.h"
/****************如无必要,勿增实体********************/
class SymbolGraph
{
public:
SymbolGraph() {
}
SymbolGraph(string file, char sp);
bool contains(string key) {
return m_keyToID->find(key) != m_keyToID->end();
}
int index(string key) {
return m_keyToID->at(key);
}
string name(int idx) {
return m_keys->at(idx);
}
Graph* G() {
return m_graph;
}
private:
map<string, int>* m_keyToID = nullptr;//键值-> ID
vector<string>* m_keys = nullptr;//ID -> 键值
Graph* m_graph = nullptr;
vector<string>* split(string s, char sep);
};
void degreeOfSeparation(string file, string goalStr);
void testSymbolGraph();
SymbolGraph.cpp
#include "SymbolGraph.h"
#define out(x) cout<<x<<" "
#define hh printf_s("\n")//换行
/*
* 要求文件里面的边只出现一次,即无向图,添加边时自动完成from->to to->from
* 格式:起点 邻接点1 邻接点2 邻接点3 ~
*/
SymbolGraph::SymbolGraph(string file, char sp)
{
m_keyToID = new map<string, int>();
ifstream stream(file, ios::in);
string lineStr = "";
while (getline(stream, lineStr)) {
vector<string>* tmp = split(lineStr, sp);
int n = tmp->size();
for (int i = 0; i < n; i++)
{
if (m_keyToID->find(tmp->at(i)) == m_keyToID->end()) {
m_keyToID->emplace(tmp->at(i), m_keyToID->size());
}
}
}
//构造键值表
int v = m_keyToID->size();
m_keys = new vector<string>(v);
for (auto it = m_keyToID->begin(); it != m_keyToID->end(); ++it) {
m_keys->at(it->second) = it->first;
}
//初始化顶点
m_graph = new Graph(v);
//添加边
ifstream in(file, ios::in);
while (getline(in, lineStr)) {
vector<string>* tmp = split(lineStr, sp);
int n = tmp->size();
int v = m_keyToID->at(tmp->at(0));
for (int i = 1; i < n; i++)
{
int w = m_keyToID->at(tmp->at(i));
m_graph->addEdge(v, w);//添加无向边
}
}
}
vector<string>* SymbolGraph::split(string s, char sep)
{
istringstream iss(s);
vector<string>* res = new vector<string>();
string buffer;
while (getline(iss, buffer, sep)) {
res->push_back(buffer);
}
return res;
}
void degreeOfSeparation(string file, string startName,char sp)
{
SymbolGraph* sg = new SymbolGraph(file, sp);
Graph* graph = sg->G();
if (!sg->contains(startName)) {
out(startName), out(" not in dataBase."), hh;
return;
}
int s = sg->index(startName);
Paths path(*graph, s);//默认是广度优先搜索
out("input search name, input q to quit.\n");
string next = "";
while (true) {
getline(cin,next);
if (next == "q") break;
if (sg->contains(next)) {
int t = sg->index(next);
if (path.hasPathto(t)) {
for (auto id :path.pathTo(t)) {
out(" "), out(sg->name(id)), hh;
}
}
else {
out("Not connected");
}
}
else {
out("Not in dataBase.");
}
hh;
}
}
void testSymbolGraph()
{
//degreeOfSeparation("routes.txt", "JFK",' ');
degreeOfSeparation("movies.txt", "Tin Men (1987)",'/');
}
routes.txt
LAX LAS PHX
LAS PHX DEN
PHX DEN ORD DFW
DEN ORD
ORD DFW HOU ATL JFK
DFW HOU
HOU ATL MCO
ATL MCO JFK
MCO JFK