这是一个AOV拓扑排序的例子,为了应付公司测试而作,写起来也不容易,给记录一下。
在Visual C++2005下做的,这个版本的IDE环境用起来还不错。
aov.h
//data structure
//linked graph

#include <iostream>
#include <vector>
#include <string>
#include <map>

class EdgeNode

...{
public:
int adjvex;
//double weight; useless in this program.
EdgeNode *nextarc;
public:
EdgeNode(const int idx)

...{
adjvex = idx;
nextarc = 0;
}
};

// table head
class VNode

...{
public:
std::string data;
EdgeNode *firstarc;
public:
VNode(const char* data, EdgeNode * firstarc)

...{
if(data != 0)
this->data = data;
else
printf("check test file. VNode Constructor. ");
this->firstarc = firstarc;
}
};

class Graph

...{
public:
int vnum;
std::vector<VNode> Vertices;
private:
std::map<std::string, int> node_map;//pretend to be hash_map
public:
Graph()

...{
vnum = 0;
}
int addNode(VNode& node);
int getNode(const char* name); //return the index in Vertices.
void clear();
};

aov.cpp
//Normal return 0, otherwise -1
//Graph DAG, which records clothes information.
//
#include "aov.h"

using namespace std;

int Graph::addNode(VNode& node)

...{
node_map.insert(map<std::string, int>::value_type(node.data, vnum++));
Vertices.push_back(node);
return 0;
}

int Graph::getNode(const char* name)

...{
map<string, int>::iterator it;
it = node_map.find(name);
if(it != node_map.end())
return it->second;
return -1;
}

void Graph::clear()

...{
vector<EdgeNode*> needtodel;
for(vector<VNode>::iterator it = Vertices.begin(); it != Vertices.end(); ++it)

...{
EdgeNode* next = it->firstarc;
while(next)

...{
needtodel.push_back(next);
next = next->nextarc;
}
}
for(vector<EdgeNode*>::iterator it = needtodel.begin(); it != needtodel.end(); ++it)

...{
delete *it;
}
}

test.h
#include "aov.h"

#define PATH_LEN 256

class AOVTest

...{
Graph G;
std::vector<int> outputArray;
public:
int prepare(const char* file);
int TopologicalSort();
int output(const char* file);
};
test.cpp
#include "test.h"
#include <fstream>
#include <stack>
using namespace std;

#define BUFFER_SIZE 1024

int AOVTest::TopologicalSort()

...{
int count = 0;
int* indegree = (int*)calloc(G.vnum, sizeof(int));
if(!indegree)

...{
printf( "Can't allocate memory " );
return -1;
}

for(int i = 0; i < G.vnum; ++i)

...{
EdgeNode* t = G.Vertices[i].firstarc;
while(t)

...{
indegree[t->adjvex]++;
t = t->nextarc;
}
}

stack<int> S;
for(int i = 0; i<G.vnum; ++i)

...{
if(indegree[i] == 0)
S.push(i);
}
count = 0;
while(!S.empty())

...{
int idx = S.top();
outputArray.push_back(idx);
S.pop();
++count;
for(EdgeNode* t = G.Vertices[idx].firstarc; t ; t = t->nextarc)

...{
int k = t->adjvex;
indegree[k]--;
if(indegree[k] == 0)
S.push(k);
}
}
if(count < G.vnum)

...{
free(indegree);
return -1;
}
free(indegree);
return 0;
}

//
//create graph from test file
int AOVTest::prepare(const char* file)

...{
fstream fs(file, ios::in);
if(!fs)

...{
cout << "in file open failed!" << endl;
return -1;
}

while(!fs.eof())

...{
char buffer[BUFFER_SIZE];
memset(buffer, 0, BUFFER_SIZE);
fs.getline(buffer, BUFFER_SIZE);

string line(buffer);
if(line.empty())
continue;

string::size_type pos = 0;
pos = line.find("->", 0);
if(pos != string::npos)

...{
//handle with first cloth
string sfirst = line.substr(0, pos);
if(sfirst.empty())

...{
printf("Error format. check test file. //->first one not exist!");
return -1;
}
int idx1 = G.getNode(sfirst.c_str());
if(idx1 == -1)

...{ //find in VNode
idx1 = G.vnum;
VNode vnode1(sfirst.c_str(), 0);
G.addNode(vnode1);
}

//handle with last cloth
string slast = line.substr(pos + 2, line.length() - pos - 2);
if(slast.empty())

...{
printf("Error format. check test file. //->last one not exist!");
return -1;
}
int idx2 = G.getNode(slast.c_str());
if(idx2 == -1)

...{ //find in VNode
idx2 = G.vnum;
VNode vnode2(slast.c_str(), 0);
G.addNode(vnode2);
}

//connection reverse
EdgeNode* plink = new EdgeNode(idx2);
EdgeNode* next = G.Vertices[idx1].firstarc;
if(!next)
G.Vertices[idx1].firstarc = plink;
else

...{
EdgeNode* current;
while(next)

...{
current = next;
next = next->nextarc;
}
current->nextarc = plink;
}
}
}
return 0;
}

int AOVTest::output(const char* file)

...{
fstream fs(file, ios::out);
if(!fs)

...{
cout << "out file open failed!" << endl;
return -1;
}

for(vector<int>::iterator it = outputArray.begin(); it != outputArray.end(); ++it)

...{
fs << G.Vertices[*it].data << endl;
}
return 0;
}
最后的了,main.cpp
#include "test.h"

#define USAGE_MSG "Usage: AOV [infile] + options
-o refer to output file.
default -o is result.txt. "
int main(int argc, char** argv)

...{
if(argc < 2)

...{
//printf("Usage: AOV [infile] + options
// -o refer to output file.
// default -o is result.txt. ");
printf(USAGE_MSG);
getchar();
return -1;
}

char infile[256];
char outfile[256];
memset(outfile, 0, sizeof(outfile));

for(int i = 1; i < argc; ++i)

...{
if(argv[i][0] != '-')

...{
if(i == 1)
strcpy(infile, argv[i]);
else if(i == 3)
strcpy(outfile, argv[i]);
else

...{
printf(USAGE_MSG);
getchar();
return -1;
}

}
else

...{
if(argv[i][1] != 'o' || strlen(argv[i]) > 2)

...{
printf(USAGE_MSG);
getchar();
return -1;
}
}
}
if(!outfile)

...{
strcpy(outfile, "result.txt");
}

AOVTest ts;
int ret = 0;
ret = ts.prepare(infile);
if(ret)
_ASSERT(0);
ret = ts.TopologicalSort();
if(ret)
_ASSERT(0);
ret = ts.output(outfile);
if(ret)
_ASSERT(0);

getchar();
return 0;
}