学校的校园景点平面图(校园景点迷你地图C++&数据结构)

学校的校园景点平面图(校园景点迷你地图C++&数据结构)

设计要求:

(1)建图
以图中顶点表示主要景点,并存放景点的编号、名称、简介等信息;
(2)查询
该系统可以查询景点的信息;
查询图中任意两个景点间的最短路径;
查询图中所有景点间的最短路径;
查询图中任意两个景点间的所有路径。
(3)更新
更新景点间路径长度;
在两个景点之间添加一条路径;
删除两个景点之间的一条路径;
增添一个景点;
去除一个景点;
更改景点的简介。

功能实现

(1)建图
首先画出所要建立的地图的形象版
在这里插入图片描述
为了方便使用图论的知识来完成上述所要实现的功能,将这个形象图抽象化,变成图:
在这里插入图片描述
邻接矩阵1:(由createMTGraph()函数建立的邻接矩阵)
在这里插入图片描述
邻接矩阵2:(由createMTGraph1()函数建立的邻接矩阵)
在这里插入图片描述
接下来使用数据结构的知识用编程语言表示这个图:

#define numedges 100     //最大边数 
#define numvertices 13 //最大顶点个数 

typedef string vertexdata; //顶点数据类型
typedef int  edgedata;   //边上权值类型
typedef int *listofnode; 
typedef struct node{
	vertexdata verlist[numvertices]; //顶点表,verlist[i]类型为string,存放顶点名称
	vertexdata info[numvertices];//存放顶点简介
	edgedata edge[numvertices][numvertices]; //邻接矩阵--边表,可视为边之间的关系,存放权值
	int n,e;//图中当前的顶点个数与边数 
}MTGraph; 

这是使用邻接矩阵表示有向图。
注:为什么刚才抽象出来的图是无向图,而我要使用有向图呢?
因为分析这个地图要实现的功能,有“查询图中任意两个景点间的最短路径; 查询图中所有景点间的最短路径;查询图中任意两个景点间的所有路径。”,这些功能一定会用到那个著名的算法:Floyd算法,而这个算法是要求使用有向图的;而且使用邻接矩阵表示的图,无论是有向图还是无向图,都是可以互相转化的,简单地说就是:双向有向图==无向图,即把有向图每对顶点之间的有向边都变为两条方向相反的有向边!这也不会费多少功夫和资源。

(2)对该图的一些基本操作:

//判断两个顶点之间是否有边 
bool isEdge(MTGraph &G,int v1,int v2){
	return G.edge[v1][v2]!=INF;
}

//创建一个新的顶点 
void newnode(MTGraph &G,vertexdata v){
	G.verlist[G.n]=v;//G.n=11
	G.n++;//G.n=12
	for(int i=0;i<G.n+1;i++){//i<12  (i:0~11)
		G.edge[G.n-1][i]=INF;
		G.edge[i][G.n-1]=INF;
	}
} 

//更改两个景点v1,v2之间的路径长度为juli
void chg(MTGraph &G,int v1,int v2,int juli){
	if(isEdge(G,v1,v2)){
		int temp=G.edge[v1][v2];
		G.edge[v1][v2]=juli;
		G.edge[v2][v1]=juli;
		cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间的路径长度从"<<temp<<"更改为"<<juli<<endl;
	}
	else{
		cout<<"这两个景点之间没有直接路径,更新失败!"<<endl;
		//return;
	}
	
}

//删除一个顶点 
void delnode(MTGraph &G,int v){
	int i,j;
	for(i=0;i<G.n;i++)
		if(G.edge[v][i]!=INF){
			G.edge[v][i]=INF;
			G.edge[i][v]=INF;	
			G.e==G.e-2;
		}// 删除一个顶点 之后表示该图的邻接矩阵 也会改变 
		for(i=v+1;i<G.n;i++)//行 
			for(j=0;j<G.n;j++)//列 
				G.edge[i-1][j]=G.edge[i][j];	
		for(i=v+1;i<G.n;i++)//列 
			for(j=0;j<G.n-1;j++)//行 
				G.edge[j][i-1]=G.edge[j][i];
		for(i=v+1;i<G.n;i++)
			G.verlist[i-1]=G.verlist[i];
		G.n--;
}


