2021-1 用符号作为顶点名的图的API c++实现

输入格式

在这里插入图片描述
不需要知道边数,也没有直接给出顶点数。但是,通过两次扫描文件routes.txt,建立

  • 符号表 Sting -> id 从【机场名】找到标志符【ID】
  • 反向索引,从【ID】 找到【机场名】,即数组keys[]
  • 存储【ID】的无向图

在这里插入图片描述

API

在这里插入图片描述

SymbolGraph.h

头文件见 Graph.h Paths.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

示例

在这里插入图片描述

文本下载movies.txt

猜你喜欢

转载自blog.csdn.net/qq_34890856/article/details/112973370