1.輸入指定的邊數和頂點數建立圖,並輸出深度優先遍歷和廣度優先遍歷的結果。
1)問題描述:在主程序中設計一個簡單的菜單,分別調用相應的函數功能:
1…圖的建立
2…深度優先遍歷圖
3…廣度優先遍歷圖
0…結束
2)實驗要求:在程序中定義下述函數,並實現要求的函數功能:
CreateGraph(): 按從鍵盤的數據建立圖
DFSGrahp():深度優先遍歷圖
BFSGrahp():廣度優先遍歷圖
3)實驗提示:
圖的存儲可採用鄰接表或鄰接矩陣;
圖存儲數據類型定義 (鄰接表存儲)
# define MAX_VERTEX_NUM 8 //頂點最大個數
typedef struct ArcNode
{ int adjvex;
struct ArcNode *nextarc;
int weight; //邊的權
}ArcNode; //表結點
# define VertexType int //頂點元素類型
typedef struct VNode
{ int degree,indegree; //頂點的度,入度
VertexType data;
ArcNode *firstarc;
}Vnode /*頭結點*/, AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertices;
int vexnum,arcnum;//頂點的實際數,邊的實際數
}ALGraph;
4)注意問題:
注意理解各算法實現時所採用的存儲結構。
注意區別正、逆鄰接。
#include<iostream>
using namespace std;
#include<cstdlib>
#include<queue> //c++的隊列庫函數
#include<algorithm>
# define MAX_VERTEX_NUM 8 //頂點最大個數
typedef struct ArcNode{
int adjvex;
ArcNode *nextarc;
}ArcNode;
typedef struct VNode{
int data; //int 類型
ArcNode *firstarc;
}Vnode, AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertex;
int vexnum,arcnum; //頂點的實際數,邊的實際數
}Graph;
void CreateGraph(Graph &G){
ArcNode* s;
int i,j;
int k,d;
int n = G.vexnum;
int e = G.arcnum;
for(i=1; i<=n; i++){ //n爲頂點數、e爲邊數
G.vertex[i].data = i;
G.vertex[i].firstarc = NULL;
}
for(i=1; i<=e; i++){
// 輸入邊
scanf("%d%d",&k,&d);
s = (ArcNode*)malloc(sizeof(ArcNode));
s->adjvex = d;
s->nextarc = G.vertex[k].firstarc;
G.vertex[k].firstarc = s;
s = (ArcNode*)malloc(sizeof(ArcNode));
s->adjvex = k;
s->nextarc = G.vertex[d].firstarc;
G.vertex[d].firstarc = s;
}
for(i=1;i<=n;i++){
int count=0;
int paixu[100] = {0};
ArcNode* r;
r = (ArcNode*)malloc(sizeof(ArcNode));
r = G.vertex[i].firstarc;
while(r!=NULL){
paixu[count] = r->adjvex;
count++;
r = r->nextarc;
}
sort(paixu,paixu+100);
r = G.vertex[i].firstarc;
count =100-count;
while(r!=NULL){
r->adjvex = paixu[count];
count++;
r = r->nextarc;
}
}
}
int flag[100] = {0};
int con=1;
void DFS(Graph G,int v){
if(con < G.vexnum){
cout<<G.vertex[v].data<<" ";
con++;
}
else{
cout<<G.vertex[v].data;
}
ArcNode* p = (ArcNode*)malloc(sizeof(ArcNode));
p = G.vertex[v].firstarc;
flag[v] = 1;
while(p){
if(!flag[p->adjvex]){
DFS(G,p->adjvex);
}
p = p->nextarc;
}
}
int flag1[100] = {0};
int con1 = 1;
void BFS(Graph G,int v){
queue <int> Q;
cout<<G.vertex[v].data<<" ";
con1++;
ArcNode* p = (ArcNode*)malloc(sizeof(ArcNode));
flag1[v] = 1;
Q.push(v);
while(!Q.empty()){
v = Q.front();
Q.pop();
p = G.vertex[v].firstarc;
while(p){
if(!flag1[p->adjvex]){
if(con1 < G.vexnum){
cout<<G.vertex[p->adjvex].data<<" ";
con1++;
}
else{
cout<<G.vertex[p->adjvex].data;
}
flag1[p->adjvex] = 1;
Q.push(p->adjvex);
}
p = p->nextarc;
}
}
}
int main(){
int T;
Graph G;
cout<<"1...圖的建立"<<endl;
cout<<"2...深度優先遍歷圖"<<endl;
cout<<"3...廣度優先遍歷圖"<<endl;
cout<<"0...結束"<<endl;
cout<<endl;
scanf("%d",&T);
while(T != 0){
if(T == 1){
cout<<"請輸入圖的頂點數和邊數"<<endl;
scanf("%d%d",&G.vexnum,&G.arcnum); // 頂點數 邊數
CreateGraph(G); //建立圖
cout<<"建圖成功"<<endl;
}
else if(T == 2){
cout<<"深度優先遍歷結果爲:"<<endl;
DFS(G,1); //深度優先遍歷圖
cout<<endl;
}
else if(T == 3){
cout<<"廣度優先遍歷結果爲:"<<endl;
BFS(G,1); //廣度優先遍歷圖
cout<<endl;
}
scanf("%d",&T);
}
return 0;
}
2. 教學計劃編制問題
1)問題描述:軟件專業的學生要學習一系列課程,其中有些課程必須在其先修課完成後才能學習。
2)實驗要求:假設每門課程的學習時間爲一個學期,試爲該專業的學生設計教學計劃,使他們能在最短時間內修完專業要求的全部課程。
3) 實現提示:
- 以頂點代表課程,弧代表課程的先後修關係,按課程先後關係建立有向無環圖。
- 利用拓撲排序實現。
#include<iostream>
using namespace std;
#include<cstdlib>
#include<stack> //c++的棧庫函數
#include<algorithm>
# define MAX_VERTEX_NUM 8 //頂點最大個數
typedef struct ArcNode{
int adjvex;
ArcNode *nextarc;
}ArcNode; //表結點
#define VertexType int //頂點元素類型
typedef struct VNode{
int degree,indegree; //頂點的度,入度
int data; //int 類型
ArcNode *firstarc;
}Vnode, AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertex;
int vexnum,arcnum; //頂點的實際數,邊的實際數
}Graph;
void CreateGraph(Graph &G){
ArcNode* s;
int i,j;
int k,d;
int n = G.vexnum;
int e = G.arcnum;
for(i=1; i<=n; i++){ //n爲頂點數、e爲邊數
G.vertex[i].data = i;
G.vertex[i].firstarc = NULL;
G.vertex[i].indegree = 0;
}
cout<<"請輸入各邊"<<endl;
for(i=1; i<=e; i++){
scanf("%d%d",&k,&d);
s = (ArcNode*)malloc(sizeof(ArcNode));
s->adjvex = d;
G.vertex[d].indegree++;
s->nextarc = G.vertex[k].firstarc;
G.vertex[k].firstarc = s;
}
for(i=1;i<=n;i++){
int count=0;
int paixu[100] = {0};
ArcNode* r;
r = (ArcNode*)malloc(sizeof(ArcNode));
r = G.vertex[i].firstarc;
while(r!=NULL){
paixu[count] = r->adjvex;
count++;
r = r->nextarc;
}
sort(paixu,paixu+100);
r = G.vertex[i].firstarc;
count =100-count;
while(r!=NULL){
r->adjvex = paixu[count];
count++;
r = r->nextarc;
}
}
}
int TS(Graph G){
int i,k,tmp,count=1;
stack<int> s;
ArcNode *p;
for(i=G.vexnum;i>0;i--){
if( G.vertex[i].indegree == 0){
s.push(i);
}
}
cout<<endl<<"結果爲:"<<endl;
while(!s.empty()){
int tm[100]={0};
int con=0;
while(!s.empty()){
tm[con] = s.top();
con++;
s.pop();
}
sort(tm,tm+100);
int con1 = con;
while(con){
s.push(tm[100-con1+con-1]);
con--;
}
tmp = s.top();
s.pop();
if(count<G.vexnum){
cout<<G.vertex[tmp].data<<" ";
count++;
}
else{
cout<<G.vertex[tmp].data;
}
for(p = G.vertex[tmp].firstarc; p; p=p->nextarc){
k = p->adjvex;
if(!(--G.vertex[k].indegree)){
s.push(k);
}
}
}
}
int main(){
Graph G;
cout<<"請輸入頂點數和邊數:"<<endl;
scanf("%d%d",&G.vexnum,&G.arcnum); // 頂點數 邊數
CreateGraph(G); //建立圖
TS(G);
return 0;
}
3.給定實際背景,解決最短路徑問題
1)問題描述:假設以一個帶權有向圖表示某一區域的公交線路網,圖中頂點代表一些區域中的重要場所,弧代表已有的公交線路,弧上的權表示該線路上的票價(或搭乘所需時間),試設計一個交通指南系統,指導前來諮詢者以最低的票價或最少的時間從區域中的某一場所到達另一場所。
2)實驗要求:利用Dijkstra算法求最低的票價
3) 實現提示:
- 該問題可以歸結爲一個求帶權有向圖中頂點間最短路徑的問題。
- 建立以票價爲權的有向圖,再利用Dijkstra算法求最短路徑及其路徑長度。
#include<iostream>
using namespace std;
typedef struct Arc{
int quan;
}AdjMatrix[500][500]; //矩陣
typedef struct Graph{
int vertex[1000];
AdjMatrix arcs;
int vexnum,arcnum;
};
int main(){
int n,m;
Graph G;
cout<<"請輸入頂點數和邊數:"<<endl;
cin>>n>>m;
int i,j;
for(i=1;i<=n;i++){ //初始化矩陣
for(j=1;j<=n;j++){
G.arcs[i][j].quan = 99999;
}
}
int m1 = m;
int a,b,c;
int P;
cout<<"請輸入邊信息:"<<endl;
while(m1--){ //賦權值
cin>>a>>b>>c;
G.arcs[a][b].quan = c;
}
int q[1000];
for(i=0;i<=1000;i++){
q[i] = 99999;
}
int n1 = n-1;
int nowi = 1, nowq = 0,nowj = 1;
int z = 9999;
while(n1--){
int min = 99999;
for(j=1;j<=n;j++){
if(nowi != j){
if(G.arcs[nowi][j].quan < q[j]){
q[j] = G.arcs[nowi][j].quan;
if(nowj == j){
q[j] += nowq;
}
}
if(G.arcs[nowi][j].quan < min){
min = G.arcs[nowi][j].quan;
}
}
}
for(j=1;j<=n;j++){
if(min == q[j]){
nowj = j;
}
}
nowq = nowq + min;
q[nowj] = nowq;
int min1 = 99999;
for(i=1;i<=n;i++){
if(q[i]<=min1){
min1 = q[i];
nowi = i;
}
}
nowq = min1;
if(nowi==n && nowq<z){
z = nowq;
}
for(j=1;j<=n;j++){
if(min1 == q[j]){
q[j] = 99999;
}
}
}
cout<<"第1個節點到第n個節點的最短路徑:"<<endl;
cout<<z;
return 0;
}
4.利用最小生成樹算法解決通信網的總造價最低問題
1)問題描述:若在n個城市之間建通信網絡,架設n-1條線路即可。如何以最低的經濟代價建設這個通信網,是一個網絡的最小生成樹問題。
2)實驗要求:利用Prim算法求網的最小生成樹。
3) 實現提示:通信線路一旦建立,必然是雙向的。因此,構造最小生成樹的網一定是無向網。爲簡單起見,圖的頂點數不超過10個,網中邊的權值設置成小於100。
#include<iostream>
using namespace std;
typedef struct Arc{
int quan;
}AdjMatrix[500][500]; //矩陣
typedef struct Graph{
AdjMatrix arcs;
int vexnum,arcnum;
};
int main(){
int n,m;
Graph G;
cout<<"請輸入頂點數和邊數"<<endl;
cin>>n>>m;
int i,j;
for(i=1;i<=n;i++){ //初始化矩陣
for(j=1;j<=n;j++){
G.arcs[i][j].quan = 99999;
}
}
int m1 = m;
int a,b,c;
int P;
cout<<"請輸入各邊信息"<<endl;
while(m1--){ //賦權值
cin>>a>>b>>c;
G.arcs[a][b].quan = c;
G.arcs[b][a].quan = c;
}
int u[1000] = {0};
int v[1000] = {0};
for(i=2;i<=n;i++){
v[i] = i;
}
u[1] = 1;
int n1 = n-1;
int nowi,nowj,sum=0;
while(n1--){
i=1;
int min = 99999;
while(i != n+1){
if(u[i]!=0){
j=1;
while(j != n+1){
if(G.arcs[u[i]][v[j]].quan<=min && v[j]!=0){
min = G.arcs[u[i]][v[j]].quan;
nowi = u[i];
nowj = v[j];
}
j++;
}
}
i++;
}
G.arcs[nowi][nowj].quan = 99999;
G.arcs[nowj][nowi].quan = 99999;
sum += min;
u[nowj] = nowj;
v[nowj] = 0;
}
cout<<"最小代價爲:"<<endl;
cout<<sum;
return 0;
}