//添加1条V1->V2的有向边(建立图时用)
void setsucc1(MTGraph &G,int v1,int v2,int w){
	if(isEdge(G,v1,v2))
		return;
	G.e++;
	G.edge[v1][v2]=w;
	//G.edge[v2][v1]=w;
}


//在V1和V2这两个景点之间添加一条路径(添加路径时用)
void setsucc2(MTGraph &G,int v1,int v2,int w){
	if(isEdge(G,v1,v2)){
		cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间已经存在路径,不需要在添加路径!"<<endl;
		return;
	}
	G.e++;
	G.edge[v1][v2]=w;
	G.edge[v2][v1]=w;
	cout<<"成功在"<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间添加一条长度为"<<w<<"的路径"<<endl;
}

//删除V1->V2的和V2->V1的边;删除V1和V2这两个景点之间的一条路径
void delsucc(MTGraph &G,int v1,int v2){
	if(!isEdge(G,v1,v2)){
		cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间不存在路径,不需要在删除路径!"<<endl;
		return;
	}
	int temp=G.edge[v1][v2];
	G.e--;
	G.edge[v1][v2]=INF;
	G.edge[v2][v1]=INF; 
	//G.edge[v1][v2]=0;
	//G.edge[v2][v1]=0; 
	cout<<"成功删除"<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间一条长度为"<<temp<<"的路径"<<endl;
} 

//v的直接后继 
int *succ(MTGraph G,int v){
	int *ret=new int[numvertices];
	int i,k;
	for(i=0;i<G.n;i++){
		if(G.edge[v][i])
			ret[k++]=i;
	}
	ret[k]=-1;
	return ret;
}

//v的直接前驱 
int *pre(MTGraph G,int v){
	int *ret=new int[numvertices];
	int i,k;
	for(i=0;i<G.n;i++){
		if(G.edge[i][v])
			ret[k++]=i;
	}
	ret[k]=-1;
	return ret;
}

建图函数:
1.

