圖的基本運算及智慧交通中的最佳路徑選擇問題(實驗三)
阿新 • • 發佈:2019-01-24
1.編寫程式,實現鄰接矩陣的初始化、撤銷、邊的搜尋、插入、刪除等操作
/*資料結構實驗三
完成鄰接矩陣的初始化,撤銷,邊的搜尋,插入,刪除等操作 */
#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef struct{
ElemType **a; //鄰接矩陣
int n; //圖的頂點數
int e; //圖當前的邊數
ElemType noEdge; //兩頂點無邊時的值
}mGraph;
//初始化,nSize頂點數,noEdgeValue無邊的值
int Init(mGraph *mg,int nSize,ElemType noEdgeValue){
int i,j;
mg->n=nSize;
mg->e=0; //初始化沒有邊
mg->noEdge=noEdgeValue;
mg->a=(ElemType**)malloc(nSize*sizeof(ElemType*)); //生成長度為n的一維陣列指標
if(!mg->a) return 0;
for(int i=0;i<mg->n;i++){
mg->a[i]=(ElemType*)malloc (nSize*sizeof(ElemType));
for(j=0;j<mg->n;j++) mg->a[i][j]=mg->noEdge;
mg->a[i][i]=0; //自迴路設定為0
}
return 1;
}
//撤銷操作,撤銷的時候順序不能變,先釋放指標陣列就會找不到陣列指標啦
int Destory(mGraph *mg){
int i;
for(int i=0;i<mg->n;i++) free(mg->a[i]); //釋放n個一維陣列儲存空間
free(mg->a); //釋放n個一維指標陣列的儲存空間
return 1;
}
//邊的搜尋操作,判斷邊在不在圖中
int Exist(mGraph *mg,int u,int v){
if(u<0||v<0||u>mg->n-1||v>mg->n-1||u==v||mg->a[u][v]==mg->noEdge){
cout<<"這條邊不存在."<<endl;
return 0;
}
cout<<"這條邊存在."<<endl;
cout<<"這條邊的長度為:"<<mg->a[u][v]<<endl;
return 1;
}
//邊的插入
int Insert(mGraph *mg,int u,int v,ElemType w){
if(u<0||v<0||u>mg->n-1||v>mg->n-1||u==v) return 0;
if(mg->a[u][v]!=mg->noEdge) {
cout<<"該邊已存在."<<endl;
return 0;
}
mg->a[u][v]=w;
mg->e++;
return 1;
}
//邊的刪除
int Remove(mGraph *mg,int u,int v){
if(u<0||v<0||u>mg->n-1||v>mg->n-1||u==v)
return 0;
if(mg->a[u][v]==mg->noEdge) return 0; //刪除的邊不存在
mg->a[u][v]=mg->noEdge;
mg->e--;
return 1;
}
int main(){
mGraph mg;
int n,n1,u,v,w,a,b;
// fangxin();
// fx();
cout<<"請輸入頂點的個數:"<<endl;
cin>>n;
Init(&mg,n,0);
cout<<"請輸入插入邊的個數:"<<endl;
cin>>n1;
cout<<"請輸入插入邊的起點(頂點計算從0開始)、終點和邊權:"<<endl;
for(int i=0;i<n;i++){
cin>>u>>v>>w;
Insert(&mg,u,v,w);
}
cout<<"請輸入查詢的邊的兩個端點:"<<endl;
cin>>a>>b;
Exist(&mg,a,b);
Destory(&mg);
Remove(&mg,0,1);
system("pause");
return 0;
}
2.以鄰接矩陣所示的鄰接矩陣為儲存結構,編寫程式,實現圖的深度和寬度遍歷。
//鄰接矩陣實現深度和寬度遍歷
/*資料結構實驗三
完成鄰接矩陣的初始化,撤銷,邊的搜尋,插入,刪除等操作 */
#include<bits/stdc++.h>
#include<queue>
using namespace std;
typedef int ElemType;
typedef struct{
ElemType **a; //鄰接矩陣
int n; //圖的頂點數
int e; //圖當前的邊數
ElemType noEdge; //兩頂點無邊時的值
}mGraph;
//初始化,nSize頂點數,noEdgeValue無邊的值
int Init(mGraph *mg,int nSize,ElemType noEdgeValue){
int i,j;
mg->n=nSize;
mg->e=0; //初始化沒有邊
mg->noEdge=noEdgeValue;
mg->a=(ElemType**)malloc(nSize*sizeof(ElemType*)); //生成長度為n的一維陣列指標
if(!mg->a) return 0;
for(int i=0;i<mg->n;i++){
mg->a[i]=(ElemType*)malloc(nSize*sizeof(ElemType));
for(j=0;j<mg->n;j++) mg->a[i][j]=mg->noEdge;
mg->a[i][i]=0; //自迴路設定為0
}
return 1;
}
//撤銷操作,撤銷的時候順序不能變,先釋放指標陣列就會找不到陣列指標啦
int Destory(mGraph *mg){
int i;
for(int i=0;i<mg->n;i++) free(mg->a[i]); //釋放n個一維陣列儲存空間
free(mg->a); //釋放n個一維指標陣列的儲存空間
return 1;
}
//邊的搜尋操作,判斷邊在不在圖中
int Exist(mGraph *mg,int u,int v){
if(u<0||v<0||u>mg->n-1||v>mg->n-1||u==v||mg->a[u][v]==mg->noEdge){
cout<<"這條邊不存在."<<endl;
return 0;
}
cout<<"這條邊存在."<<endl;
cout<<"這條邊的長度為:"<<mg->a[u][v]<<endl;
return 1;
}
//邊的插入
int Insert(mGraph *mg,int u,int v,ElemType w){
if(u<0||v<0||u>mg->n-1||v>mg->n-1||u==v) return 0;
if(mg->a[u][v]!=mg->noEdge) {
cout<<"該邊已存在."<<endl;
return 0;
}
mg->a[u][v]=w;
mg->e++;
return 1;
}
//邊的刪除
int Remove(mGraph *mg,int u,int v){
if(u<0||v<0||u>mg->n-1||v>mg->n-1||u==v)
return 0;
if(mg->a[u][v]==mg->noEdge) return 0; //刪除的邊不存在
mg->a[u][v]=mg->noEdge;
mg->e--;
return 1;
}
void dfs(mGraph mg,int i,int visited[]){
visited[i]=1;
cout<<i<<" ";
for(int j=0;j<mg.n;j++){
if(mg.a[i][j]!=0&&visited[j])
dfs(mg,j,visited);
}
}
void dfsGraph(mGraph mg,int visited[]){
int i;
for(int i=0;i<mg.n;i++) visited[i]=0;
for(int i=0;i<mg.n;i++){
if(!visited[i])
dfs(mg,i,visited);
}
}
int bfsGraph(mGraph *mg,int visited[]){
int i,j;
queue<int> q;
for(int i=0;i<mg->n;i++) visited[i]=0;
for(int i=0;i<mg->n;i++){
if(!visited[i]){
visited[i]=1;
cout<<i<<" ";
q.push(i);
while(!q.empty()){
q.pop();
for(int j=0;j<mg->n;j++){
if(!visited[j]&&mg->a[i][j]!=0){
visited[j]=1;
cout<<j<<" ";
q.pop();
}
}
}
}
}
}
int main(){
mGraph mg;
int n,n1,u,v,w,a,b,visited[10010];
memset(visited,0,sizeof(visited));
cout<<"請輸入頂點的個數:"<<endl;
cin>>n;
Init(&mg,n,0);
cout<<"請輸入插入邊的個數:"<<endl;
cin>>n1;
cout<<"請輸入插入邊的起點(頂點計算從0開始)、終點和邊權:"<<endl;
for(int i=0;i<n1;i++){
cin>>u>>v>>w;
Insert(&mg,u,v,w);
}
cout<<"鄰接矩陣儲存下,圖的深度遍歷訪問過的結點:";
dfsGraph(mg,visited);
cout<<endl;
cout<<"鄰接矩陣儲存下,圖的寬度遍歷訪問過的結點:";
bfsGraph(&mg,visited);
cout<<endl;
system("pause");
return 0;
}
3.實現鄰接表的初始化、撤銷、邊的搜尋、插入、刪除等操作
//以鄰接矩陣為儲存結構,實現圖的深度、寬度、深度優先遍歷
#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef struct Enode{
int adjVex; //任意頂點u相鄰的點
ElemType w; //邊的權值
struct Enode* nextArc; //指向下一個邊結點
}Enode;
typedef struct{
int n; //結點個數
int e; //邊的個數
Enode **a; //指向一維指標陣列
}Lgraph;
//初始化
int init(Lgraph *lg,int nSize) {
lg->a=(Enode **)malloc(nSize*sizeof(Enode*));
lg->n=nSize;
lg->e=0;
if(!lg->a) return 0;
else {
for(int i=0;i<nSize;i++){
lg->a[i]=NULL;
}
return 1;
}
}
//鄰接表的撤銷
int Destory(Lgraph *lg){
int i;
Enode *p,*q;
for(int i=0;i<lg->n;i++){
p=lg->a[i];
q=p;
while(p){
p=p->nextArc;
free(q);
q=p;
}
}
free(lg->a); //釋放一維指標陣列a的儲存空間
return 1;
}
//搜尋邊
int Exist(Lgraph *lg,int u,int v){
Enode *p;
if(u<0||v<0||u>=lg->n||v>lg->n||u==v) return 0;
p=lg->a[u];
while(p &&p->adjVex!=v){
p=p->nextArc;
}
if(!p) return 0;
else{
cout<<"該邊的權值為"<<p->w<<",";
return 1;
}
}
//插入邊
int Insert(Lgraph *lg,int u,int v,int w){
Enode *p;
if(u<0||v<0||u>=lg->n||v>=lg->n||u==v) return 0;
if(Exist(lg,u,v)) return 0;
p=(Enode *) malloc(sizeof(Enode)); //為新生成的邊分配儲存空間
p->adjVex=v;
p->w=w;
p->nextArc=lg->a[u]; //插入結點在序列的開頭
lg->a[u]=p;
lg->e++;
return 1;
}
//刪除邊
int Remove(Lgraph *lg,int u,int v){
if(u<0||v<0||u>=lg->n||v>=lg->n||u==v) return 0;
Enode *p,*q;
p=lg->a[u];
q=NULL;
while(p &&p->adjVex!=v){
q=p;
p=p->nextArc;
}
if(!p) return 0; //q是待刪結點的前驅結點,p是待刪結點
if(q) q->nextArc=p->nextArc;
else lg->a[u]=p->nextArc;
free(q);
lg->e--;
return 1;
}
int main(){
Lgraph lg;
int n,u,v,w;
bool flag1,flag2,flag3;
flag1=flag2=flag3=false;
cout<<"請輸入頂點的個數:"<<endl;
cin>>n;
init(&lg,n);
cout<<"請輸入插入的邊的兩個頂點和邊權:(0 0 0表示輸入結束)"<<endl;
while(cin>>u>>v>>w){
if(u==0 &&v==0 &&w==0) break;
Insert(&lg,u,v,w);
}
cout<<"請輸入待查詢的邊的兩個頂點:"<<endl;
cin>>u>>v;
flag1=Exist(&lg,u,v);
if(flag1) cout<<"該邊存在."<<endl;
else cout<<"該邊不存在."<<endl;
cout<<endl;
cout<<"請輸入待刪除的邊的兩個頂點:"<<endl;
cin>>u>>v;
flag2=Remove(&lg,u,v);
if(flag2) cout<<"刪除成功."<<endl;
else cout<<"刪除失敗."<<endl;
cout<<"撤銷鄰接表."<<endl;
flag3=Destory(&lg);
if(flag3) cout<<"撤銷成功."<<endl;
else cout<<"撤銷失敗."<<endl;
system("pause");
return 0;
}
4.以鄰接表為儲存結構,編寫程式,實現圖的深度和寬度遍歷。
深度
//深度和寬度遍歷圖,鄰接表儲存
#include<bits/stdc++.h>
#define maxn 10010
using namespace std;
int visited[maxn];
typedef struct Enode{
int adjVex; //任意與u相鄰的點
int w; //邊權
struct Enode *nextArc; //指向下一個邊結點
}Enode;
typedef struct{
int n,e;
Enode **a;
}Lgraph;
//單一頂點深搜
void dfs(int v,int visited[],Lgraph g){
Enode *w;
cout<<v<<" "; //訪問結點v
visited[v]=1;
for(w=g.a[v];w ;w=w->nextArc) //訪問鄰接點
{
if(!visited[w->adjVex]){
dfs(w->adjVex,visited,g);
}
}
}
//初始化
int init(Lgraph *lg,int nSize){
lg->n=nSize;
lg->e=0;
lg->a=(Enode **)malloc(nSize*sizeof(Enode *));
if(!lg->a) return 0;
for(int i=0;i<lg->n;i++){
lg->a[i]=NULL;
}
return 1;
}
//插入邊
int Insert(Lgraph *lg,int u,int v,int w){
if(u<0||v<0||u>lg->n-1||v>lg->n-1||u==v) return 0;
Enode *p;
p=(Enode *)malloc(sizeof(Enode));
p->adjVex=v;
p->w=w;
p->nextArc=lg->a[u];
lg->a[u]=p; //這裡注意,開始寫錯了,查了好久
lg->e++;
return 1;
}
//全圖深搜
void dfsGraph(Lgraph g){
int i;
int *visited=(int *)malloc(g.n*sizeof(int ));
for(int i=0;i<g.n;i++)
visited[i]=0;
for(int i=0;i<g.n;i++){
if(!visited[i]){
dfs(i,visited,g);
}
}
free(visited);
}
int main(){
Lgraph lg;
int n,u,v,w,visited[maxn],p;
memset(visited,0,sizeof(visited));
cout<<"請輸入頂點的個數."<<endl;
cin>>n;
init(&lg,n);
cout<<"請輸入帶插入邊的兩個端點和邊權.(以0 0 0結尾)"<<endl;
while(cin>>u>>v>>w){
if(u==0 &&v==0 &&w==0) break;
Insert(&lg,u,v,w);
}
cout<<"請輸入搜尋的起點."<<endl;
cin>>u;
//單一頂點深搜
cout<<"單一頂點深搜:";
dfs(u,visited,lg);
cout<<endl;
//全圖深搜
cout<<"全圖深搜:";
dfsGraph(lg);
cout<<endl;
cout<<"深搜結束"<<endl;
system("pause");
return 0;
}
寬度:
//寬度遍歷圖,鄰接表儲存
#include<bits/stdc++.h>
#include<queue>
#define maxn 10010
using namespace std;
typedef struct Enode{
int adjVex; //相鄰的結點
int w; //邊權
struct Enode * nextArc;
}Enode;
typedef struct{
int n; //頂點數
int e; //邊數
Enode **a; //一維指標陣列
}Lgraph;
int init(Lgraph *lg,int nSize){
lg->n=nSize;
lg->e=0;
lg->a=(Enode **)malloc(nSize*sizeof(Enode *));
if(!lg->a) return 0;
for(int i=0;i<lg->n;i++)
lg->a[i]=NULL;
return 1;
}
int Insert(Lgraph *lg,int u,int v,int w){
if(u<0||v<0||u>lg->n-1||v>lg->n-1||u==v) return 0;
Enode *p;
p=(Enode *)malloc(sizeof(Enode));
p->adjVex=v;
p->w=w;
p->nextArc=lg->a[u];
lg->a[u]=p;
return 1;
}
int bfs(int v,int visited[],Lgraph g){
Enode *w;
queue<int > q; //呼叫STL庫
visited[v]=1;
cout<<v<<" ";
q.push(v);
while(!q.empty()){
q.front(); //取隊首元素
q.pop(); //隊首元素出隊
for(w=g.a[v];w;w=w->nextArc){
if(!visited[w->adjVex]){
visited[w->adjVex]=1;
cout<<w->adjVex<<" ";
q.push(w->adjVex);
}
}
}
}
int bfsGraph(Lgraph g){
int i;
int *visited=(int *)malloc(g.n*sizeof(int));
for(int i=0;i<g.n;i++) visited[i]=0;
for(int i=0;i<g.n;i++){
if(!visited[i]) bfs(i,visited,g);
}
free(visited);
}
int main(){
Lgraph lg;
int n,visited[maxn],u,v,w,v1;
memset(visited,0,sizeof(visited));
cout<<"請輸入頂點的個數."<<endl;
cin>>n;
init(&lg,n);
cout<<"請輸入帶插入邊的兩個端點和邊權.(以0 0 0結尾)"<<endl;
while(cin>>u>>v>>w){
if(u==0 &&v==0 &&w==0) break;
Insert(&lg,u,v,w);
}
cout<<"請輸入寬度搜算的起點:"<<endl;
cin>>v1;
cout<<"寬搜的結點:";
bfs(v1,visited,lg);
cout<<endl;
cout<<"全圖寬搜: ";
bfsGraph(lg);
cout<<endl<<"寬搜結束。"<<endl;
return 0;
}
5.編寫程式,實現智慧交通中的最佳路徑選擇問題。