欧拉七桥问题
歐拉七橋問題
把一塊連通的陸地作為一個頂點,每一座橋當成圖的一條邊,那么就把哥尼斯堡的七座橋抽象成圖中所示
對于圖中的每一個頂點,將與之相連的邊的數量定義為它的度(Degree)
定理:如果一個圖能夠從一個頂點出發, 每條邊不重復地遍歷一遍回到這個頂點,那么每一頂點的度必須為偶數。
證明:假如能夠遍歷圖的每條邊各一次, 那么對于每個頂點,需要從
某條邊進人頂點,同時從另一條邊離開這個頂點。進人和離開頂點的次
數是相同的,因此每個頂點有多少條進入的邊,就有多少條出去的邊。
也就是說,每個頂點相連的邊的數量是成對出現的,即每個頂點的度都
是偶數。
在圖9.5中,有多個頂點的度為奇數,因此,這個圖無法從一個頂點出發,
遍歷每條邊各一次然后回到這個頂點。
構建網絡爬蟲的工程要點
“如何構建一個網絡爬蟲”Google常用的一道面試題。
網絡爬蟲在工程實現上要考慮的細節非常多,其中大的方面有這樣幾點。
首先,用BFS?還是DFS?
雖然從理論上講,這兩個算法(在不考慮時間因素的前提下)都能夠在大致相同的時間里“爬下”整個“靜態”互聯網上的內容,但是工程上的兩個假設——不考慮時間因素,互聯網靜態不變,都是現實中做不到的。搜索引擎的網絡
爬蟲問題更應該定義成“如何在有限時間里最多地爬下最重要的網頁”。顯然各個網站最重要的網頁應該是它的首頁。在最極端的情況下,如果爬蟲非常小,只能下載非常有限的網頁,那么應該下載的是所有網站的首頁,如果把爬蟲再擴大些,應該爬下從首頁直接鏈接的網頁(就如同和北京直接相連的城市),因為這些網頁是網站設計者自認為相當重要的網頁。在這個前提下,顯然BFS明顯優于DFS。事實上在搜索引擎的爬蟲,雖然不是簡單地采用BFS,但是先爬哪個網頁,后爬哪個網頁的調度程序,原理上基本上是BFS。
那么是否DFS就不使用了呢?也不是這樣的。這跟爬蟲的分布式結構以及網絡通信的握手成本有關。所謂“握手”就是指下載服務器和網站的服務器建立通信的過程。這個過程需要額外的時間(Overhead Time )如果握手的次數太多,下載的效率就降低了。實際的網絡爬蟲都是由成百上千甚至成干上萬臺服務器組成的分布式系統。對于某個網站,一般是由特定的一 一臺或者幾臺服務器專門下載。 這些服務器下載完網站,然后再進人下一個網站,而不是每個網站先輪流下載5%,然后回過頭來下載第二批,這樣可以避免握手的次數太多。要是下載完第個網站再下載第二個,那么這又有點像DFS,雖然下載同一個網站(或者子網站)時,還是需要用BFS的。
總結起來,網絡爬蟲對網頁通歷的次序不是簡單的BFS或者DFS有一個相對復雜的下載優先級排序的方法。管理這個優先級排用序的子系統般稱為調度系統 (Scheduler),由它來決定當一個網頁下載完成后,接下來下載哪個當然在調用系統里需要存儲那些已經發現但是尚未下載的網頁的URL,它們一般存在一個優先級隊列 ( Priorty Queue)里。而用這種方式遍歷整個互聯網,在工程上和BFS更相似。因此,在爬蟲中,BFS的成分多一些。
第二,頁面的分析和URL的提取。
在上一部分中提到,當一個網頁下載完成后,需要從這個網頁中提取其中的URL。把它們加入到下載的隊列中。這個工作在互聯網的早期不難,因為那時的網頁都是直接用HTML語言書寫的。那些URL都以文本的形式放在網頁中,前后都有明顯的標識,很容易提取出來。但是現在很多URL的提取就不那么直接了,因為很多網頁如今是用一些腳本語言(比如JavaScript) 生成的。打開網頁的源代碼,URL不是直接可見的文本,而是運行這一段腳本后才能得到的結果。因此,網絡爬蟲的頁面分析就變得復雜很多,它要模擬瀏覽器運行一個網頁,才能得到里面隱含的URL。有些網頁的腳本寫得非常不規范,以至于解析起來非常困難。可是,這些網頁還是可以在瀏覽器中打開,說明瀏覽器可以解析。因此,需要做瀏覽器內核的工程師來寫網絡爬蟲中的解析程序,可惜出色的瀏覽器內核工程師在全世界數量并不多。因此,若你發現些網頁明明存在,但搜索引擎就是沒有收錄,一個可能的原因是網絡爬蟲中的解析程序沒能成功解析網頁中不規范的腳本程序。
第三,記錄哪些網頁已經下載過的小本本——URL表。
在互聯網上,一個網頁可能被多個網頁中的超鏈接所指向,即在互聯網這張大圖上,有很多弧(鏈接)可以走到這個節點(網頁)。這樣在遍歷互聯網這張圖時,這個網頁可能被多次訪問到。為了防止一個網頁被下載多次,我們可以用個哈希表記錄哪些網頁已經下載過。再遇到這我們就可以跳過它。采用哈希表的好處是,判斷一個網頁的URL是否在表中,平均只需一次(或者略多的)查找。當然。如果遇到還未下載的網頁。除了下載該網頁,還要適時將這個網頁的URL存入哈希表中,這個操作對哈希表來講也非常簡單。在一臺下載服務器上建立和維護一張哈希表并不是難事。但是如果同時有上千臺服務器一起下載網頁。維護一張統一的哈希表就不那么簡單了。 首先,這張哈希表會大到一臺服務器存儲不下。其次,由于每個下載服務器在開始下載前和完成下載后都要訪問和維護這張表,以免不同的服務器做重復的工作,這
個存儲哈希表的服務器的通信就成了整個爬蟲系統的瓶頸。
這里有各種解決辦法,沒有絕對正確的,但是卻也有好壞之分。好的方法都采用了這樣兩個技術: 首先明確每臺下載服務器的分工,也就是說在調度時一看到某個URL就知道要交給哪臺服務器去下載,以免很多服務器都要重重復判斷某個URL是否需要下載。然后,在明確分工的基礎上,判斷URL是否下載就可以批處理了,比如每次向哈希表(一組獨立的服務器)發送一大批詢問, 或者每次更新一批哈希表的內容。 這樣通信的次數就大大減少了。
轉載于:《數學之美》
總結
- 上一篇: QuickCHM V2.6注册码
- 下一篇: 高斯定理在神经网络上的投影