//构建图之1,包括表示该图的邻接矩阵(元素由INF和每对顶点间的路径长度组成),图中顶点的名称和简介
void createMTGraph(MTGraph &G){
//	int i,j,x,y,e,w;
	int i,j,n=11,e=30,x,y,w;
	//int i,j,n=3,e=6,x,y,w;
	//memset(G.edge,0,sizeof(G.edge));
	for(i=0;i<numvertices;i++)
		for(j=0;j<numvertices;j++)
			G.edge[i][j]=INF;
	/*cout << "请输入图中当前的顶点个数:";
	cin>>n;//n=11
	G.n=n;
	cout <<endl;
	cout << "请输入图中当前的边数:";
	cin>>e;//e=30
	//G.e=e;*/
	G.n=n;
	/*
	for(i=0;i<n;i++){
		cout << "请输入顶点"<<i<<"的名称:";
		cin>>G.verlist[i];//顶点表,verlist[i]类型为string,存放顶点名称
		cout << "请输入顶点"<<i<<"的简介:";
		cin>>G.info[i];//存放顶点简介
	}*/
	
	
	vertexdata str1[13]={"大门","厚学楼","浦江","操场","大礼堂","宿舍","西苑","沉毅广场","镜湖","东苑","图书馆"};
	for(int i=0;i<13;i++){
		G.verlist[i]= str1[i];
	}		
	 //存放景点简介的字符串数组 
	vertexdata str2[13]={"大门是南京工业大学的门面招牌,气势恢宏!","厚学楼是学习圣地,在这里总是能看到莘莘学子发奋苦读的情景!",
	"浦江是美食天堂,这里有各式各样的特色美食!","操场十分辽阔整洁,是学生放松锻炼的好地方!","大礼堂是学校举办各种文艺演出的地方,周末还会放电影哟!",
	"宿舍是学生们休息,娱乐,学习的地方!","西苑景色很美,有绿水,有大树,还有一个很时尚的网红餐厅!","沉毅广场也是学校的一大门面担当,那个古老的大铜鼎更是令人赞叹!",
	"镜湖很美,水面辽阔,平静如镜,还有荷花!","东苑有一个拥有穹顶的食堂,很有艺术感,还上过电视哦!","图书馆是个知识宝库,里面的学生也是络绎不绝!"};
	for(int i=0;i<13;i++){
		G.info[i]= str2[i];
	}
	
	//景点平面图的邻接矩阵
	edgedata edge1[13][13]={ 
			{INF,50,INF,INF,60,INF,INF,INF,INF,INF,INF,INF,INF},
			{50,INF,80,INF,80,INF,INF,40,INF,INF,INF,INF,INF},
			{INF,80,INF,20,INF,INF,INF,INF,INF,INF,INF,INF,INF},
			{INF,INF,20,INF,INF,INF,INF,160,INF,INF,INF,INF,INF},
			{60,80,INF,INF,INF,60,INF,INF,INF,INF,INF,INF,INF},
			{INF,INF,INF,INF,60,INF,120,280,INF,INF,INF,INF,INF},
			{INF,INF,INF,INF,INF,120,INF,INF,INF,100,INF,INF,INF},
			{INF,40,INF,160,INF,280,INF,INF,500,INF,400,INF,INF},
			{INF,INF,INF,INF,INF,INF,INF,500,INF,300,200,INF,INF},
			{INF,INF,INF,INF,INF,INF,100,INF,300,INF,INF,INF,INF},
			{INF,INF,INF,INF,INF,INF,INF,400,200,INF,INF,INF,INF}
			};
	for(int i=0;i<13;i++){//我用上面的二维数组代替此地图初始化的过程 ,不会破坏其可拓展性 ,而且不用每次运行程序都手动输入一遍邻接矩阵 
		for(int j=0;j<13;j++){//想换一个地图就只要更改这个邻接矩阵即可 
			G.edge[i][j]=edge1[i][j];
		}
	}
	/*
	for(i=0;i<e;i++){//void setsucc(MTGraph &G,int v1,int v2,int w)在改变G的e(G.e),,怪不得一直输入起点终点无法退出
		cout << "请输入起点:";
		cin>>x;
		cout << "请输入终点:";
		cin>>y;
		cout << "请输入权值:";
		cin>>w;
		setsucc1(G,x,y,w);//e为奇数时要这样建立图,每条边都要输入一遍,要输入e对顶点
	}
	*/
	/*for(i=0;i<e/2;i++){//void setsucc(MTGraph &G,int v1,int v2,int w)在改变G的e(G.e),,怪不得一直输入起点终点无法退出
		cout << "请输入起点:";
		cin>>x;
		cout << "请输入终点:";
		cin>>y;
		cout << "请输入权值:";
		cin>>w;
		setsucc(G,x,y,w);
		setsucc(G,y,x,w);//e为偶数时可以这样建立图,输入一半的边即可,只要输入e/2对顶点
	}*/
}
//构建图之2(改变了邻接矩阵的表示:有边G.edge[i][j]==1,没有边G.edge[i][j]==INF),这个建图函数是为了服务功能10:查询图中任意两个景点间的所有路径 
void createMTGraph1(MTGraph &G){
//	int i,j,x,y,e,w;
	int i,j,n=11,e=30,x,y,w;
	//int i,j,n=3,e=6,x,y,w;
	//memset(G.edge,0,sizeof(G.edge));
	for(i=0;i<numvertices;i++)
		for(j=0;j<numvertices;j++)
			G.edge[i][j]=INF;
	
	G.n=n;
	
	vertexdata str1[13]={"大门","厚学楼","浦江","操场","大礼堂","宿舍","西苑","沉毅广场","镜湖","东苑","图书馆"};
	for(int i=0;i<13;i++){
		G.verlist[i]= str1[i];
	}		
	 //存放景点简介的字符串数组 
	vertexdata str2[13]={"大门是南京工业大学的门面招牌,气势恢宏!","厚学楼是学习圣地,在这里总是能看到莘莘学子发奋苦读的情景!",
	"浦江是美食天堂,这里有各式各样的特色美食!","操场十分辽阔整洁,是学生放松锻炼的好地方!","大礼堂是学校举办各种文艺演出的地方,周末还会放电影哟!",
	"宿舍是学生们休息,娱乐,学习的地方!","西苑景色很美,有绿水,有大树,还有一个很时尚的网红餐厅!","沉毅广场也是学校的一大门面担当,那个古老的大铜鼎更是令人赞叹!",
	"镜湖很美,水面辽阔,平静如镜,还有荷花!","东苑有一个拥有穹顶的食堂,很有艺术感,还上过电视哦!","图书馆是个知识宝库,里面的学生也是络绎不绝!"};
	for(int i=0;i<13;i++){
		G.info[i]= str2[i];
	}
	
	//景点平面图的邻接矩阵
	edgedata edge1[13][13]={ 
			{INF,1,INF,INF,1,INF,INF,INF,INF,INF,INF,INF,INF},
			{1,INF,1,INF,1,INF,INF,1,INF,INF,INF,INF,INF},
			{INF,1,INF,1,INF,INF,INF,INF,INF,INF,INF,INF,INF},
			{INF,INF,1,INF,INF,INF,INF,1,INF,INF,INF,INF,INF},
			{1,1,INF,INF,INF,1,INF,INF,INF,INF,INF,INF,INF},
			{INF,INF,INF,INF,1,INF,1,1,INF,INF,INF,INF,INF},
			{INF,INF,INF,INF,INF,1,INF,INF,INF,1,INF,INF,INF},
			{INF,1,INF,1,INF,1,INF,INF,1,INF,1,INF,INF},
			{INF,INF,INF,INF,INF,INF,INF,1,INF,1,1,INF,INF},
			{INF,INF,INF,INF,INF,INF,1,INF,1,INF,INF,INF,INF},
			{INF,INF,INF,INF,INF,INF,INF,1,1,INF,INF,INF,INF}
			};
	for(int i=0;i<13;i++){//我用上面的二维数组代替此地图初始化的过程 ,不会破坏其可拓展性 ,而且不用每次运行程序都手动输入一遍邻接矩阵 
		for(int j=0;j<13;j++){//想换一个地图就只要更改这个邻接矩阵即可 
			G.edge[i][j]=edge1[i][j];
		}
	}
	
}

