idk why these stuffs get stashed for so long and I didn't ever commit them
This commit is contained in:
112
OrigFiles/6-图/6-3-1-MGTraverseApp/LinkQueue.h
Normal file
112
OrigFiles/6-图/6-3-1-MGTraverseApp/LinkQueue.h
Normal file
@@ -0,0 +1,112 @@
|
||||
|
||||
template <class DT>
|
||||
struct QNode //结点
|
||||
{
|
||||
DT data; //数据域,存储数据元素值
|
||||
QNode *next;//指针域,指向下一个结点
|
||||
};
|
||||
|
||||
template<class DT>
|
||||
struct LinkQueue
|
||||
{
|
||||
QNode<DT> * front;
|
||||
QNode<DT> * rear;
|
||||
};
|
||||
|
||||
|
||||
//【算法3.19】
|
||||
template <class DT>
|
||||
void InitQueue(LinkQueue<DT> &Q)//创建空队列
|
||||
{
|
||||
Q.front=new QNode<DT>; //创建头结点
|
||||
if(!Q.front) exit(1); //创建失败,结束运行
|
||||
Q.front->next=NULL;
|
||||
Q.rear=Q.front;
|
||||
}
|
||||
|
||||
//【算法3.20】
|
||||
template <class DT>
|
||||
void DestroyQueue(LinkQueue<DT> &Q)//释放链队
|
||||
{
|
||||
QNode<DT> *p;
|
||||
while(Q.front)//从头结点开始,依次释放结点
|
||||
{
|
||||
p=Q.front;
|
||||
Q.front=Q.front->next;
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
||||
//【算法3.21】 入队
|
||||
template<class DT>
|
||||
bool EnQueue(LinkQueue<DT> &Q,DT e)
|
||||
{
|
||||
QNode<DT> *p;
|
||||
p=new QNode<DT>; // 创建新结点
|
||||
if(!p) return false; // 创建失败,结束运行
|
||||
p->data=e; // 新结点赋值
|
||||
p->next=NULL; // 链在队尾
|
||||
Q.rear->next=p;
|
||||
Q.rear=p;
|
||||
return true; // 入队成功,返回true
|
||||
}
|
||||
|
||||
//【算法3.22】 出队
|
||||
template<class DT>
|
||||
bool DeQueue(LinkQueue<DT> &Q,DT &e)
|
||||
{
|
||||
QNode<DT> *p;
|
||||
if(Q.front==Q.rear) return false; //队空,返回false
|
||||
p=Q.front->next; // 取出队元素
|
||||
e=p->data;
|
||||
Q.front->next=p->next; //队首元素出队
|
||||
if(Q.rear==p) //只有一个元素时出队,
|
||||
Q.rear=Q.front; // 修改队尾
|
||||
delete p;
|
||||
return true; // 出队成功,返回true
|
||||
}
|
||||
|
||||
|
||||
//【算法3.23】 取队头元素
|
||||
template<class DT>
|
||||
bool GetHead(LinkQueue<DT> Q,DT &e)
|
||||
{
|
||||
if(Q.front==Q.rear) return false; // 队空,返回false
|
||||
e=Q.front->next->data;
|
||||
return true; // 删除成功,返回true
|
||||
}
|
||||
|
||||
//取队尾元素
|
||||
template<class DT>
|
||||
bool GetTail(LinkQueue<DT> Q,DT &e)
|
||||
{
|
||||
if(Q.front==Q.rear) // 队空
|
||||
return false; // 返回false
|
||||
e=Q.rear->data; // 获取队尾元素
|
||||
return true; // 返回true
|
||||
}
|
||||
|
||||
//测队空
|
||||
template<class DT>
|
||||
bool QueueEmpty(LinkQueue<DT> Q)
|
||||
{
|
||||
if(Q.front==Q.rear) // 队空
|
||||
return true; //返回true
|
||||
else //非空
|
||||
return false; //返回false
|
||||
}
|
||||
|
||||
//显示队列内容
|
||||
template<class DT>
|
||||
void DispQueue(LinkQueue<DT> Q)
|
||||
{
|
||||
QNode<DT> *p;
|
||||
p=Q.front->next;
|
||||
while(p)
|
||||
{
|
||||
cout<<p->data<<"\t";
|
||||
p=p->next;
|
||||
}
|
||||
cout<<endl;
|
||||
}
|
||||
|
||||
107
OrigFiles/6-图/6-3-1-MGTraverseApp/MGTraverseApp.cpp
Normal file
107
OrigFiles/6-图/6-3-1-MGTraverseApp/MGTraverseApp.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
//#include<string>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "MGraph.h"
|
||||
#include "LinkQueue.h"
|
||||
using namespace std;
|
||||
|
||||
void DispMenu()
|
||||
{
|
||||
cout<<"\n请选择你要的操作"<<endl;
|
||||
cout<<" 1. 建立图"<<endl;
|
||||
cout<<" 2. 判断两顶点的连通性"<<endl;
|
||||
cout<<" 3. 判断图的连通性"<<endl;
|
||||
cout<<" 4. 显示图"<<endl;
|
||||
cout<<" 0. 退出"<<endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//算法6.14 判断两顶点是否连通
|
||||
template<class DT>
|
||||
bool IsConected(MGraph<DT> G, int i, int j)
|
||||
{
|
||||
int k;
|
||||
for(k=0;k<G.vexnum;k++)
|
||||
visited[i]=false;
|
||||
DFS2(G,i);
|
||||
if(visited[j]==false)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 算法6.15 判断图的连通性
|
||||
template<class DT>
|
||||
bool IsGraphConected(MGraph<DT> G)
|
||||
{
|
||||
int i,flag=1;
|
||||
for(i=0;i<G.vexnum;i++) // 访问标志初始化
|
||||
visited[i]=0;
|
||||
DFS2(G,0); // 遍历图
|
||||
for(i=0;i<G.vexnum;i++)
|
||||
if(visited[i]==0) // 如果未遍历到所有顶点
|
||||
{
|
||||
flag=0;break; // 图不连通
|
||||
}
|
||||
return flag; // 否则,图连通
|
||||
}
|
||||
|
||||
bool visited[MAX_VEXNUM]={false};
|
||||
|
||||
void main()
|
||||
{
|
||||
char u,v;
|
||||
int i,j,k;
|
||||
MGraph<char> G;
|
||||
int choice;
|
||||
do
|
||||
{
|
||||
DispMenu();
|
||||
cin>>choice;
|
||||
switch(choice)
|
||||
{
|
||||
case 1: // 创建无向图
|
||||
CreateUDG(G);
|
||||
cout<<endl;
|
||||
cout<<"创建的图为:"<<endl;
|
||||
DispG(G);
|
||||
break;
|
||||
case 2: // 判断两顶点的连通性
|
||||
cout<<"请输入两顶点值: ";
|
||||
cin>>u>>v;
|
||||
i=LocateVex(G,u);
|
||||
j=LocateVex(G,v);
|
||||
if(i==-1 ||j==-1 || i==j) // 顶点不存在
|
||||
cout<<"\n顶点不存在或两顶点相同 "<<endl;
|
||||
else
|
||||
{
|
||||
if(IsConected(G,i,j))
|
||||
cout<<"\n"<<u<<"和"<<v<<"之间连通!"<<endl;
|
||||
else
|
||||
cout<<"\n"<<u<<"和"<<v<<"之间不连通!"<<endl;
|
||||
}
|
||||
cout<<endl;
|
||||
break;
|
||||
case 3: // 判断图的连通性
|
||||
if(IsGraphConected(G))
|
||||
cout<<"\n此图连通! "<<v<<endl;
|
||||
else
|
||||
cout<<"\n此图不连通!"<<endl;
|
||||
cout<<endl;
|
||||
break;
|
||||
case 4: // 显示图
|
||||
DispG(G);
|
||||
cout<<endl;
|
||||
break;
|
||||
case 0:
|
||||
cout<<"\n结束运行,Bye-Bye!"<<endl;
|
||||
break;
|
||||
default:
|
||||
cout<<"\n选择不合理,请重选!"<<endl;
|
||||
}
|
||||
}while(choice!=0);
|
||||
}
|
||||
299
OrigFiles/6-图/6-3-1-MGTraverseApp/Mgraph.h
Normal file
299
OrigFiles/6-图/6-3-1-MGTraverseApp/Mgraph.h
Normal file
@@ -0,0 +1,299 @@
|
||||
/*--------------------------无向图的邻接矩阵表示-----------------------------*/
|
||||
|
||||
#define MAX_VEXNUM 20 // 最大顶点数
|
||||
|
||||
template <class DT>
|
||||
struct MGraph // 图的邻接矩阵表示存储定义
|
||||
{
|
||||
DT vexs[MAX_VEXNUM]; // 顶点信息
|
||||
int arcs[MAX_VEXNUM][MAX_VEXNUM];
|
||||
int vexnum,arcnum; // 顶点数和边数
|
||||
};
|
||||
|
||||
|
||||
template <class DT>
|
||||
void DispG(MGraph<DT> G) // 显示图信息
|
||||
{
|
||||
int i,j;
|
||||
DT u,v;
|
||||
cout<<G.vexnum<<"个顶点:"<<endl;
|
||||
for(i=0;i<G.vexnum;i++)
|
||||
cout<<G.vexs[i]<<" ";
|
||||
cout<<endl;
|
||||
cout<<G.arcnum<<"条边信息如下:"<<endl;
|
||||
for(i=0;i<G.vexnum;i++)
|
||||
{
|
||||
for(j=i+1;j<G.vexnum;j++)
|
||||
if (G.arcs[i][j]!=0)
|
||||
{
|
||||
GetVex(G,i,u);
|
||||
GetVex(G,j,v);
|
||||
cout<<'('<<u<<","<<v<<")"<<'\t';
|
||||
}
|
||||
}
|
||||
cout<<endl;
|
||||
}
|
||||
|
||||
|
||||
//算法6.1 顶点定位
|
||||
template <class DT>
|
||||
int LocateVex(MGraph<DT> G,DT v)
|
||||
{
|
||||
for(int i = 0;i<G.vexnum;i++)
|
||||
{
|
||||
if(G.vexs[i] == v)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//6.2 创建无向图
|
||||
template <class DT>
|
||||
void CreateUDG(MGraph<DT> &G)
|
||||
{
|
||||
int i,j,k;
|
||||
DT v1,v2;
|
||||
cout<<"请输入无向图的顶点数 "; // 1. 输入顶点数、边数
|
||||
cin>>G.vexnum ;
|
||||
cout<<"请输入无向图的边数 ";
|
||||
cin>>G.arcnum ;
|
||||
cout<<"请输入"<<G.vexnum<<"个顶点的值(单个字符)"<<endl; // 2. 输入顶点值
|
||||
for(i = 0;i<G.vexnum;i++)
|
||||
cin>>G.vexs[i];
|
||||
for(i=0;i<G.vexnum;i++) // 3.邻接矩阵初始化
|
||||
for(j=0;j<G.vexnum;j++)
|
||||
G.arcs[i][j]=0;
|
||||
cout<<"请输入各条边的两个邻接点"<<endl; // 4.创建各条边
|
||||
for( k=0;k<G.arcnum;k++)
|
||||
{
|
||||
cout<<"输入第"<<k<<"条边的两个顶点:"<<endl;
|
||||
cin>>v1>>v2; // 4.1 输入边的两个邻接点
|
||||
i = LocateVex(G,v1); // 4.2 定位两个邻接点
|
||||
j = LocateVex(G,v2);
|
||||
if(i<0 || j<0 || i==j)
|
||||
{
|
||||
cout<<"顶点信息错,重新输入!"<<endl;
|
||||
k--;
|
||||
continue;
|
||||
}
|
||||
G.arcs[i][j]=1; // 4.3 修改邻接矩阵
|
||||
G.arcs[j][i]=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class DT>
|
||||
bool GetVex(MGraph<DT> G, int k, DT &v) // 获取第 u 个顶点值v
|
||||
{
|
||||
if(k<0 || k>=G.vexnum) // u不存在,返回false
|
||||
return false;
|
||||
else
|
||||
{
|
||||
v=G.vexs[k];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class DT>
|
||||
bool PutVex(MGraph<DT> &G,DT &u,DT v) // 为第u个顶点赋值
|
||||
{
|
||||
int k;
|
||||
k=LocateVex(G,u);
|
||||
if(k<0 ) // u不存在,返回false
|
||||
return false;
|
||||
else // u存在,赋值
|
||||
{
|
||||
G.vexs[k] = v;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//算法6.3 按值查找第一邻接点
|
||||
template <class DT>
|
||||
int FirstAdjvex(MGraph<DT> G,int u)
|
||||
{
|
||||
if(u<0 || u>=G.vexnum) // 顶点不存在
|
||||
return -1; // 无邻接点,返回-1
|
||||
for(int j=0;j<G.vexnum;j++) // 扫描邻接矩阵第u行
|
||||
if(G.arcs[u][j]!=0) // 如果有非零元,
|
||||
return j; // 第一个非零元所在列号,为其邻接点序号
|
||||
return -1; // 否则,无邻接点,返回-1
|
||||
}
|
||||
|
||||
template <class DT>
|
||||
int NextAdjvex(MGraph<DT> G,int u,int w) //查找第u个顶点邻接点W的下一个邻接点
|
||||
{
|
||||
if(u<0 || u>=G.vexnum || w<0
|
||||
|| w>=G.vexnum || G.arcs[u][w]==0 ) // 参数不合理
|
||||
return -1; // 无邻接点
|
||||
for(int j=w+1;j<G.vexnum;j++) // 扫描邻接矩阵第u行w列后的元素
|
||||
if(G.arcs[u][j]!=0) // 如果有非零元,
|
||||
return j; // 第一个非零元所在列号,为其邻接点序号
|
||||
return -1; // 否则无邻接点,返回-1
|
||||
}
|
||||
|
||||
|
||||
template <class DT>
|
||||
bool InsertVex(MGraph<DT> &G,DT v) // 插入值为v的顶点
|
||||
{
|
||||
DT w;
|
||||
int j;
|
||||
char ans;
|
||||
if(G.vexnum>=MAX_VEXNUM) // 无存储空间,不能插入
|
||||
{
|
||||
cout<<"无存储空间,不能插入!"<<endl;
|
||||
return false;
|
||||
}
|
||||
G.vexs[G.vexnum++]= v; // 顶点信息加入至G.vexs中,顶点数增1
|
||||
for(j=0;j<G.vexnum;j++) // 初始化邻接矩阵最后一行和最后一列值
|
||||
{
|
||||
G.arcs[G.vexnum-1][j]=0;
|
||||
G.arcs[j][G.vexnum-1]=0;
|
||||
}
|
||||
cout<<"创建边吗(Y/N)?"<<endl;
|
||||
cin>>ans;
|
||||
while(ans=='Y'|| ans=='y')
|
||||
{
|
||||
cout<<"输入另一个顶点值"<<endl;
|
||||
cin>>w;
|
||||
j=LocateVex(G,w);
|
||||
if(j>=0) // 顶点存在
|
||||
InsertArc(G,v,w);
|
||||
else
|
||||
cout<<w<<"顶点不存在!";
|
||||
cout<<"继续创建边吗(Y/N)?"<<endl;
|
||||
cin>>ans;
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class DT>
|
||||
bool InsertArc(MGraph<DT> &G,DT v,DT w) // 在值为v、w顶点间加边
|
||||
{ int i = LocateVex(G,v);
|
||||
int j = LocateVex(G,w);
|
||||
if(i<0 || j<0 || i==j) // 顶点不存在或两端点相同
|
||||
return false; // 不能插入边,返回false
|
||||
G.arcs[i][j]=1;
|
||||
G.arcs[j][i]=1;
|
||||
G.arcnum++;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class DT>
|
||||
bool DeleteArc(MGraph<DT> &G,DT v,DT w) // 按顶点值删除边
|
||||
{
|
||||
int i = LocateVex(G,v);
|
||||
int j = LocateVex(G,w);
|
||||
if(i<0||j<0||i == j) // 边不存在,返回false
|
||||
{
|
||||
cout<<"边不存在!"<<endl;
|
||||
return false;
|
||||
}
|
||||
G.arcs[i][j]=0; // 置邻接矩阵第 i 行第 j 列为零
|
||||
G.arcs[j][i]=0; // 置邻接矩阵第 i 列第 j 行为零
|
||||
G.arcnum--; // 边数减1
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class DT>
|
||||
bool DeleteVex(MGraph<DT> &G,DT v) // 按值删除顶点
|
||||
{
|
||||
int i,j;
|
||||
DT w;
|
||||
i = LocateVex(G,v); // 顶点定位
|
||||
if(i<0)
|
||||
{
|
||||
cout<<"顶点不存在!"<<endl; // 顶点不存在
|
||||
return false;
|
||||
}
|
||||
for(j=0;j<G.vexnum;j++) // 删除与顶点v相连的边
|
||||
{
|
||||
if(G.arcs[i][j]!=0)
|
||||
{
|
||||
GetVex(G,j,w);
|
||||
DeleteArc(G,v,w);
|
||||
}
|
||||
}
|
||||
for(j=i+1;j<G.vexnum;j++) // 排在顶点v后面的顶点前移
|
||||
{
|
||||
G.vexs[j-1] = G.vexs[j];
|
||||
}
|
||||
G.vexnum--;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// 算法6.10
|
||||
template <class DT>
|
||||
void DFS2(MGraph<DT> G,int v) // 连通图深度优先遍历
|
||||
{
|
||||
int w;
|
||||
visited[v] = true; // 先访问index
|
||||
//cout<<G.vexs[v];
|
||||
for(w=0;w<G.vexnum;w++)
|
||||
{
|
||||
if(G.arcs[v][w]!=0 && !visited[w] )
|
||||
DFS2(G,w);
|
||||
}
|
||||
}
|
||||
|
||||
// 算法6.9
|
||||
template <class DT>
|
||||
void DFSTraverse(MGraph<DT> G) // 非连通图深度优先遍历
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<G.vexnum;i++) // 访问标志初始化
|
||||
visited[i]=0;
|
||||
for( i=0;i<G.vexnum;i++) // 对未被访问的顶点
|
||||
{
|
||||
if(!visited[i])
|
||||
DFS2(G,i); // 进行深度优先递归
|
||||
}
|
||||
cout<<endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
// 算法 6.11 广度优先遍历
|
||||
template <class DT>
|
||||
void BFS(MGraph<DT> G,int v)
|
||||
{
|
||||
int w;
|
||||
LinkQueue<int> Q; // 创建一个队列
|
||||
InitQueue(Q);
|
||||
cout<<G.vexs[v]; // 访问顶点v
|
||||
visited[v]=true; // 做访问标志
|
||||
EnQueue(Q,v); // 入队
|
||||
while(!QueueEmpty(Q)) // 队非空
|
||||
{
|
||||
DeQueue(Q,v); // 出队
|
||||
for(w=FirstAdjvex(G,v);w>=0;w=NextAdjvex(G,v,w)) // 遍历v的邻接点
|
||||
if(!visited[w]) // 未被访问
|
||||
{
|
||||
cout<<G.vexs[w]; // 访问
|
||||
visited[w]=true; // 做访问标志
|
||||
EnQueue(Q,w); // 入队
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 算法6.12
|
||||
template <class DT>
|
||||
void BFSTraverse(MGraph<DT> G) // 广度优先遍历
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<G.vexnum;i++) // 访问标志初始化
|
||||
visited[i]=false;
|
||||
for(i=0;i<G.vexnum;i++) // 对未被访问的结点
|
||||
{
|
||||
if(!visited[i])
|
||||
BFS(G,i); // 进行BFS遍历
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user