-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGraph.cpp
More file actions
170 lines (156 loc) · 5.14 KB
/
Copy pathGraph.cpp
File metadata and controls
170 lines (156 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include "Graph.hpp"
#include "WikiAPI.hpp"
#include <queue>
#include <stack>
#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <utility>
using std::move;
using std::queue;
using std::stack;
using std::unordered_set;
using std::pair;
using std::cout;
using std::endl;
Graph::Graph():currNode(nullptr) {}
Graph::Graph(int srcID, string srcTitle)
{
emplaceSourceNode(srcID,move(srcTitle));
}
Graph::~Graph() {
for(auto& idNode: adjList)
delete idNode.second;
}
const string& Graph::getTitle(int id) {
return adjList[id]->title;
}
bool Graph::contains(int id) {
return adjList.find(id)!=adjList.end();
}
void Graph::emplaceSourceNode(int id, string title) {
currNode = adjList[id] = new Node(id, move(title));
}
void Graph::setSourceNode(int id) {
currNode = adjList[id];
}
void Graph::connectOutNode(int id) {
currNode->outgoingNodes.push_back(adjList[id]);
}
void Graph::connectToOutgoingLinks(bool displayPages) {
currNode->hasAllOutgoing=true;
if(displayPages && currNode->prev) cout<< currNode->prev->title+" -> "+currNode->title <<endl;
string text=WikiAPI::getOutgoingLinks(currNode->id);
string g="\"gplcontinue\"";
string p = "\"pageid\"";
string t = "\"title\"";
bool hasCont=false;
string gplcont;
int loc = text.find(g,0);
do{
if(loc!=string::npos) {
loc=loc+15;
hasCont = true;
gplcont = text.substr(loc,text.find('\"', loc) - loc);
}
else
hasCont=false;
loc = text.find(p,0);
while (loc != string::npos) {
int pos = loc + 9;
int id = stoi(text.substr(pos, text.find(',', pos) - pos));
loc=text.find(t, pos);
pos = loc + 9;
if(adjList.find(id)==adjList.end()) {
string title = text.substr(pos, text.find('\"', pos) - pos);
emplaceOutNode(id, title);
}
else
connectOutNode(id);
loc = text.find(p,pos);
}
if(hasCont) {
text = WikiAPI::getOutgoingLinks(currNode->id, gplcont);
loc=text.find(g,0);
}
}while(hasCont);
}
vector<int> Graph::getPrevPathTo(Node* src, Node* dest) {
vector<int> path;
while(src!=dest){//TODO: explore efficiency
path.push_back(src->id);
src=src->prev;
}
path.push_back(src->id);
std::reverse(path.begin(),path.end());
return path;
}
void Graph::emplaceOutNode(int id, string title) {
currNode->outgoingNodes.push_back(adjList[id] = new Node(id, move(title), currNode));
}
vector<int> Graph::breadthFirstSearchOut(int srcID, string srcTitle, int targetID, bool displayPages) {
if(contains(srcID))
setSourceNode(srcID);
else
emplaceSourceNode(srcID,move(srcTitle));
queue<Node*> nodes({currNode});
unordered_set<Node*> visited({currNode});
Node* dest = nullptr;
while(!nodes.empty() && !dest){
currNode = nodes.front(); nodes.pop();
//if this node hasn't gotten its outgoing links, get them first
if(!currNode->hasAllOutgoing)
connectToOutgoingLinks(displayPages);
//iterate through the current Node's outgoing links
for(Node* out: currNode->outgoingNodes){
//if we haven't encountered it, make its prev the currNode and add it to visited
if(visited.insert(out).second){
nodes.push(out);
out->prev=currNode;
}
//if found, get path and return it. We also want to reset currNode
if(out->id==targetID) {
dest=out;
break;
}
}
}
return dest ? move(getPrevPathTo(dest, adjList[srcID])):vector<int>();
}
vector<int> Graph::iterativeDeepeningDepthSearchOut(int srcID, string srcTitle, int targetID, int maxDepth, bool displayPages) {
if(contains(srcID))
setSourceNode(srcID);
else
emplaceSourceNode(srcID,move(srcTitle));
stack<pair<Node*,int>> nodeDepths;
nodeDepths.push({currNode, 0});
unordered_set<Node*> visited({currNode});
Node* dest = nullptr;
while(!nodeDepths.empty() && !dest){
currNode = nodeDepths.top().first;
int depth = nodeDepths.top().second;
nodeDepths.pop();
//if this node hasn't gotten its outgoing links, get them first
if(!currNode->hasAllOutgoing)
connectToOutgoingLinks(displayPages);
//iterate through the current Node's outgoing links
if(depth<maxDepth) for(Node* out: currNode->outgoingNodes) {
//if we haven't encountered it,make its prev the currNode and add it to visited
if(visited.insert(out).second){
nodeDepths.push({out,depth+1});
out->prev=currNode;
}
//if found, get path and return it. We also want to reset currNode
if (out->id == targetID){
dest=out;
break;
}
}
}
return dest ? move(getPrevPathTo(dest, adjList[srcID])):vector<int>();
}
Graph::Node::Node(int id, string title, Node* prev)
: id(id),
title(move(title)),
prev(prev)
{}