(3)各种功能的实现
1.查询景点的信息;

//查询景点v的信息(简介)
void printinfo(MTGraph g,int v){
	//if
	cout<<"景点"<<g.verlist[v]<<"的简介:"<<g.info[v]<<endl;
}

在main()函数中对应着case 1:

case 1:
			int x1;
			cout<<"请输入想要查询信息的景点的代号:";
			cin>>x1;
			cout<<endl;
			printinfo(g,x1);
			break;

2.查询图中任意两个景点间的最短路径;
该功能由Floyd算法和配合Floyd算法使用的输出函数组成:

//求图中任意两个景点间的最短路径---Floyd算法 
void floyd(MTGraph g,int d[numvertices][numvertices],int p[numvertices][numvertices]){
	int i,j,k;
	for(i=0;i<g.n;i++){
		for(j=0;j<g.n;j++){
			d[i][j]=g.edge[i][j];
			p[i][j]=-1;
		}
	}
	for(k=0;k<g.n;k++)
		for(i=0;i<g.n;i++)
			for(j=0;j<g.n;j++){
				if(d[i][j]>d[i][k]+d[k][j]){
					d[i][j]=d[i][k]+d[k][j];
					p[i][j]=k;
				}
			}	
}//O(g.n^3) 


//输出U->V的最短路径
void printpath(MTGraph g,int p[numvertices][numvertices],int u, int v){
	int k;
	if(p[u][v]==-1){
		cout<<"<"<<g.verlist[u]<<"--->"<<g.verlist[v]<<">";
		return;
	}
	k=p[u][v];
	printpath(g,p,u,k);
	printpath(g,p,k,v);		
}

