本文轉自:http://www.linuxidc.com/Linux/2013-10/90915.htm
華爲2014上機考試樣題_高級題_地鐵換乘最短路徑_無向無權圖+鄰接表存儲+BFS廣度優先算法
/*
Copyright (c) 2013, [email protected]
華爲2014上機考試樣題 高級題 地鐵換乘 最短路徑 http://www.linuxidc.com/Linux/2013-10/90916.htm
華爲2014校園招聘經歷_底層軟件研發_機考 http://www.linuxidc.com/Linux/2013-10/90912.htm
華爲2014機考題目_判斷if括號匹配是否合法_堆棧_簡單的方法- - http://www.linuxidc.com/Linux/2013-10/90913.htm
華爲2014機考題_判斷if括號是否匹配_堆棧 http://www.linuxidc.com/Linux/2013-10/90914.htm
無向無權圖 鄰接表存儲 BFS廣度優先算法搜索
涉及:圖 鏈表 隊列 指針 數組 字符串 類型轉換
供參考
*/
/*
*/
#include <iostream>
#include <string> //用到字符串操作
#include <sstream> //int轉string,用到流操作
using namespace std; //標準庫命名空間
#define DEBUG
#define VerNum 35 //定義頂點數,爲 35=18(A)+15(B)+2(T)
typedef int Boolean;
#define TRUE 1
#define FALSE 0
/*********************字符串數組與編號映射*************************************
A
data: A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 A18
index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
B
data: B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15
index: 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
T
data: T1 T2
index: 33 34
*/
string Data[VerNum]; //字符串數組,用於存儲輸入的字符串,數據和下標構成上述映射關係;全局變量
string intToString(int index) //int轉string函數,用於下述 initD() 的字符串序號
{
stringstream str1;
string str2;
str1 << index;
str1 >> str2;
return str2;
}
void InitData() //初始化字符串數組,完成映射
{
int index;
for (index = 0; index < 18; index++) //A1-A18, index 0-17
Data[index] = "A" + intToString(index + 1);
for (index = 18; index < 33; index++) //B1-B15, index 18-32
Data[index] = "B" + intToString(index - 18 + 1);
for (index = 33; index < 35; index++) //T1-T2, index 33-34
Data[index] = "T" + intToString(index - 33 + 1);
}
int dataToIndex(string str) //查找輸入字符串的相應index
{
int index;
for (index = 0; index < VerNum; index++)
{
if(strcmp(str.c_str(),Data[index].c_str()) == 0) //比較輸入字符串str與數據數組Data[]的各元素,相等則返回該元素下標index
break;
}
return index;
}
/**************************************************************鄰接表存儲圖信息******************************
Data index 頂點表GraphList 第一邊表e1[35] 第二邊表e2[33] 第三邊表e3[2] 第四邊表e4[2]
verIndex firstedge eVerIndex nextEdge eVerIndex nextEdge eVerIndex nextEdge eVerIndex nextEdge
-----------------------------------------------------------------------------------------------------------------------------------------------
A1 0 | 0 --> |e1[0] 1 --> |e2[0] 17 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A2 1 | 1 --> | 2 --> | 0 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A3 2 | 2 --> | 3 --> | 1 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A4 3 | 3 --> | 4 --> | 2 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A5 4 | 4 --> | 5 --> | 3 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A6 5 | 5 --> | 6 --> | 4 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A7 6 | 6 --> | 7 --> | 5 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A8 7 | 7 --> | 8 --> | 6 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A9 8 | 8 --> | 33(T1) --> | 7 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A10 9 | 9 --> | 10 --> | 33(T1) -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A11 10 | 10 --> | 11 --> | 9 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A12 11 | 11 --> | 12 --> | 10 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A13 12 | 12 --> | 34(T2) --> | 11 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A14 13 | 13 --> | 14 --> | 34(T2) -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A15 14 | 14 --> | 15 --> | 13 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A16 15 | 15 --> | 16 --> | 14 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A17 16 | 16 --> | 17 --> | 15 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
A18 17 | 17 --> | 0 --> |e2[17] 16 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B1 18 | 18 --> | 19 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B2 19 | 19 --> | 20 --> |e2[18] 18 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B3 20 | 20 --> | 21 --> | 19 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B4 21 | 21 --> | 22 --> | 20 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B5 22 | 22 --> | 33(T1) --> | 21 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B6 23 | 23 --> | 24 --> | 33(T1) -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B7 24 | 24 --> | 25 --> | 23 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B8 25 | 25 --> | 26 --> | 24 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B9 26 | 26 --> | 27 --> | 25 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B10 27 | 27 --> | 34(T2) --> | 26 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B11 28 | 28 --> | 29 --> | 34(T2) -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B12 29 | 29 --> | 30 --> | 28 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B13 30 | 30 --> | 31 --> | 29 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B14 31 | 31 --> | 32 --> |e2[30] 30 -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
B15 32 | 32 --> | 31(B14) -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
T1 33 | 33 --> |e1[33] 9(A10) --> |e2[31] 8(A9) --> |e3[0] 23(B6) --> |e4[0] 22(B5) -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
T2 34 | 34 --> |e1[34] 13(A14) --> |e2[32] 12(A14) --> |e3[1] 28(B11) --> |e4[1] 27(B10) -->NULL |
-----------------------------------------------------------------------------------------------------------------------------------------------
參考:
http://blog.chinaunix.net/uid-26548237-id-3483650.html
*/
//邊表結構
typedef struct edgeNode
{
int eVerIndex; //邊表頂點號
struct edgeNode *nextEdge; //指向下一邊表的指針
}edgeNode; //struct edgeNode的別名爲edgeNode,方便調用
//頂點表結構
typedef struct vertexNode
{
int verIndex; //頂點表的頂點號
edgeNode *firstEdge; //指向第一邊表的指針
}vertexNode;
//頂點表構成的圖的鄰接表
typedef struct
{
vertexNode adjList[VerNum]; //頂點表結構數組,總數爲頂點的數目
}graphList; //將此結構體別名定義爲graphList
//建圖,確立頂點表和邊表的關係,完善各表的數據域和指針域
void CreatGraph(graphList *g) //指針形參,對g指向的內容的操作在函數結束後仍然有效
{
/**************邊表************************/
//邊表和頂點表的填充過程參考上面的鄰接表圖
edgeNode *e1[35]; //第一邊表
edgeNode *e2[33]; //第二邊表
edgeNode *e3[2]; //第三邊表
edgeNode *e4[2]; //第四邊表
int i;
for (i = 0; i < 35; i++) //第一邊表初始化,分配內存
e1[i] = new edgeNode;
for (i = 0; i < 33; i++) //第二邊表初始化,分配內存
e2[i] = new edgeNode;
for (i = 0; i < 2; i++) //第三、四邊表初始化,分配內存
{
e3[i] = new edgeNode;
e4[i] = new edgeNode;
}
//第一邊表數據域,即第一邊表頂點號
//A
for (i = 0; i < 18; i++)
e1[i]->eVerIndex = i + 1;
//修正A
e1[8]->eVerIndex = 33; //A9-->T1
e1[12]->eVerIndex = 34; //A13-->T2
e1[17]->eVerIndex = 0; //A18-->A1
//B
for (i = 18; i < 18+15; i++)
e1[i]->eVerIndex = i + 1;
//修正B
e1[22]->eVerIndex = 33; //B5-->T1
e1[27]->eVerIndex = 34; //B10-->T2
e1[32]->eVerIndex = 31; //B15-->B14
//T1 T2
e1[33]->eVerIndex = 9; //T1-->A10
e1[34]->eVerIndex = 13; //T2-->A14
//第二邊表數據域,即第二邊表頂點號
//A
for (i = 0; i < 18; i++)
e2[i]->eVerIndex = i - 1;
//修正A
e2[0]->eVerIndex = 17; //A1-->A18
e2[9]->eVerIndex = 33; //A10-->T1
e2[13]->eVerIndex = 34; //A14-->T2
//B
for(i=18; i<31; i++) //B1和B15沒有第二邊表
e2[i]->eVerIndex = i;
//修正B
e2[22]->eVerIndex = 33; //B6-->T1
e2[27]->eVerIndex = 34; //B11-->T2
//T1 T2
e2[31]->eVerIndex = 8; //T1-->A9
e2[32]->eVerIndex = 12; //T2-->A13
//第三邊表數據域,即第三邊表頂點號
//T1 T2
e3[0]->eVerIndex = 23; //T1-->B6
e3[1]->eVerIndex = 28; //T2-->B11
//第四邊表數據域,即第四邊表頂點號
//T1 T2
e4[0]->eVerIndex = 22; //T1-->B5
e4[1]->eVerIndex = 27; //T2-->B10
//第一邊表指針域
for (i = 0; i < 18; i++)
e1[i]->nextEdge = e2[i];
e1[18]->nextEdge = NULL; //B1沒有第二邊表
for (i = 19; i < 32; i++)
e1[i]->nextEdge = e2[i-1];
e1[32]->nextEdge = NULL; //B15沒有第二邊表
e1[33]->nextEdge = e2[31];
e1[34]->nextEdge = e2[32];
//第二邊表指針域
for (i = 0; i < 31; i++)
e2[i]->nextEdge = NULL;
e2[31]->nextEdge = e3[0];
e2[32]->nextEdge = e3[1];
//第三邊表指針域
e3[0]->nextEdge = e4[0];
e3[1]->nextEdge = e4[1];
//第四邊表指針域
e4[0]->nextEdge = NULL;
e4[1]->nextEdge = NULL;
/*************************************************************/
/***完善頂點表數據域和指針域,關聯頂點表與第一邊表****/
for (i = 0; i < VerNum; i++)
{
g->adjList[i].verIndex = i; //頂點表數據域
g->adjList[i].firstEdge = e1[i]; //頂點表指針域
}
/*************************************************************/
}
/***打印鄰接表信息*******/
#ifdef DEBUG //只在DEBUG模式下打印
void printGraph(graphList *g)
{
int i;
edgeNode *p;
for (i = 0; i < VerNum; i++)
{
cout << "頂點號:" << i << "邊號:";
p = g->adjList[i].firstEdge;
while (p)
{
cout << p->eVerIndex << " ";
p = p->nextEdge;
}
cout << endl;
}
}
#endif
/***************************************************/
/****BFS廣度優先搜索鄰接表,找出最短路徑***********
參考:
http://blog.163.com/zhoumhan_0351/blog/static/3995422720098711040303/
******************************************************/
//隊列鏈表結點結構,單向鏈表
typedef struct qNote
{
int qVerIndex; //隊列數據域,結點存儲的頂點號
struct qNote *nextQNode; //隊列指針域,結點指向的下一個隊列結點
}qNote;
//隊列鏈表
typedef struct
{
qNote *front; //隊列頭,刪除
qNote *rear; //隊列尾,添加
}queue;
//初始化隊列,新建隊列
void InitQueue(queue *q)
{
q->rear = new qNote; //新建隊列結點,賦予隊尾
q->front = q->rear; //空隊列的隊頭與隊尾爲同一單元
/*
if(q->front == NULL) //分配單元失敗
{
cout << "InitQueue Error!" << endl;
exit(1);
}
*/
q->front->nextQNode = NULL; //隊頭的指向下一結點的指針爲空
//因爲隊首隊尾爲同一單元,則隊尾結點的下一結點指針也爲空,即q->rear->nextQNode == NULL
}
//入隊,隊尾添加
void EnQueue(queue *q, int e) //形參爲隊列q地址,要添加的新的隊列結點的數據域
{
qNote *p = new qNote; //新建節點,並分配內存
/*if(p == NULL ) //若分配內存失敗則退出
{
cout << "EnQueue Error!" << endl;
exit(1);
}
*/
p->qVerIndex = e;
p->nextQNode = NULL;
q->rear->nextQNode = p; //原隊尾指向下一結點的指針指向p
q->rear = p; //p成爲新的隊尾
}
int QueueEmpty(queue *q) //判斷隊列是否爲空,空則返回1,非空爲0
{
return (q->front == q->rear ? 1:0); //判斷條件爲,隊頭與隊尾爲同一單元
}
//出隊,隊首刪除
void DeQueue(queue *q, int *m) //隊列q指針傳參,m爲指針形參,用於保存刪除的結點的數據域
{
qNote *p = new qNote; //新建隊列結點,用於緩存
if (QueueEmpty(q)) //若爲空隊列,則報錯退出
{
cout<<"DeQueue Error!"<<endl;
exit(1);
}
p = q->front->nextQNode; //要刪除的結點緩存爲p
*m = p->qVerIndex; //要刪除的結點的數據域放入m所指單元
q->front->nextQNode = p->nextQNode; //隊頭指向下一結點的指針,即指向要刪除的結點的下一個結點
if (q->front->nextQNode == NULL)
{
q->rear = q->front; //若隊首指向下一個結點的指針爲空,則表明隊列已經清空,隊首隊尾爲同一單元
//注:不能寫反了
}
free(p); //釋放緩存
}
//BFS廣度優先搜索
void BFSTraverse(graphList *g, int dist[VerNum][VerNum])
{
queue q;
edgeNode *p = new edgeNode; //定義邊表結點類型指針,下面訪問各個結點的邊表時用到
int index;
/*
此處使用循環來得到所有點相對其他點的最短路徑,
若圖有未達到的點,需要再設置一個循環來達到遍歷所有點的目的,
因爲此題中任何點均可以達到其他所有點,不必再設下一循環
*/
for (index = 0; index < VerNum; index++)
{
InitQueue(&q); //初始化隊列q,每個新的起點都重置一下隊列
Boolean visited[VerNum] = {FALSE}; //定義各頂點訪問標誌,並初始化爲FALSE
/*
設置一個層次標誌
BFS算法是把圖從一個頂點轉化爲樹,並按照距離的遠近設置樹的層次,
處於同一層次的葉結點與根結點的距離相同
而且根結點與頁結點的距離,就是層次數
*/
int level[VerNum][VerNum]; //樹的最大度爲VerNum(第一個),每層中最大葉結點爲VerNum(第二個)
//此數組用於保存每層的各葉子結點
int r1,r2; //數組橫下標爲r1,縱下標r2
for(r1=0; r1<VerNum; r1++) //初始化層次數組
{
for(r2=0; r2<VerNum; r2++)
level[r1][r2] = VerNum; //因爲沒有VerNum序號的結點,用於判斷是否賦值,或作其他用途
}
EnQueue(&q,index); //頂點入隊
visited[index] = TRUE; //入隊表示已訪問
r1 = 0;
r2 = 0;
level[0][0] = index; //樹的根節點存放的頂點號
//r1表示層次數,r2表示本層的第幾個葉結點
dist[index][index] = r1; //表示該頂點到自身的距離爲0
while (!QueueEmpty(&q))
{
int m;
DeQueue(&q,&m); //隊首出隊
if (m == level[r1][0]) //若出隊的頂點號與第r1層的第一個結點的頂點號相同
//即:出隊的頂點號是某層第一個入隊的結點,那麼說明該層已經訪問結束,進入下一層訪問
{
r1 += 1; //進入下一層
r2 = 0; //下一層起點
}
p = g->adjList[m].firstEdge; //按照鄰接表各頂點邊表的順序訪問每個頂點
while (p)
{
if (!visited[p->eVerIndex])
{
EnQueue(&q,p->eVerIndex); //未訪問的入隊
visited[p->eVerIndex] = TRUE; //入隊表示已訪問
level[r1][r2] = p->eVerIndex; //r1層r2葉結點的頂點號爲當前訪問的邊表頂點號
dist[index][p->eVerIndex] = r1; //根頂點與當前訪問的頂點的距離,爲當前訪問的點所在的層次數
r2 += 1; //該層訪問結點數遞增
}
p = p->nextEdge; //循環控制,指向下一個邊表
}
}
}
}
#ifdef DEBUG
void printBFS(int dist[VerNum][VerNum])
{
cout<<endl;
for (int i = 0; i < VerNum; i++)
{
cout<<i<<":";
for (int j = 0; j < VerNum; j++)
{
cout<<dist[i][j]<<" ";
}
cout<<endl;
}
}
#endif
int main()
{
InitData(); //初始化字符串數組,Data[]數組已經設置成了全局變量。。也可以設置在此處數組傳參
graphList g; //建圖
CreatGraph(&g); //完善圖的所有結點
#ifdef DEBUG //調試用,打印圖
printGraph(&g);
#endif
int dist[VerNum][VerNum]; //定義各頂點間距離數組
for(int d1=0; d1<VerNum; d1++) //初始化距離數組
{
for(int d2=0; d2<VerNum; d2++)
{
dist[d1][d2] = 0; //表示頂點d1到頂點d2的距離
//最大距離不會是VerNum,表示無法到達或有其他用途
}
}
BFSTraverse(&g, dist); //BFS搜索,保存各點最短路徑
#ifdef DEBUG
printBFS(dist); //打印各點間最短路徑
#endif
string str1, str2; //用於保存兩個輸入的字符串
#ifdef DEBUG
cout << "請輸入兩個站點:" << endl;
#endif
cin >> str1 >> str2; //輸入兩個字符串,沒有設置冗餘,對於不符合規範的輸入,只取前兩個
int index1, index2; //用於保存將兩個輸入的字符串轉換後的頂點號
index1 = dataToIndex(str1); //將str1轉換成相應頂點號
index2 = dataToIndex(str2); //將str2轉換成相應頂點號
//兩點index1和index2間的距離即爲dist[index1][index2],無向,則也等於dist[index2][index1]
#ifdef DEBUG
cout << "兩點間站點數爲:" << endl;
#endif
cout << dist[index1][index2] <<endl;
#ifdef DEBUG
system("pause"); //暫停,以查看輸出
#endif
return 0;
}
用Floyd算法,簡單易理解,但時間複雜度是n^3。
參考:http://blog.csdn.net/suren__123/article/details/10985305 原文個別錯誤已改。
- #include <cstdlib>
- #include <iostream>
- #include <string>
- /*
- Author : 俗人
- Time : 2013/9/2
- description : 地鐵換乘問題
- 已知2條地鐵線路,其中A爲環線,B爲東西向線路,線路均爲雙向,
- 換乘點爲 T1,T2,編寫程序,任意輸入兩個站點名稱,輸出乘坐地鐵
- 最少所需要經過的車站數量
- A(環線):A1...A9 T1 A10...A13 T2 A14...A18
- B(直線):B1...B5 T1 B6...B10 T2 B11...B15
- 樣例輸入:A1 A3
- 樣例輸出:3
- */
- using namespace std;
- //無向圖的數據結構
- struct Graph
- {
- int arrArc[100][100]; //鄰接矩陣
- int verCount; //點數
- int arcCount; //邊數
- };
- //FLOYD算法 求任意兩點最短路徑矩陣
- void floyd(Graph *p,int dis[100][100]){
- for(int k = 1;k <= p->verCount;k++)
- for(int i = 1; i <= p->verCount;i++)
- for(int j = 1;j <= p->verCount;j++)
- {
- //存在更近的路徑,則更新
- if(dis[i][j]>dis[i][k]+dis[k][j])
- dis[i][j]=dis[i][k]+dis[k][j];
- }
- }
- //站名字符串轉節點編號
- int char_to_int(string s){
- string s1[38] = {"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","A10",
- "A11","A12","A13","A14","A15","A16","A17","A18",
- "B1","B2","B3","B4","B5","B6","B7","B8","B9","B10",
- "B11","B12","B13","B14","B15","T1","T2"} ;
- for(int i=1 ; i <= 38;i ++){
- if (s == s1[i])
- return i;
- }
- return -1;
- }
- int main(int argc, char *argv[])
- {
- Graph g;
- g.verCount = 35; //原文有誤
- g.arcCount = 36; //原文有誤
- cout<<"number of ver:"<<g.verCount<<" number of arc:" <<g.arcCount<<endl;
- //初始化鄰接矩陣
- for(int i = 1;i<=g.verCount;i++)
- { for(int j = 1;j<=g.verCount;j++)
- {
- //i到本身的距離爲0
- //不同節點值爲不可達
- if(i==j) g.arrArc[i][i]= 0;
- else
- g.arrArc[i][j] = 65535;
- }
- }
- //輸入A環線個點相連情況 每個邊權重都爲1
- int a[21] = {1,2,3,4,5,6,7,8,9,34,10,11,12,13,35,14,15,16,17,18,1};
- for(int i=0;i<20;i++)
- {
- g.arrArc[a[i]][a[i+1]] = 1;
- g.arrArc[a[i+1]][a[i]] = 1;
- }
- //輸入B線個點相連情況 每個邊權重都爲1
- int b[17] = {19,20,21,22,23,34,24,25,26,27,28,35,29,30,31,32,33};
- for(int i=0;i<16;i++)
- {
- g.arrArc[b[i]][b[i+1]] = 1;
- g.arrArc[b[i+1]][b[i]] = 1;
- }
- //計算鄰接矩陣
- floyd(&g,g.arrArc);
- cout << "請輸入起始站點:" <<endl;
- string start;
- string end;
- cin >> start >> end;
- cout << g.arrArc[char_to_int(start)][char_to_int(end)] <<endl;
- system("PAUSE");
- return EXIT_SUCCESS;
- }