話不多說 直接進入正題!
首先我給出demo 輸入比如 五道口,國貿 點擊按鈕搜索查詢即可!
現在我說說我的思路:
S1:加載全部換乘結點 方法Hashtable LoadDC()
DCht.Add("XX", new double[] { -2, -1.4 });
上面是執行的一句代碼,XX的坐標即為(-1,-1.4) 用double類型后面要是地鐵換乘站在X之前增加了 那就直接寫上小於-1.4的,反之大於1.4! 否則若用int類型那耦合性太高了
這是不用int類型的好處!
S2:加載換乘站之間的關系{Relation for Node} 方法 HashSet<string[]> LoadDD()
b1 = "begin"; b2 = "end"; len = "4.1"; timem = "7"; SWAP(backlist, ref arry, b1, b2, len, timem);
len代表路程(數據來至百度),timem代表b1到b2的時間!
S3:現在我要查詢B到E的最短路程 搜索: B-E 開始
S3_1:如果B,E都是換乘結點比如“西二旗”到“國貿” 那直接進行第四步S4
S3_2:如果B,E中有一個不是換乘結點,執行方法 HashSet<string> GetPreOrNextNode(string stationname)
string[] Linecp = { "西二旗", "生命科學園", "朱辛庄", "鞏華城", "沙河", "沙河高教園", "南邵" }; int[] Linecpnode = { 1, 0, 0, 0, 0, 0, 1 }; liststr.Add(Linecp); listint.Add(Linecpnode);
1代表是換乘點或者是X號線的起點,0代表不是換乘結點
hs = new HashSet<string>(tempstr); ///O(1) if (hs.Contains(stationname) == true)
執行hash查找 最優情況下:O(1)
while (pre > -1) { if (tint[pre] == 1) break; pre = pre - 1; } int next = b; while (next < tint.Length) { if (tint[next] == 1) break; next = next + 1; } HashSet<string> hr = new HashSet<string>(); hr.Add(liststr[a][pre]); hr.Add(liststr[a][next]); return hr;
現在返回可能值:(b1x,b1y),(b2x,b2y) 可能值共有C(2,2)+C(3,2)+C(4,2)=10種可能
根據起點B和終點E查詢出來了BE附近的可能結點 然后用點到點的距離 找出最多10中可能值的最小值 返回min_b_node,min_e_node
S4:
現在已經有b_node,和e_node 起點和終點附近最短距離的換乘結點,(最短距離不代表最短路程,因為有可能它們之間沒有換乘關系) 但不要緊,請看下面:
坐標中從一點出發到另一點的8種情況 直接上代碼:
bool CK(bool isadd, double[] bxy, double[] exy) { if (dx >= 0 && dy >= 0 && exy[0] >= bxy[0] && exy[1] >= bxy[1] && exy[0] <= ex && exy[1] <= ey) //1 x增大y增大 isadd = true; else if (dx >= 0 && dy <= 0 && exy[0] >= bxy[0] && exy[1] <= bxy[1] && exy[0] <= ex && exy[1] >= ey)//2 x增大y減小 isadd = true; else if (dx <= 0 && dy >= 0 && exy[0] <= bxy[0] && exy[1] >= bxy[1] && exy[0] >= ex && exy[1] <= ey)//3 x減小y增大 isadd = true; else if (dx <= 0 && dy <= 0 && exy[0] <= bxy[0] && exy[1] <= bxy[1] && exy[0] >= ex && exy[1] >= ey)//4 x減小y減小 isadd = true; else if (dx >= 0 && dy == 0 && exy[0] >= bxy[0] && exy[1] == bxy[1] && exy[1] == ey && exy[0] <= ex)//5 x增大y不變 isadd = true; else if (dx == 0 && dy >= 0 && exy[0] == bxy[0] && exy[1] >= bxy[1] && exy[0] == ex && exy[1] <= ey)//6 x不變y增大 isadd = true; else if (dx <= 0 && dy == 0 && exy[0] <= bxy[0] && exy[1] == bxy[1] && exy[1] == by && exy[0] >= ex)//7 x減小y不變 isadd = true; else if (dx == 0 && dy <= 0 && exy[0] == bxy[0] && exy[1] <= bxy[1] && exy[0] == bx && exy[1] >= ey)//8 x不變 y減小 isadd = true; else isadd = false; return isadd; }
代碼我就不用解釋了,下面是核心代碼
///O(n) foreach (string strbegin in beginlist) { if (strbegin.IndexOf("-") == -1 && mainht.ContainsKey(strbegin) == true)//have this key and first load data { bxy = (double[])DCht[strbegin]; earry = mainht[strbegin].ToString().Split(','); foreach (string ar in earry) { exy = (double[])DCht[ar]; isadd = CK(isadd, bxy, exy); if (isadd == true) { returnlist.Add(strbegin + "-" + ar); isend = 0; } } } else if (strbegin.IndexOf("-") > -1 && mainht.ContainsKey(strbegin.Substring(strbegin.LastIndexOf("-") + 1)) == true) { temgstr = strbegin.Substring(strbegin.LastIndexOf("-") + 1); bxy = (double[])DCht[temgstr]; earry = mainht[temgstr].ToString().Split(',');//exchange node foreach (string ar in earry) { exy = (double[])DCht[ar]; isadd = CK(isadd, bxy, exy); if (isadd == true) { if (!strbegin.Contains(ar)) returnlist.Add(strbegin + "-" + ar); isend = 0; } } } } } earry = null; if (isend == 0) return GetF(returnlist, i); else return null;
到這里本人有個問題請教:
Code1: if (fresult.Contains(temp) == false) fresult.Add(temp);
Code2: fresult.Add(temp);
Code1和Code2有什么區別? freault為hashset 性能上的????? 我看了java中的實現過程 但是C#語言看不了實現過程 只看了過程的描述!
后面的實現過程就很簡單了! 找到BE之間盡量短的可能路線的集合然后找出其中最短的路徑 程序結束!
測試結果:
程序開始執行時間:20130515115735 734 LoadData begin:20130515115735 734 換乘站全集:Ux begin: 20130515115735734換乘站全集:Ux end: 20130515115735734 LoadData endss:20130515115735 734 GetF() begin:20130515115735:734 GetF() endss:20130515115735:734 五道口-知春路------------->北京西站: 五道口-知春路-西直門-車公庄-白石橋南-北京西站 五道口-知春路-西直門-國家圖書館-白石橋南-北京西站 五道口-知春路-海淀黃庄-國家圖書館-白石橋南-北京西站 count:3 最短路程為:五道口-知春路-海淀黃庄-國家圖書館-白石橋南-北京西站:11.3 程序結束執行時間:20130515115735 734
程序開始執行時間:20130515115844 812 LoadData begin:20130515115844 812 換乘站全集:Ux begin: 20130515115844812換乘站全集:Ux end: 20130515115844812 LoadData endss:20130515115844 812 GetF() begin:20130515115844:812 GetF() endss:20130515115844:812 五道口-知春路------------->國貿: 五道口-知春路-西直門-平安里-西單-東單-建國門-國貿 五道口-知春路-西直門-平安里-東四-東單-建國門-國貿 五道口-知春路-西直門-平安里-東四-朝陽門-建國門-國貿 五道口-知春路-西直門-平安里-東四-朝陽門-呼家樓-國貿 五道口-知春路-北土城-惠新西街南口-芍葯居-三元橋-呼家樓-國貿 五道口-知春路-西直門-鼓樓大街-雍和宮-東四-東單-建國門-國貿 五道口-知春路-西直門-鼓樓大街-雍和宮-東四-朝陽門-建國門-國貿 五道口-知春路-西直門-鼓樓大街-雍和宮-東四-朝陽門-呼家樓-國貿 五道口-知春路-西直門-鼓樓大街-雍和宮-東直門-朝陽門-建國門-國貿 五道口-知春路-西直門-鼓樓大街-雍和宮-東直門-朝陽門-呼家樓-國貿 五道口-知春路-西直門-車公庄-復興門-西單-東單-建國門-國貿 五道口-知春路-西直門-車公庄-平安里-西單-東單-建國門-國貿 五道口-知春路-西直門-車公庄-平安里-東四-東單-建國門-國貿 五道口-知春路-西直門-車公庄-平安里-東四-朝陽門-建國門-國貿 五道口-知春路-西直門-車公庄-平安里-東四-朝陽門-呼家樓-國貿 五道口-知春路-北土城-鼓樓大街-雍和宮-東四-東單-建國門-國貿 五道口-知春路-北土城-鼓樓大街-雍和宮-東四-朝陽門-建國門-國貿 五道口-知春路-北土城-鼓樓大街-雍和宮-東四-朝陽門-呼家樓-國貿 五道口-知春路-北土城-鼓樓大街-雍和宮-東直門-朝陽門-建國門-國貿 五道口-知春路-北土城-鼓樓大街-雍和宮-東直門-朝陽門-呼家樓-國貿 五道口-知春路-北土城-惠新西街南口-雍和宮-東四-東單-建國門-國貿 五道口-知春路-北土城-惠新西街南口-雍和宮-東四-朝陽門-建國門-國貿 五道口-知春路-北土城-惠新西街南口-雍和宮-東四-朝陽門-呼家樓-國貿 五道口-知春路-北土城-惠新西街南口-雍和宮-東直門-朝陽門-建國門-國貿 五道口-知春路-北土城-惠新西街南口-雍和宮-東直門-朝陽門-呼家樓-國貿 五道口-知春路-北土城-惠新西街南口-芍葯居-東直門-朝陽門-建國門-國貿 五道口-知春路-北土城-惠新西街南口-芍葯居-東直門-朝陽門-呼家樓-國貿 count:27 最短路程為:五道口-知春路-北土城-惠新西街南口-芍葯居-三元橋-呼家樓-國貿:16.8 程序結束執行時間:20130515115844 812
獻上測試鏈接 點擊我
SF 2013.05.15
END