在main()函数中对应着case 2:

case 2:
			floyd(g,d,p);
			cout<<"请输入想要查询最短路径的两个景点的编号:"<<endl;
			cin>>v1>>v2; 
			cout<<g.verlist[v1]<<"和"<<g.verlist[v2]<<"之间的最短路径为:"<<endl;
			cout<<setiosflags(ios::left)<<g.verlist[v1]<<"->"<<g.verlist[v2]<<":"; 
			printpath(g,p,v1,v2);
			cout<<"      ";
			cout<<"该路径的长度为:"<<d[v1][v2]<<"米"<<endl;				
			break;

3.查询图中所有景点间的最短路径;
该功能也是由Floyd算法和配合Floyd算法使用的输出函数组成,只是不止输出要查询的2个顶点之间的最短路径,而是输出每对顶点的:
在main()函数中对应着case 3:

case 3:
			floyd(g,d,p);
			cout<<"每对顶点之间最短路径为:"<<endl;
				for(i=0;i<g.n;i++){
					for(j=0;j<g.n;j++){
						if(d[i][j]==INF)
							continue;
						else{
							if(i!=j){//&&g.egdge[i][j]!=INF
								//cout<<setiosflags(ios::left)<<i<<g.verlist[i]<<"->"<<j<<g.verlist[j]<<":"; 
								cout<<setiosflags(ios::left)<<g.verlist[i]<<"->"<<g.verlist[j]<<":"; 
								printpath(g,p,i,j);
								cout<<endl;
							}
						}		
					}  
				} 
			break;

4.查询图中任意两个景点间的所有路径;
这个功能应该是对我来说最烧脑的一个,它是我最后实现的一个功能,所以我把它放在了case 10;
首先在mian()函数开头定义好case 10中要使用的变量并把图建好:

