用SQL解決有向圖問題(轉)
一個常見的高階電腦科學問題可以在“有向圖”的範疇之下描述。有向圖是由一組向量和邊所連線的一組有限的節點。例如,一個節點可以想象為一座“城市”,而每個向量可以想象為兩座城市間的一個“航線”。
有很多演算法和論文講到如何解決每種可能路線的遍歷問題以及尋找最短路徑或者最小代價路徑的問題。這些演算法中大部分都是過程化的,或者是使用遞迴方面來解決的。然而 SQL 的宣告性語言使得解決複雜的有向圖問題更加容易,而且不需要很多程式碼。
讓我們以兩座城市之間的航線為例子,建立一個表儲存一些假想資料:
(
code char(3) constraint airports_pk primary key,
description varchar2(200)
);
insert into airports values ('LHR','London Heathrow, UK');
insert into airports values ('JFK','New York-Kennedy, USA');
insert into airports values ('GRU','Sao Paulo, Brazil');
create table fares
(
depart char(3),
arrive char(3),
price number,
constraint fares_pk primary key (depart,arrive),
constraint fares_depart_fk foreign key (depart) references airports,
constraint fares_arrive_fk foreign key (arrive) references airports
);
insert into fares values('LHR','JFK',700);
insert into fares values('JFK','GRU',600);
insert into fares values('LHR','GRU',1500);
insert into fares values('GRU','LHR',1600);
不能使用CONNECT BY 語法來解決如何從倫敦到聖保羅,因為在圖中有資料產生一個環(從聖保羅飛回):
ERROR:
ORA-01436: CONNECT BY loop in user data
要解決有向圖問題,我們需要建立一個臨時表來儲存兩個節點之間所有可能的路徑。我們必須注意不復制已經處理過的路徑,而且在這種情況下,我們不想路徑走回開始處的同一個地點。我還希望跟蹤到達目的地所需航程的數目,以及所走路線的描述。
臨時表使用以下指令碼建立:
(
depart char(3),
arrive char(3),
hops integer,
route varchar2(30),
price number,
constraint faretemp_pk primary key (depart,arrive)
);
一個簡單的檢視可以在稍微簡化這個例子中使用的程式碼。檢視可以根據 fares 表中的單個航程計算從 faretemp 表中的一個路徑到達一下一個航程的資料:
as
select src.depart,
dst.arrive,
src.hops+1 hops,
src.route||','||dst.arrive route,
src.price + dst.price price
from faretemp src,fares dst
where src.arrive = dst.depart
and dst.arrive != src.depart;
/
show errors;
這個演算法相當簡單。首先,使用 fares 表中的資料填充 faretemp 表,作為初始的航程。然後,取到我們剛才插入的所有資料,使用它們建立所有可能的二航程(two-hop)路徑。重複這一過程,直至在兩個節點之間建立了新路徑。迴圈過程將在節點間所有可能的路徑都被描述之後退出。如果我們只對某個開始條件感興趣,那麼我們還可以限制第一次的插入從而減少裝載資料的量。下面是發現路徑的程式碼:
begin
-- initial connections
insert into faretemp
select depart,arrive,1,depart||','||arrive,price from fares;
while sql%rowcount > 0 loop
insert into faretemp
select depart,arrive,hops,route,price from nexthop
where (depart,arrive)
not in (select depart,arrive from faretemp);
end loop;
end;
/
show errors;
select * from faretemp order by depart,arrive;
可以在表 A 中檢視輸出。
前面的資料有一個小問題。資料是點之間最短路徑(最小航程數)的集合。然而,從倫敦到聖保羅的航程卻不是最便宜的一個。
要解決最便宜的費用問題,需要對我們的迴圈做一個改進,當在一個航程中發現一個更便宜的路線時使用這個路線代替原來的路線。修改後的程式碼如下:
declare
l_count integer;
begin
-- initial connections
insert into faretemp
select depart,arrive,1,depart||','||arrive,price from fares;
l_count := sql%rowcount;
while l_count > 0 loop
update faretemp
set (hops,route,price) =
(select hops,route,price from nexthop
where depart = faretemp.depart
and arrive = faretemp.arrive)
where (depart,arrive) in
(select depart,arrive from nexthop
where price < faretemp.price);
l_count := sql%rowcount;
insert into faretemp
select depart,arrive,hops,route,price from nexthop
where (depart,arrive)
not in (select depart,arrive from faretemp);
l_count := l_count + sql%rowcount;
end loop;
end;
/
show errors;
select * from faretemp order by depart,arrive;
可能在表 B中檢視輸出。
演算法發現LHR、JFK、GRU 路線比 LHR、GRU 路線便宜,所以用前者代替了後者。迴圈將在沒有更便宜的費用,並且沒有其它可能路線時退出。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/756652/viewspace-242154/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- sql多參問題解決SQL
- 瞭解GaussDB效能調優之隱式轉換,解決慢SQL問題SQL
- 【OracleEBS】 訂單暫掛問題sql解決OracleSQL
- Spark SQL中出現 CROSS JOIN 問題解決SparkSQLROS
- 解決圖片訪問403 Forbidden問題ORB
- 如何捕獲問題SQL解決過度CPU消耗的問題SQL
- SQL隱碼攻擊問題以及解決方法SQL
- 什麼是 Flink SQL 解決不了的問題?SQL
- 用STAR模式來解決問題模式
- 用exfe.js和canvas解決移動端 IOS 拍照上傳圖片翻轉問題JSCanvasiOS
- nginx 解決圖片跨域問題Nginx跨域
- Js深度拷貝解決雙向繫結問題JS
- Python 命令跳轉微軟應用商店問題解決辦法Python微軟
- 有獎問題徵集:一鍵解鎖解題祕籍,從向《怎樣解題》作者提問開始
- 兩款工具解決SQL Server遷移問題DJSQLServer
- 【問題解決】使用YYYY-MM-dd時間轉換問題
- 無向圖的最小環問題
- phantomjs截圖中文亂碼問題解決JS
- 解決Hexo關於圖片的問題Hexo
- Windows解決斷後佔用問題Windows
- 用linux man命令,自己解決問題Linux
- 圖 - 有向圖
- No debuggable processes(Android Studio沒有可除錯應用)問題解決方案Android除錯
- WPF 讀取圖片 賦值Image控制元件 解決圖片佔用問題賦值控制元件
- Angular應用解決跨域訪問的問題Angular跨域
- PDF轉圖片部分公式字元丟失問題解決的爬坑記錄公式字元
- JAVA程式設計題-用java解決兔子問題Java程式設計
- 解決zabbix圖形化中文亂碼問題
- 用分散式鎖解決併發問題分散式
- WPS 2019解決不能啟用巨集問題
- 元件複用傳值(待解決問題)元件
- ubuntu下解決埠被佔用問題Ubuntu
- 無向圖的最小環問題[TODO]
- 玩轉dnmp之埠對映問題解決方案
- Laravel 解決blade模板轉義html標籤問題LaravelHTML
- 合約 USDT 轉賬失敗的問題解決
- SQL Server常見問題介紹及快速解決建議SQLServer
- [解決問題] Vagrant nginx 站點配置問題(ThinkPHP HTML 無法調跳轉)NginxPHPHTML