目的:使用C++模板设计并逐步完善图的邻接矩阵抽象数据类型(ADT)。
内容:(1)请参照图的邻接矩阵模板类原型,设计并逐步完善图的邻接矩阵ADT。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。)
(2)使用构造函数,构造一个具有结点和边的有权图。
注意:DG(有向图), DN(有向网), UDG(无向图), UDN(无向网)
题解
不了解接口怎么写的可以参考我另一篇邻接矩阵ADT的博客
/* 边表的结点定义 */
template<class TypeOfEdge>
struct edgeNode
{
int data;
TypeOfEdge weight;
edgeNode<TypeOfEdge>* next;
edgeNode(const int& d, edgeNode<TypeOfEdge>* ptr = NULL) //构造函数,用于构造其他结点(无权图)
//函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
{
next = ptr;
data = d;
weight = 0;
}
edgeNode(const int& d, const TypeOfEdge& w, edgeNode<TypeOfEdge>* ptr = NULL) //构造函数,用于构造其他结点(带权图)
//函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
{
next = ptr;
data = d;
weight = w;
}
int getData() { return data; } //取得结点的序号(顶点集)
TypeOfEdge getWeight() { return weight; } //取得边集中对应边的权值
void SetLink(edgeNode<TypeOfEdge>* link) { next = link; } //修改结点的next域
void SetData(int value) { data = value; } //修改结点的序号(顶点集)
void SetWeight(TypeOfEdge value) { weight = value; } //修改边集中对应边的权值
};
//图的邻接表类
template<class TypeOfVer, class TypeOfEdge>
struct verNode
{
TypeOfVer ver;
edgeNode<TypeOfEdge>* head;
verNode(edgeNode<TypeOfEdge>* h = NULL) { head = h; }
TypeOfVer getVer() { return ver; } //取得结点值(顶点集)
edgeNode<TypeOfEdge>* getHead() { return head; } //取得对应的边表的头指针
void setVer(TypeOfVer value) { ver = value; } //设置结点值(顶点集)
void setHead(edgeNode<TypeOfEdge>* value) { head = value; } //设置对应的边表的头指针
};
template <class TypeOfVer, class TypeOfEdge>
class adjlist_graph {
private:
int Vers; //顶点数
int Edges; //边数
verNode<TypeOfVer, TypeOfEdge>* verList;
string GraphKind; //图的种类标志
bool Delete_Edge(int u, int v)
{
edgeNode <TypeOfEdge>* p = verList[u].head;
while (p->next != NULL) {
if (p->data == v) {
break;
}
if (p->next == NULL)
break;
p = p->next;
}
edgeNode <TypeOfEdge>* q = verList[u].head;
if (q!=p)
while (q->next != p) {
q = q->next;
}
q->next = p->next;
delete p;
return 1;
}
bool DFS(int u, int& num, int visited[]) //DFS遍历(递归部分)
{
int i = u;
edgeNode <TypeOfEdge>* p = verList[i].head;
while (p != NULL) {
if (visited[p->data] == 0) {
cout << "->" << verList[p->data].ver;
visited[p->data] = 1;
num++;
DFS( p->data,num, visited);
}
if (p->next == NULL)
break;
p = p->next;
}
return 1;
}
bool w1;
public:
void display()//测试用
{
for (int i = 0; i < Vers; i++) {
cout << verList[i].ver;
if (i != Vers - 1)
cout << " ";
}
cout << endl;
for (int i = 0; i < Vers; i++) {
edgeNode <TypeOfEdge> * p = verList[i].head;
cout << verList[i].ver << ":";
while (p != NULL) {
cout << p->data <<":"<<p->weight;
if (p->next == NULL)
break;
cout << "->";
p = p->next;
}
if (i != Vers - 1)
cout << endl;
}
}
adjlist_graph(const string& kd, int vSize, const TypeOfVer d[])
{ //构造函数构造一个只有结点没有边的图。
GraphKind = kd; Vers = vSize; w1 = 0;
verList=new verNode<TypeOfVer,TypeOfEdge> [Vers];
for(int i=0;i<Vers;++i)
verList[i].ver=d[i];
}
adjlist_graph(const string& kd, int vSize, int eSize, const TypeOfVer d[], int** e)
{ //构造函数构造一个无权图。5个参数的含义:图的类型、结点数、边数、结点集和边集
GraphKind = kd; Vers = vSize; w1 = 0;
verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
for (int i = 0; i < Vers; ++i)
verList[i].ver = d[i];
Edges = eSize;
for (int i = 0; i < eSize; i++) {
edgeNode<TypeOfEdge> *p = new edgeNode<TypeOfEdge>(e[i][1]);
if ( kd == "DG") {
p->next = verList[e[i][0]].head;
verList[e[i][0]].head = p;
}
else {
p->next = verList[e[i][0]].head;
verList[e[i][0]].head = p;
edgeNode<TypeOfEdge>*q = new edgeNode<TypeOfEdge>( e[i][0]);
q->next = verList[e[i][1]].head;
verList[e[i][1]].head = q;
}
}
}
adjlist_graph(const string& kd, int vSize, int eSize, const TypeOfVer d[], int** e, const TypeOfEdge w[]) //构造函数构造一个有权图。
{
GraphKind = kd; Vers = vSize; w1 = 1;
verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
for (int i = 0; i < Vers; ++i)
verList[i].ver = d[i];
Edges = eSize;
for (int i = 0; i < eSize; i++) {
edgeNode<TypeOfEdge>* p = new edgeNode<TypeOfEdge>(e[i][1]);
p->weight = w[i];
if (kd == "DN") {
p->next = verList[e[i][0]].head;
verList[e[i][0]].head = p;
}
else {
p->next = verList[e[i][0]].head;
verList[e[i][0]].head = p;
edgeNode<TypeOfEdge>* q = new edgeNode<TypeOfEdge>(e[i][0]);
q->weight = w[i];
q->next = verList[e[i][1]].head;
verList[e[i][1]].head = q;
}
}
}
bool GraphisEmpty() { return Vers == 0; } //判断图空否
string GetGraphKind() { return GraphKind; }
bool GetVer(int u, TypeOfVer& data) //取得G中指定顶点的值
{
data = verList[u].ver;
return 1;
}
int GetFirstAdjVex(int u, int& v) //返回G中指定顶点u的第一个邻接顶点的位序(顶点集)。若顶点在G中没有邻接顶点,则返回-1
{
if (u<0 || u>Vers - 1) {
v = -1;
return -1;
}
if (verList[u].head != NULL) {
v = verList[u].head->data;
return 1;
}
v = -1;
return -1;
}
int GetNextAdjVex(int u, int v, int& w) //返回G中指定顶点u的下一个邻接顶点(相对于v)的位序(顶点集)。若顶点在G中没有邻接顶点,则返回false
{
if (u<0 || u>Vers - 1) {
v = -1;
return -1;
}
edgeNode <TypeOfEdge>* p = verList[u].head;
while (p != NULL) {
if (p->data == v) {
w = verList[u].head->data;
return 1;
}
if (p->next == NULL)
break;
p = p->next;
}
w = -1;
return -1;
}
bool PutVer(int u, TypeOfVer data) //对G中指定顶点赋值
{
verList[u].ver = data;
return 1;
}
bool InsertVer(const TypeOfVer& data) //往G中添加一个顶点
{
verNode<TypeOfVer, TypeOfEdge>* verList2 = new verNode<TypeOfVer, TypeOfEdge>[Vers + 1];
for (int i = 0; i < Vers; i++) {
verList2[i] = verList[i];
verList[i] = NULL;
}
verList2[Vers].ver = data;
verList2[Vers].head = NULL;
delete verList;
verList = verList2;
Vers++;
return 1;
}
int LocateVer(TypeOfVer data) //返回G中指定顶点的位置
{
for (int i = 0; i < Vers; i++) {
if (verList[i].ver == data)
return i;
}
return -1;
}
bool ExistEdge(int u, int v) //没写注释,我猜是判断边是否存在?
{
edgeNode <TypeOfEdge>* p = verList[u].head;
while (p != NULL) {
if (p->data == v)
return 1;
if (p->next == NULL)
break;
p = p->next;
}
p = verList[v].head;
while (p != NULL) {
if (p->data == u)
return 1;
if (p->next == NULL)
break;
p = p->next;
}
return 0;
}
bool PrintVer() //输出顶点集
{
for (int i = 0; i < Vers; i++) {
cout << verList[i].ver;
if (i != Vers - 1)
cout << " ";
}
return 1;
}
bool PrintAdjList() //输出邻接矩阵(?)
{
if (w1 == 0)
for (int i = 0; i < Vers; i++) {
edgeNode <TypeOfEdge>* p = verList[i].head;
cout << verList[i].ver << "->";
while (p != NULL) {
cout << p->data << "->";
if (p->next == NULL)
break;
p = p->next;
}
cout << "nullptr";
if (i != Vers - 1)
cout << endl;
}
else
for (int i = 0; i < Vers; i++) {
edgeNode <TypeOfEdge>* p = verList[i].head;
cout << verList[i].ver << "->";
while (p != NULL) {
cout << p->data <<"("<<p->weight<<")" << "->";
if (p->next == NULL)
break;
p = p->next;
}
cout << "nullptr";
if (i != Vers - 1)
cout << endl;
}
return 1;
}
int GetVerNum() { return Vers; } //取得当前顶点数
int GetEdgeNum() { return Edges; } //取得当前边数
bool Insert_Edge(int u, int v) //无权图插入一条边
{
edgeNode <TypeOfEdge>* o = verList[u].head;
while (o != NULL) {
if (o->data == v)
return 0;
o = o->next;
}
if (GraphKind == "DG") {
edgeNode <TypeOfEdge>* p = new edgeNode <TypeOfEdge>(v);
p->next = verList[u].head;
verList[u].head = p;
}
else {
edgeNode <TypeOfEdge>* p = new edgeNode <TypeOfEdge>(v);
p->next = verList[u].head;
verList[u].head = p;
edgeNode <TypeOfEdge>* q = new edgeNode <TypeOfEdge>(u);
q->next = verList[v].head;
verList[v].head = q;
}
Edges++;
return 1;
}
bool Insert_Edge(int u, int v, TypeOfEdge w) //有权图插入一条边
{
if (GraphKind == "DG") {
edgeNode <TypeOfEdge>* p = new edgeNode <TypeOfEdge>(v,w);
p->next = verList[u].head;
verList[u].head = p;
}
else {
edgeNode <TypeOfEdge>* p = new edgeNode <TypeOfEdge>(v,w);
p->next = verList[u].head;
verList[u].head = p;
edgeNode <TypeOfEdge>* q = new edgeNode <TypeOfEdge>(u,w);
q->next = verList[v].head;
verList[v].head = q;
}
Edges++;
return 1;
}
bool DeleteVer(const TypeOfVer& data) //往G中删除一个顶点
{
int u = LocateVer(data);
verNode<TypeOfVer, TypeOfEdge>* verList2 = new verNode<TypeOfVer, TypeOfEdge>[Vers - 1];
for (int i = 0, k = 0; i < Vers; i++) {
if (i != u) {
verList2[k] = verList[i];
verList[i] = NULL;
k++;
}
}
delete verList;
verList = verList2;
Vers--;
edgeNode <TypeOfEdge>* p = NULL;
edgeNode <TypeOfEdge>* q = NULL;
for (int i = 0; i < Vers; i++) {
p = verList[i].head;
if (p != NULL && p->next == NULL) {
if (p->data == u) {
verList[i].head == NULL;
delete p;
}
else if (p->data > u) {
p->data=p->data-1;
}
continue;
}
p = p->next;
q = verList[i].head;
while (p!=NULL) {
if (p->data == u) {
q = p->next;
delete p;
p = q->next;
}
else if (p->data > u) {
p->data = p->data - 1;
}
if (p->next != NULL) {
p = p->next;
q = q->next;
}
}
q = verList[i].head;
if (q->data == u) {
verList[i].head = q->next;
delete q;
}
else if (q->data > u) {
q->data = q->data - 1;
}
}
return 1;
}
bool DeleteEdge(int u, int v) //删除边 (外壳:有向(删除1条边), 无向(删除2条边))
{
if (GraphKind == "DN" || GraphKind == "DG")
Delete_Edge(u,v);
else {
Delete_Edge(u, v);
Delete_Edge(v, u);
}
return 1;
}
void DFS_Traverse(int u) //DFS遍历(外壳部分)
{
int s[1000] = { 0 };
cout << verList[u].ver;
s[u] = 1;
for (int i = u; i < Vers; i++) {
if (s[i] != 0 && i != u) {
continue;
}
s[i] = 1;
DFS(u, i, s);
}
for (int i = 0; i < u; i++) {
if (s[i] != 0) {
continue;
}
s[i] = 1;
DFS(u, i, s);
}
cout << endl;
}
void BFS_Traverse(int u) //BFS遍历
{
int s[1000] = { 0 };
cout << verList[u].ver;
s[u] = 1;
for (int i = u; i < Vers; i++) {
edgeNode <TypeOfEdge>* p = verList[i].head;
if (s[i] == 0) {
cout << "->" << verList[i].ver;
s[i] = 1;
}
while (p != NULL) {
if (s[p->data] == 0) {
s[p->data] = 1;
cout << "->" << verList[p->data].ver;
}
p = p->next;
}
}
for (int i = 0; i < u; i++) {
edgeNode <TypeOfEdge>* p = verList[u].head;
if (s[i] == 0) {
cout << "->" << verList[i].ver;
s[i] = 1;
}
while (p != NULL) {
if (s[p->data] == 0) {
s[p->data] = 1;
cout << "->" << verList[p->data].ver;
}
p = p->next;
}
}
}
int GetDegree(int u)
{
if (u < 0 || u >= Vers)
return -1;
int num = 0;
edgeNode <TypeOfEdge>* p = verList[u].head;
while (p != NULL) {
num++;
p = p->next;
}
return num;
}
bool GetWeight(int u, int v, int& w)
{
edgeNode <TypeOfEdge>* p = verList[u].head;
while (p != NULL) {
if (p->data == v) {
w = p->weight;
return 1;
}
if (p->next == NULL)
break;
p = p->next;
}
p = verList[v].head;
while (p != NULL) {
if (p->data == u) {
w = p->weight;
return 1;
}
if (p->next == NULL)
break;
p = p->next;
}
return 0;
}
};