int main(){
	int i,j;
	int start_num;//起点编号 
	int node_num;//终点编号 
	int d[numvertices][numvertices],p[numvertices][numvertices];//,a[numvertices][numvertices]
	MTGraph g;
	MTGraph g1;
	createMTGraph(g);//建立图 g
	createMTGraph1(g1);//建立图 g1

接着去case 10中编写"求图中任意两个景点间的所有路径"的算法:

case 10:{ 
			bool is_in_stack[numvertices];
			is_in_stack[numvertices]={0};
			stack<int>node_stack;
			int c_position;
			c_position = 0;
			vector<vector<int> >paths;//存储所有路径
			vector<int>path;//存储单条路径
			cout<<"请输入想要查询所有路径的两个景点的编号:"<<endl;
			cin>>start_num>>node_num; //start_num和node_num可取0~10 ,但最好不要一样 
			
			cout<<g.verlist[start_num]<<"和"<<g.verlist[node_num]<<"之间的所有路径为:"<<endl;
															//思考过程 
															//先测试从0--->10的所有路径 
															//已然解决了,横空出世! 
															//接下来看看任意两点之间的所有路径 
															//完美! 
															//还有瑕疵,就是 起点编号要小于终点 
															//又一个瑕疵,连续使用10号功能就会输出不变 ,现在也解决了 
			//起点入栈
		    node_stack.push(start_num);
		    is_in_stack[0] = 1;//设置起点已入栈,1表示在栈中,0 表示不在
		    int top_element;//记录栈顶元素
		    int tmp;
		    while (!node_stack.empty())
		    {
		        top_element = node_stack.top();//查看栈顶元素,判断是否已经到达终点
		        if (top_element == node_num)//若到达终点,输出路径,弹出栈中两个点,设置出栈状态
		        {
		            while (!node_stack.empty())
		            {
		                tmp = node_stack.top();
		                node_stack.pop();
		                path.push_back(tmp);
		            }
		            paths.push_back(path);//将路径加入路径组
		            for (vector<int>::reverse_iterator rit = path.rbegin(); rit != path.rend(); rit++)
		            {
		                node_stack.push(*rit);
		            }
		            path.clear();//清除单条路径
		
		            node_stack.pop();
		            is_in_stack[top_element] = 0;
		            c_position = node_stack.top();//记录位置,以便从该位置之后进行搜索
		            top_element = node_stack.top();
		            node_stack.pop();
		            is_in_stack[top_element] = 0; //cout << vis[top_element];
		        }
		        else
		        {
		            int i = 0;
		            for (i = c_position + 1; i <node_num + 2; i++)
		            {
		
		                if (is_in_stack[i] == 0 && g1.edge[top_element][i] != INF)//未入栈,而且节点之间有边相连
		                {
		
		                    is_in_stack[i] = 1;//stack In
		                    node_stack.push(i);//入栈
		                    c_position = 0;//位置置零,是因为从记录的位置开始搜索完以后,在新的行上搜索,自然从零开始,以免漏掉节点
		                    break;
		                }
		            }
		            if (i == node_num + 2)
		            {
		                top_element = node_stack.top();
		                is_in_stack[top_element] = 0;
		                c_position = node_stack.top();
		                node_stack.pop();
		            }
		        }
		    }
		    //========================  输出 ==========================
		    //逆向
		    for (int i = 0; i <paths.size(); i++)
		    {
		        cout << "路径" << i << ": ";
		        for (int j = paths[i].size()-1; j >=0; j--)
		        {
		            if (j == 0)
		            {
		                //cout << paths[i][j];
		                cout << g1.verlist[ paths[i][j] ];
		            }
		            else
		            {
		                //cout << paths[i][j] << "->";
		                cout << g1.verlist[ paths[i][j] ] << "->";
		            }
		
		        }
		        cout << endl;
		    }
		    //========================  输出 ==========================		
			break;} 

5.更新景点间路径长度;

//更改两个景点v1,v2之间的路径长度为juli
void chg(MTGraph &G,int v1,int v2,int juli){
	if(isEdge(G,v1,v2)){
		int temp=G.edge[v1][v2];
		G.edge[v1][v2]=juli;
		G.edge[v2][v1]=juli;
		cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间的路径长度从"<<temp<<"更改为"<<juli<<endl;
	}
	else{
		cout<<"这两个景点之间没有直接路径,更新失败!"<<endl;
		//return;
	}
	
}

在main()函数中对应着case 4:

case 4:
			//int v1,v2,w;
			cout<<"请输入想要更新路径长度的两个景点的编号:"<<endl;
			cin>>v1>>v2;
			if(!isEdge(g,v1,v2)){
				cout<<"这两个景点之间没有直接路径,更新失败!"<<endl;
				break;
			}
			cout<<"请输入想要设置的新路径长度:";
			cin>>w;
			chg(g,v1,v2,w);
			break;

6.在两个景点之间添加一条路径;

//在V1和V2这两个景点之间添加一条路径(添加路径时用)
void setsucc2(MTGraph &G,int v1,int v2,int w){
	if(isEdge(G,v1,v2)){
		cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间已经存在路径,不需要在添加路径!"<<endl;
		return;
	}
	G.e++;
	G.edge[v1][v2]=w;
	G.edge[v2][v1]=w;
	cout<<"成功在"<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间添加一条长度为"<<w<<"的路径"<<endl;
}

在main()函数中对应着case 5:

case 5:
			//int v1,v2,w;
			cout<<"请输入想要添加路径的两个景点的编号:"<<endl;
			cin>>v1>>v2;
			if(isEdge(g,v1,v2)){
				cout<<g.verlist[v1]<<"和"<<g.verlist[v2]<<"这两个景点之间已经存在路径,不需要在添加路径!"<<endl;
				break;
			}
			cout<<"请输入想想要添加的路径的长度:";
			cin>>w;
			setsucc2(g,v1,v2,w);
			break;

7.删除两个景点之间的一条路径;

//删除V1->V2的和V2->V1的边;删除V1和V2这两个景点之间的一条路径
void delsucc(MTGraph &G,int v1,int v2){
	if(!isEdge(G,v1,v2)){
		cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间不存在路径,不需要在删除路径!"<<endl;
		return;
	}
	int temp=G.edge[v1][v2];
	G.e--;
	G.edge[v1][v2]=INF;
	G.edge[v2][v1]=INF; 
	//G.edge[v1][v2]=0;
	//G.edge[v2][v1]=0; 
	cout<<"成功删除"<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间一条长度为"<<temp<<"的路径"<<endl;
} 

在main()函数中对应着case 6:

case 6:
			//int v1,v2;
			cout<<"请输入想要删除路径的景点的编号:"<<endl;
			cin>>v1>>v2;
			//删除V1->V2的和V2->V1的边;删除V1和V2这两个景点之间的一条路径
			delsucc(g,v1,v2);
			break;

8.增添一个景点;

//创建一个新的顶点 ,并且为这个新顶点设置编号为G.n 
void newnode(MTGraph &G,vertexdata v){
	G.verlist[G.n]=v;//G.n=11
	G.n++;//G.n=12
	for(int i=0;i<G.n+1;i++){//i<12  (i:0~11)
		G.edge[G.n-1][i]=INF;
		G.edge[i][G.n-1]=INF;
	}
} 

在main()函数中对应着case 7:

case 7://要改进 
			//string temp;
			cout<<"请输入想要增添的景点的名称:";
			cin>>temp;
			newnode(g,temp); 
			cout<<"成功增添景点:"<<temp<<"  ";
			cout<<"该景点的编号为:"<<g.n-1<<endl;
			break;

9.去除一个景点;

//删除一个顶点 
void delnode(MTGraph &G,int v){
	int i,j;
	for(i=0;i<G.n;i++)
		if(G.edge[v][i]!=INF){
			G.edge[v][i]=INF;
			G.edge[i][v]=INF;	
			G.e==G.e-2;
		}// 删除一个顶点 之后表示该图的邻接矩阵 也会改变 
		for(i=v+1;i<G.n;i++)//行 
			for(j=0;j<G.n;j++)//列 
				G.edge[i-1][j]=G.edge[i][j];	
		for(i=v+1;i<G.n;i++)//列 
			for(j=0;j<G.n-1;j++)//行 
				G.edge[j][i-1]=G.edge[j][i];
		for(i=v+1;i<G.n;i++)
			G.verlist[i-1]=G.verlist[i];
		G.n--;
}

在main()函数中对应着case 8:

case 8://删除顶点之后,其他顶点的编号会改变 
			//int v;
			//string temp;
			temp=g.verlist[v];
			cout<<"请输入想要去除的景点的编号:";
			cin>>v;	
			delnode(g,v);
			cout<<"成功去除景点:"<<temp<<"  ";
			cout<<"该景点原来的编号为:"<<v<<endl;
			break;

10.更改景点的简介;

//更改景点的简介 
void ch (MTGraph &g,int v,vertexdata temp){
	g.info[v]=temp;
}

在main()函数中对应着case 9:

case 9:
			//int v;
			cout<<"请输入想要更改简介的景点的编号:";
			cin>>v;	
			temp1=g.verlist[v];
			cout<<"请输入想要设置的新简介:";
			cin>>temp;
			ch (g,v,temp); 
			cout<<"成功将景点:"<<temp1<<"的简介改为:"<<temp<<endl;
			break;

至此,10个功能都已实现。
运行截图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个程序是我学习计算机以来感觉最有趣的一个,完成它我确实费了不少周折,有几个功能的实现对现在的我来说着实烧脑,但越是困难我越是想把它做出来,也正是这些困难,将我通过努力获得成功时的快乐放大了。

  • 31
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值