1. 程式人生 > >圖的基本運算及智慧交通中的最佳路徑選擇問題(實驗三)

圖的基本運算及智慧交通中的最佳路徑選擇問題(實驗三)

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.編寫程式,實現智慧交通中的最佳路徑選擇問題。