深度優先搜索是一種在開發爬蟲早期使用較多的方法。它的目的是要達到被搜索結構的葉結點(即那些不包含任何超鏈的HTML文件) 。在一個HTML文件中,當一個超鏈被選擇後,被鏈接的HTML文件將執行深度優先搜索,即在搜索其餘的超鏈結果之前必須先完整地搜索單獨的一條鏈。深度優先搜索沿着HTML文件上的超鏈走到不能再深入為止,然後返回到某一個HTML文件,再繼續選擇該HTML文件中的其他超鏈。當不再有其他超鏈可選擇時,說明搜索已經結束。優點是能遍歷一個Web 站點或深層嵌套的文檔集合;缺點是因為Web結構相當深,,有可能造成一旦進去,再也出不來的情況發生。
(進化論密碼按:由於以上一段描述本人不能看懂,所以暫時保留之.)
事實上,深度優先搜索屬於圖算法的一種,英文縮寫為DFS即Depth First Search.其過程簡要來說是對每一個可能的分支路徑深入到不能再深入為止,而且每個節點衹能訪問一次.
舉例說明之:下圖是一個無嚮圖,如果我們從A點發起深度優先搜索(以下的訪問次序並不是唯一的,第二個點既可以是B也可以是C,D),則我們可能得到如下的一個訪問過程:A->B->E(沒有路了!回溯到A)->C->F->H->G->D(沒有路,最終回溯到A,A也沒有未訪問的相鄰節點,本次搜索結束).圖
簡要說明深度優先搜索的特點:每次深度優先搜索的結果必然是圖的一個連通分量.深度優先搜索可以從多點發起.如果將每個節點在深度優先搜索過程中的"結束時間"排序(具體做法是創建一個list,然後在每個節點的相鄰節點都已被訪問的情況下,將該節點加入list結尾,然後逆轉整個鏈表),則我們可以得到所謂的"拓撲排序",即topological sort.
當然,當人們剛剛掌握深度優先搜索的時候常常用它來走迷宮.事實上我們還有別的方法,那就是廣度優先搜索 (BFS).狀態(state):狀態是製問題求解過程中每一步的狀況。
算符(operater)算符是把問題從一種狀態變換到另一種狀態的方法代號。算符的屈指範圍就是搜索的範圍。(一般設為局部變量)。
節點(node):用來表明狀態特徵及相關信息。
在我們遇到的一些問題當中,有些問題我們不能夠確切的找出數學模型,即找不出一種直接求解的方法,解决這一類問題,我們一般采用搜索的方法解决。搜索就是用問題的所有可能去試探,按照一定的順序、規則,不斷去試探,直到找到問題的解,試完了也沒有找到解,那就是無解,試探時一定要試探完所有的情況(實際上就是窮舉);
對於問題的第一個狀態,叫初始狀態,要求的狀態叫目標狀態。
搜索就是把規則應用於實始狀態,在其産生的狀態中,直到得到一個目標狀態為止。
産生新的狀態的過程叫擴展(由一個狀態,應用規則,産生新狀態的過程)
搜索的要點:(1)初始狀態;
(2)重複産生新狀態;
(3)檢查新狀態是否為目標,是結束,否轉(2);
如果搜索是以接近起始狀態的程序依次擴展狀態的,叫寬度優先搜索。
如果擴展是首先擴展新産生的狀態,則叫深度優先搜索。
深度優先搜索 深度優先搜索用一個數組存放産生的所有狀態。
(1) 把初始狀態放入數組中,設為當前狀態;
(2) 擴展當前的狀態,産生一個新的狀態放入數組中,同時把新産生的狀態設為當前狀態;
(3) 判斷當前狀態是否和前面的重複,如果重複則回到上一個狀態,産生它的另一狀態;
(4) 判斷當前狀態是否為目標狀態,如果是目標,則找到一個解答,結束算法。
(5) 如果數組為空,說明無解。
對於pascal語言來講,它支持遞歸,在遞歸時可以自動實現回溯(利用局部變量)所以使用遞歸編寫深度優先搜索程序相對簡單,當然也有非遞歸實現的算法。
現在以這題來舉例(迷宮)
1111010101010111
記錄起點為(1,1)找到所有的到(4,4)的路徑.
程序如下:
const
b:array[1..4,1..4]of integer=((1,1,1,1),(0,1,0,1),(0,1,0,1),(0,1,1,1));
c:array[1..4,1..2]of -1..1=((0,1),(0,-1),(1,0),(-1,0));
var
a:array[1..16,1..2]of integer;
procedure print;
var
i,j:integer;
begin
for i:=1 to 4 do
begin
for j:=1 to 4 do
write(b[i,j]:3);
writeln;
end;
writeln('--------------');
end;
procedure try(k:integer);
var
i:integer;
begin
if (a[k,1]=4)and(a[k,2]=4) then begin print;exit;end;
for i:=1 to 4 do
begin
a[k+1,1]:=a[k,1]+c[i,1];
a[k+1,2]:=a[k,2]+c[i,2];
if (a[k+1,1]>=1)and(a[k+1,1]<=4)and(a[k+1,2]>=1)and(a[k+1,2]<=4)and
(b[a[k+1,1],a[k+1,2]]=1) then begin
b[a[k+1,1],a[k+1,2]]:=2;
try(k+1);
b[a[k+1,1],a[k+1,2]]:=1;
end;
end;
end;
begin
a[1,1]:=1;
a[1,2]:=1;
b[1,1]:=2;
try(1);
end.
這就是說是說進行搜索一條路直到不能走為止,換另一條路.