哨兵,顧名思義,是用來解決國家之間邊界問題的,不直接參與生產活動。
同樣,計算機科學中提到的哨兵,也用來解決邊界問題。
在許多算法中,存在“鄰居依賴問題”(我自己造的詞),在處理當前元素時,要涉及到它旁邊那個元素。那如果當前元素是邊界元素呢,它沒有旁邊那個元素,如果不作處理,程序就可能出錯;如果對它特別對待,就會增加代碼複雜性,還會降低程序效率。應用哨兵,也就是申請若干個多餘的元素作爲邊界元素的鄰居,可以完美得解決這個問題。
下面,我們會舉一些哨兵應用的例子。
鏈表
單鏈表在插入和刪除時,需要修改前驅結點的後繼指針,這就形成了“鄰居依賴”,鏈表中第一個元素沒有前驅結點,如果沒有特殊處理,在插入和刪除第一個結點時,就會出錯。
所以我們可以申請一個頭結點,作爲原本的第一個結點的前驅結點,問題也就解決了。但是在這種方式中,我們要插入或者刪除一個結點時,要知道它的前驅結點地址,這往往是麻煩的。
另一個方式,也是我更喜歡的方式,是申請一個尾結點,作爲原本最後一個結點的後繼結點。
要刪除某個元素時,我們不刪除當前這個結點,而是用後繼結點的數據覆蓋當前結點的數據,再刪除後繼結點。這種方式,不需要訪問前驅結點,也就解決了獲取前驅結點的困難。插入元素也是同理。而最後一個結點沒有後繼結點,所以需要一個尾結點作爲哨兵。
如果用的是雙鏈表,就需要在頭尾各加一個哨兵。
其它
在插入排序和歸併排序中,使用一個值爲無窮大或者負無窮大的哨兵元素,能降低代碼複雜性,提高程序運行效率。
在二叉樹中,插入刪除元素時也會表現出“鄰居依賴”,也可以通過哨兵解決。
在n*m的矩形區域中,例如掃雷,一個點擊方塊時,要掃描周圍8個方塊的雷數,而邊界方塊的周圍不足8個方塊,一種解決方法就是在有效矩形區域的周圍,添加一圈的方塊,
但這個方法申請的哨兵數量有點多,數量是2n+2m-4,在實踐中應該酌情考慮。
可以使用哨兵的地方還有很多,只要存在“鄰居依賴”的地方,就可以考慮使用哨兵。