搜索演算法的實現
❶ C語言題目: 搜索演算法的設計與實現
呵呵什麼時候截止?可以嘗試完成,
❷ 搜索引擎中索引時怎麼實現的
隨著互聯網的迅猛發展、WEB信息的增加,用戶要在信息海洋里查找自己所需的信息,就象大海撈針一樣,搜索引擎技術恰好解決了這一難題(它可以為用戶提供信息檢索服務)。搜索引擎是指互聯網上專門提供檢索服務的一類網站,這些站點的伺服器通過網路搜索軟體(例如網路搜索機器人)或網路登錄等方式,將Intemet上大量網站的頁面信息收集到本地,經過加工處理建立信息資料庫和索引資料庫,從而對用戶提出的各種檢索作出響應,提供用戶所需的信息或相關指針。用戶的檢索途徑主要包括自由詞全文檢索、關鍵詞檢索、分類檢索及其他特殊信息的檢索(如企業、人名、電話黃頁等)。下面以網路搜索機器人為例來說明搜索引擎技術。
1.網路機器人技術
網路機器人(Robot)又被稱作Spider、Worm或Random,核心目的是為獲取Intemet上的信息。一般定義為「一個在網路上檢索文件且自動跟蹤該文件的超文本結構並循環檢索被參照的所有文件的軟體」。機器人利用主頁中的超文本鏈接遍歷WWW,通過U趾引用從一個HT2LIL文檔爬行到另一個HTML文檔。網上機器人收集到的信息可有多種用途,如建立索引、HIML文件合法性的驗證、uRL鏈接點驗證與確認、監控與獲取更新信息、站點鏡像等。
機器人安在網上爬行,因此需要建立一個URL列表來記錄訪問的軌跡。它使用超文本,指向其他文檔的URL是隱藏在文檔中,需要從中分析提取URL,機器人一般都用於生成索引資料庫。所有WWW的搜索程序都有如下的工作步驟:
(1)機器人從起始URL列表中取出URL並從網上讀取其指向的內容;
(2)從每一個文檔中提取某些信息(如關鍵字)並放入索引資料庫中;
(3)從文檔中提取指向其他文檔的URL,並加入到URL列表中;
(4)重復上述3個步驟,直到再沒有新的URL出現或超出了某些限制(時間或磁碟空間);
(5)給索引資料庫加上檢索介面,向網上用戶發布或提供給用戶檢索。
搜索演算法一般有深度優先和廣度優先兩種基本的搜索策略。機器人以URL列表存取的方式決定搜索策略:先進先出,則形成廣度優先搜索,當起始列表包含有大量的WWW伺服器地址時,廣度優先搜索將產生一個很好的初始結果,但很難深入到伺服器中去;先進後出,則形成深度優先搜索,這樣能產生較好的文檔分布,更容易發現文檔的結構,即找到最大數目的交叉引用。也可以採用遍歷搜索的方法,就是直接將32位的IP地址變化,逐個搜索整個Intemet。
搜索引擎是一個技術含量很高的網路應用系統。它包括網路技術、資料庫技術動標引技術、檢索技術、自動分類技術,機器學習等人工智慧技術。
2.索引技術
索引技術是搜索引擎的核心技術之一。搜索引擎要對所收集到的信息進行整理、分類、索引以產生索引庫,而中文搜索引擎的核心是分詞技術。分詞技術是利用一定的規則和詞庫,切分出一個句子中的詞,為自動索引做好准備。目前的索引多採用Non—clustered方法,該技術和語言文字的學問有很大的關系,具體有如下幾點:
(1)存儲語法庫,和詞彙庫配合分出句子中的詞彙;
(2)存儲詞彙庫,要同時存儲詞彙的使用頻率和常見搭配方式;
(3)詞彙寬,應可劃分為不同的專業庫,以便於處理專業文獻;
(4)對無法分詞的句子,把每個字當作詞來處理。
索引器生成從關鍵詞到URL的關系索引表。索引表一般使用某種形式的倒排表(1nversionUst),即由索引項查找相應的URL。索引表也要記錄索引項在文檔中出現的位置,以便檢索器計算索引項之間的相鄰關系或接近關系,並以特定的數據結構存儲在硬碟上。
不同的搜索引擎系統可能採用不盡相同的標引方法。例如Webcrawler利用全文檢索技術,對網頁中每一個單詞進行索引;Lycos只對頁名、標題以及最重要的100個注釋詞等選擇性詞語進行索引;Infoseek則提供概念檢索和片語檢索,支持and、or、near、not等布爾運算。檢索引擎的索引方法大致可分為自動索引、手工索引和用戶登錄三類。
3. 檢索器與結果處理技術
檢索器的主要功能是根據用戶輸入的關鍵詞在索引器形成的倒排表中進行檢索,同時完成頁面與檢索之間的相關度評價,對將要輸出的結果進行排序,並實現某種用戶相關性反饋機制。
通過搜索引擎獲得的檢索結果往往成百上千,為了得到有用的信息,常用的方法是按網頁的重要性或相關性給網頁評級,進行相關性排序。這里的相關度是指搜索關鍵字在文檔中出現的額度。當額度越高時,則認為該文檔的相關程度越高。能見度也是常用的衡量標准之一。一個網頁的能見度是指該網頁入口超級鏈接的數目。能見度方法是基於這樣的觀點:一個網頁被其他網頁引用得越多,則該網頁就越有價值。特別地,一個網頁被越重要的網頁所引用,則該網頁的重要程度也就越高。結果處理技術可歸納為:
(1)按頻次排定次序 通常,如果一個頁麵包含了越多的關鍵詞,其搜索目標的相關性應該越好,這是非常合平常理的解決方案。
(2)按頁面被訪問度排序 在這種方法中,搜索引擎會記錄它所搜索到的頁面被訪問的頻率。人們訪問較多的頁面通常應該包含比較多的信息,或者有其他吸引入的長處。這種解決方案適合一般的搜索用戶,而因為大部分的搜索引擎都不是專業性用戶,所以這種方案也比較適合一般搜索引擎使用。
(3)二次檢索 進一步凈化(比flne)結果,按照一定的條件對搜索結果進行優化,可以再選擇類別、相關詞進行二次搜索等。
由於目前的搜索引擎還不具備智能,除非知道要查找的文檔的標題,否則排列第一的結果未必是「最好」的結果。所以有些文檔盡管相關程度高,但並不一定是用戶最需要的文檔。
搜索引擎技術的行業應用:
搜索引擎的行業應用一般指類似於千瓦通信提供的多種搜索引擎行業與產品應用模式,大體上分為如下幾種形式:
1、 政府機關行業應用
n 實時跟蹤、採集與業務工作相關的信息來源。
n 全面滿足內部工作人員對互聯網信息的全局觀測需求。
n 及時解決政務外網、政務內網的信息源問題,實現動態發布。
n 快速解決政府主網站對各地級子網站的信息獲取需求。
n 全面整合信息,實現政府內部跨地區、跨部門的信息資源共享與有效溝通。
n 節約信息採集的人力、物力、時間,提高辦公效率。
2、企業行業應用
n 實時准確地監控、追蹤競爭對手動態,是企業獲取競爭情報的利器。
n 及時獲取競爭對手的公開信息以便研究同行業的發展與市場需求。
n 為企業決策部門和管理層提供便捷、多途徑的企業戰略決策工具。
n 大幅度地提高企業獲取、利用情報的效率,節省情報信息收集、存儲、挖掘的相關費用,是提高企業核心競爭力的關鍵。
n 提高企業整體分析研究能力、市場快速反應能力,建立起以知識管理為核心的競爭情報數據倉庫,是提高企業核心競爭力的神經中樞。
3、新聞媒體行業應用
n 快速准確地自動跟蹤、採集數千家網路媒體信息,擴大新聞線索,提高採集速度。
n 支持每天對數萬條新聞進行有效抓取。監控范圍的深度、廣度可以自行設定。
n 支持對所需內容智能提取、審核。
n 實現互聯網信息內容採集、瀏覽、編輯、管理、發布的一體化。
4、 行業網站應用
n 實時跟蹤、採集與網站相關的信息來源。
n 及時跟蹤行業的信息來源網站,自動,快速更新網站信息。動態更新信息。
n 實現互聯網信息內容採集、瀏覽、編輯、管理、發布的一體化。
n 針對商務網站提出商務管理模式,大大提高行業網站的商務應用需求。
n 針對資訊網站分類目錄生成,提出用戶生成網站分類結構。並可以實時增加與更新分類結構。不受級數限制。從而大大利高行業的應用性。
n 提供搜索引擎SEO優化專業服務,快速提高行業網站的推廣。
n 提供與CCDC呼叫搜索引擎的廣告合作。建立行業網站聯盟,提高行業網站知名度。
5) 網路信息監察與監控
n 網路輿情系統。如「千瓦通信-網路輿情雷達監測系統」
n 網站信息與內容監察與監控系統,如「千瓦通信-網站信息與內容監測與監察系統(站內神探)」
隨著網際網路的迅猛發展、WEB信息的增加,用戶要在信息海洋里查找信息,就象大海撈
針一樣,搜索引擎技術恰好解決了這一難題(它可以為用戶提供信息檢索服務)。目前,
搜索引擎技術正成為計算機工業界和學術界爭相研究、開發的對象。
搜索引擎(Search Engine)是隨著WEB信息的迅速增加,從1995年開始逐漸發展起來
的技術。據發表在《科學》雜志1999年7月的文章《WEB信息的可訪問性》估計,全球目前
的網頁超過8億,有效數據超過9T,並且仍以每4個月翻一番的速度增長。用戶要在如此浩
瀚的信息海洋里尋找信息,必然會"大海撈針"無功而返。搜索引擎正是為了解決這個"迷航
"問題而出現的技術。搜索引擎以一定的策略在互聯網中搜集、發現信息,對信息進行理解
、提取、組織和處理,並為用戶提供檢索服務,從而起到信息導航的目的。搜索引擎提供
的導航服務已經成為互聯網上非常重要的網路服務,搜索引擎站點也被美譽為"網路門戶"
。搜索引擎技術因而成為計算機工業界和學術界爭相研究、開發的對象。本文旨在對搜索
引擎的關鍵技術進行簡單的介紹,以起到拋磚引玉的作用。
分 類
按照信息搜集方法和服務提供方式的不同,搜索引擎系統可以分為三大類:
1.目錄式搜索引擎:以人工方式或半自動方式搜集信息,由編輯員查看信息之後,人
工形成信息摘要,並將信息置於事先確定的分類框架中。信息大多面向網站,提供目錄瀏
覽服務和直接檢索服務。該類搜索引擎因為加入了人的智能,所以信息准確、導航質量高
,缺點是需要人工介入、維護量大、信息量少、信息更新不及時。這類搜索引擎的代表是
:Yahoo、LookSmart、Open Directory、Go Guide等。
2.機器人搜索引擎:由一個稱為蜘蛛(Spider)的機器人程序以某種策略自動地在互
聯網中搜集和發現信息,由索引器為搜集到的信息建立索引,由檢索器根據用戶的查詢輸
入檢索索引庫,並將查詢結果返回給用戶。服務方式是面向網頁的全文檢索服務。該類搜
索引擎的優點是信息量大、更新及時、毋需人工干預,缺點是返回信息過多,有很多無關
信息,用戶必須從結果中進行篩選。這類搜索引擎的代表是:AltaVista、Northern Ligh
t、Excite、Infoseek、Inktomi、FAST、Lycos、Google;國內代表為:"天網"、悠遊、O
penFind等。
3.元搜索引擎:這類搜索引擎沒有自己的數據,而是將用戶的查詢請求同時向多個搜
索引擎遞交,將返回的結果進行重復排除、重新排序等處理後,作為自己的結果返回給用
戶。服務方式為面向網頁的全文檢索。這類搜索引擎的優點是返回結果的信息量更大、更
全,缺點是不能夠充分使用所使用搜索引擎的功能,用戶需要做更多的篩選。這類搜索引
擎的代表是WebCrawler、InfoMarket等。
性 能 指 標
我們可以將WEB信息的搜索看作一個信息檢索問題,即在由WEB網頁組成的文檔庫中檢索
出與用戶查詢相關的文檔。所以我們可以用衡量傳統信息檢索系統的性能參數-召回率(R
ecall)和精度(Pricision)衡量一個搜索引擎的性能。
召回率是檢索出的相關文檔數和文檔庫中所有的相關文檔數的比率,衡量的是檢索系
統(搜索引擎)的查全率;精度是檢索出的相關文檔數與檢索出的文檔總數的比率,衡量
的是檢索系統(搜索引擎)的查准率。對於一個檢索系統來講,召回率和精度不可能兩全
其美:召回率高時,精度低,精度高時,召回率低。所以常常用11種召回率下11種精度的
平均值(即11點平均精度)來衡量一個檢索系統的精度。對於搜索引擎系統來講,因為沒
有一個搜索引擎系統能夠搜集到所有的WEB網頁,所以召回率很難計算。目前的搜索引擎系
統都非常關心精度。
影響一個搜索引擎系統的性能有很多因素,最主要的是信息檢索模型,包括文檔和查詢
的表示方法、評價文檔和用戶查詢相關性的匹配策略、查詢結果的排序方法和用戶進行相
關度反饋的機制。
主 要 技 術
一個搜索引擎由搜索器、索引器、檢索器和用戶介面等四個部分組成。
1.搜索器
搜索器的功能是在互聯網中漫遊,發現和搜集信息。它常常是一個計算機程序,日夜
不停地運行。它要盡可能多、盡可能快地搜集各種類型的新信息,同時因為互聯網上的信
息更新很快,所以還要定期更新已經搜集過的舊信息,以避免死連接和無效連接。目前有
兩種搜集信息的策略:
● 從一個起始URL集合開始,順著這些URL中的超鏈(Hyperlink),以寬度優先、深
度優先或啟發式方式循環地在互聯網中發現信息。這些起始URL可以是任意的URL,但常常
是一些非常流行、包含很多鏈接的站點(如Yahoo!)。
● 將Web空間按照域名、IP地址或國家域名劃分,每個搜索器負責一個子空間的窮盡
搜索。 搜索器搜集的信息類型多種多樣,包括HTML、XML、Newsgroup文章、FTP文件、
字處理文檔、多媒體信息。 搜索器的實現常常用分布式、並行計算技術,以提高信息
發現和更新的速度。商業搜索引擎的信息發現可以達到每天幾百萬網頁。
2.索引器
索引器的功能是理解搜索器所搜索的信息,從中抽取出索引項,用於表示文檔以及生
成文檔庫的索引表。
索引項有客觀索引項和內容索引項兩種:客觀項與文檔的語意內容無關,如作者名、
URL、更新時間、編碼、長度、鏈接流行度(Link Popularity)等等;內容索引項是用來
反映文檔內容的,如關鍵詞及其權重、短語、單字等等。內容索引項可以分為單索引項和
多索引項(或稱短語索引項)兩種。單索引項對於英文來講是英語單詞,比較容易提取,
因為單詞之間有天然的分隔符(空格);對於中文等連續書寫的語言,必須進行詞語的切
分。 在搜索引擎中,一般要給單索引項賦與一個權值,以表示該索引項對文檔的區分
度,同時用來計算查詢結果的相關度。使用的方法一般有統計法、資訊理論法和概率法。短
語索引項的提取方法有統計法、概率法和語言學法。
索引表一般使用某種形式的倒排表(Inversion List),即由索引項查找相應的文檔
。索引表也可能要記錄索引項在文檔中出現的位置,以便檢索器計算索引項之間的相鄰或
接近關系(proximity)。
索引器可以使用集中式索引演算法或分布式索引演算法。當數據量很大時,必須實現即時
索引(Instant Indexing),否則不能夠跟上信息量急劇增加的速度。索引演算法對索引器
的性能(如大規模峰值查詢時的響應速度)有很大的影響。一個搜索引擎的有效性在很大
程度上取決於索引的質量。
3.檢索器 檢索器的功能是根據用戶的查詢在索引庫中快速檢出文檔,進行文檔與
查詢的相關度評價,對將要輸出的結果進行排序,並實現某種用戶相關性反饋機制。
檢索器常用的信息檢索模型有集合理論模型、代數模型、概率模型和混合模型四種。
4.用戶介面
用戶介面的作用是輸入用戶查詢、顯示查詢結果、提供用戶相關性反饋機制。主要的
目的是方便用戶使用搜索引擎,高效率、多方式地從搜索引擎中得到有效、及時的信息。
用戶介面的設計和實現使用人機交互的理論和方法,以充分適應人類的思維習慣。
用戶輸入介面可以分為簡單介面和復雜介面兩種。
簡單介面只提供用戶輸入查詢串的文本框;復雜介面可以讓用戶對查詢進行限制,如
邏輯運算(與、或、非;+、-)、相近關系(相鄰、NEAR)、域名范圍(如.e、.com)
、出現位置(如標題、內容)、信息時間、長度等等。目前一些公司和機構正在考慮制定
查詢選項的標准。
未 來 動 向
搜索引擎已成為一個新的研究、開發領域。因為它要用到信息檢索、人工智慧、計算
機網路、分布式處理、資料庫、數據挖掘、數字圖書館、自然語言處理等多領域的理論和
技術,所以具有綜合性和挑戰性。又由於搜索引擎有大量的用戶,有很好的經濟價值,所
以引起了世界各國計算機科學界和信息產業界的高度關注,目前的研究、開發十分活躍,
並出現了很多值得注意的動向。
1.十分注意提高信息查詢結果的精度,提高檢索的有效性 用戶在搜索引擎上進行
信息查詢時,並不十分關注返回結果的多少,而是看結果是否和自己的需求吻合。對於一
個查詢,傳統的搜索引擎動輒返回幾十萬、幾百萬篇文檔,用戶不得不在結果中篩選。解
決查詢結果過多的現象目前出現了幾種方法:一是通過各種方法獲得用戶沒有在查詢語句
中表達出來的真正用途,包括使用智能代理跟蹤用戶檢索行為,分析用戶模型;使用相關
度反饋機制,使用戶告訴搜索引擎哪些文檔和自己的需求相關(及其相關的程度),哪些
不相關,通過多次交互逐步求精。二是用正文分類(Text Categorization)技術將結果分
類,使用可視化技術顯示分類結構,用戶可以只瀏覽自己感興趣的類別。三是進行站點類
聚或內容類聚,減少信息的總量。
2.基於智能代理的信息過濾和個性化服務
信息智能代理是另外一種利用互聯網信息的機制。它使用自動獲得的領域模型(如We
b知識、信息處理、與用戶興趣相關的信息資源、領域組織結構)、用戶模型(如用戶背景
、興趣、行為、風格)知識進行信息搜集、索引、過濾(包括興趣過濾和不良信息過濾)
,並自動地將用戶感興趣的、對用戶有用的信息提交給用戶。智能代理具有不斷學習、適
應信息和用戶興趣動態變化的能力,從而提供個性化的服務。智能代理可以在用戶端進行
,也可以在伺服器端運行。
3.採用分布式體系結構提高系統規模和性能
搜索引擎的實現可以採用集中式體系結構和分布式體系結構,兩種方法各有千秋。但
當系統規模到達一定程度(如網頁數達到億級)時,必然要採用某種分布式方法,以提高
系統性能。搜索引擎的各個組成部分,除了用戶介面之外,都可以進行分布:搜索器可以
在多台機器上相互合作、相互分工進行信息發現,以提高信息發現和更新速度;索引器可
以將索引分布在不同的機器上,以減小索引對機器的要求;檢索器可以在不同的機器上.
❸ 請問什麼是搜索演算法
搜索演算法是利用計算機的高性能來有目的的窮舉一個問題的部分或所有的可能情況,從而求出問題的解
的一種方法。搜索過程實際上是根據初始條件和擴展規則構造一棵解答樹並尋找符合目標狀態的節點的過程。
所有的搜索演算法從其最終的演算法實現上來看,都可以劃分成兩個部分——控制結構和產生系統,而所有的算
法的優化和改進主要都是通過修改其控制結構來完成的。
❹ 實現二分搜索演算法,並分析其時間復雜度
對於這樣一個謂詞f(),滿足性質:若f(a)=true,則對於任意定義域內的b>a,f(b)=true.
l與r為值域
int work ( int begin , int end ) {
while ( end - begin != 1 ) {
const int middle = ( begin + end ) / 2 ;
if ( f ( middle ) ) end = middle ;
else begin = middle ;
}
return begin ;
}
返回的是最大的x使f(x)為否
❺ 二分搜索演算法的實現
二分搜索的時候,是要慢慢縮小搜索范圍的。比如一共有10個,那麼middle是5,下一層搜索的范圍應該是1-4和6-10。你的函數里沒有這個功能。搜索函數至少應該是int BinarySearch(Type a[], const Type& x,int left, int right);終止條件就是if(left > right) 你定義y的時候是在main函數里,所以BinarySearch裡面不能直接用y,解決方式是在外部定義一個全局的y變數,或者把y變數傳到函數里。
❻ C語言遞歸函數如何實現二分搜索演算法
折半查找法也稱為二分查找法,它充分利用了元素間的次序關系,採用分治策略,可在最壞的情況下用O(log n)完成搜索任務。它的基本思想是,已知一個有n個元素的有序序列, 將n個元素分成個數大致相同的兩半,取a[n/2]與欲查找的x作比較,如果x=a[n/2]則找到x,演算法終止。如果x<a[n/2],則我們只要在數組a的左半部繼續搜索x(這里假設數組元素呈升序排列)。如果x>a[n/2],則我們只要在數組a的右半部繼續搜索x, 直到找到x或者是沒有找到!
如果是常規的方法的話那麼我們可以通過循環的方式, 按照上面說的演算法, 找到則退出循環, 否則繼續循環直到左下標位置小於或者等於右下標的位置.
按兄弟你的意思是要用遞歸方法進行搜索, 那麼大概還是上面的演算法, 只是把循環的方式改成遞歸方式: 如果沒找到,則確定新的搜索范圍, 即左右下標新位置, 然後把新的參數傳給函數繼續調用函數進行遞歸搜索!!
遞歸方式實現詳細代碼如下:
#include <stdio.h>
#define ARRAY_SIZE 10
#define NOT_FOUND -1
int BinarySearch(int array[], int left, int right, int NumToSearch)
{
int mid = (left + right) / 2;
if (left <= right)
{
if (NumToSearch == array[mid])
{
return mid;
}
else if (NumToSearch < array[mid])
{
right = mid - 1;
return BinarySearch(array, left, right, NumToSearch);
}
else
{
left = mid + 1;
return BinarySearch(array, left, right, NumToSearch);
}
}
return NOT_FOUND;
}
int main()
{
int a[ARRAY_SIZE] = {2, 5, 6, 7, 13, 20, 22, 27, 112, 222};//假設一個已知的有序且是升序數列
int result = 0;//查找的結果
int x = 13;//假設我們要查找的數是13
int left = 0;//序列開始下標
int right = ARRAY_SIZE - 1;//序列結尾下標
result = BinarySearch(a, left, right, x);
if (result == NOT_FOUND)
{
printf("Not Found!\n");
}
else
{
printf("Found %d in array a, it is a[%d]\n", x, result);
}
return 0;
}
希望對兄弟你有幫助!
❼ A*搜尋演算法的代碼實現(C語言實現)
用C語言實現A*最短路徑搜索演算法,作者 Tittup frog(跳跳蛙)。 #include<stdio.h>#include<math.h>#defineMaxLength100 //用於優先隊列(Open表)的數組#defineHeight15 //地圖高度#defineWidth20 //地圖寬度#defineReachable0 //可以到達的結點#defineBar1 //障礙物#definePass2 //需要走的步數#defineSource3 //起點#defineDestination4 //終點#defineSequential0 //順序遍歷#defineNoSolution2 //無解決方案#defineInfinity0xfffffff#defineEast(1<<0)#defineSouth_East(1<<1)#defineSouth(1<<2)#defineSouth_West(1<<3)#defineWest(1<<4)#defineNorth_West(1<<5)#defineNorth(1<<6)#defineNorth_East(1<<7)typedefstruct{ signedcharx,y;}Point;constPointdir[8]={ {0,1},//East {1,1},//South_East {1,0},//South {1,-1},//South_West {0,-1},//West {-1,-1},//North_West {-1,0},//North {-1,1}//North_East};unsignedcharwithin(intx,inty){ return(x>=0&&y>=0 &&x<Height&&y<Width);}typedefstruct{ intx,y; unsignedcharreachable,sur,value;}MapNode;typedefstructClose{ MapNode*cur; charvis; structClose*from; floatF,G; intH;}Close;typedefstruct//優先隊列(Open表){ intlength; //當前隊列的長度 Close*Array[MaxLength]; //評價結點的指針}Open;staticMapNodegraph[Height][Width];staticintsrcX,srcY,dstX,dstY; //起始點、終點staticCloseclose[Height][Width];//優先隊列基本操作voidinitOpen(Open*q) //優先隊列初始化{ q->length=0; //隊內元素數初始為0}voidpush(Open*q,Closecls[Height][Width],intx,inty,floatg){ //向優先隊列(Open表)中添加元素 Close*t; inti,mintag; cls[x][y].G=g; //所添加節點的坐標 cls[x][y].F=cls[x][y].G+cls[x][y].H; q->Array[q->length++]=&(cls[x][y]); mintag=q->length-1; for(i=0;i<q->length-1;i++) { if(q->Array[i]->F<q->Array[mintag]->F) { mintag=i; } } t=q->Array[q->length-1]; q->Array[q->length-1]=q->Array[mintag]; q->Array[mintag]=t; //將評價函數值最小節點置於隊頭}Close*shift(Open*q){ returnq->Array[--q->length];}//地圖初始化操作voidinitClose(Closecls[Height][Width],intsx,intsy,intdx,intdy){ //地圖Close表初始化配置 inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { cls[i][j].cur=&graph[i][j]; //Close表所指節點 cls[i][j].vis=!graph[i][j].reachable; //是否被訪問 cls[i][j].from=NULL; //所來節點 cls[i][j].G=cls[i][j].F=0; cls[i][j].H=abs(dx-i)+abs(dy-j); //評價函數值 } } cls[sx][sy].F=cls[sx][sy].H; //起始點評價初始值 // cls[sy][sy].G=0; //移步花費代價值 cls[dx][dy].G=Infinity;}voidinitGraph(constintmap[Height][Width],intsx,intsy,intdx,intdy){ //地圖發生變化時重新構造地 inti,j; srcX=sx; //起點X坐標 srcY=sy; //起點Y坐標 dstX=dx; //終點X坐標 dstY=dy; //終點Y坐標 for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { graph[i][j].x=i;//地圖坐標X graph[i][j].y=j;//地圖坐標Y graph[i][j].value=map[i][j]; graph[i][j].reachable=(graph[i][j].value==Reachable); //節點可到達性 graph[i][j].sur=0;//鄰接節點個數 if(!graph[i][j].reachable) { continue; } if(j>0) { if(graph[i][j-1].reachable) //left節點可以到達 { graph[i][j].sur|=West; graph[i][j-1].sur|=East; } if(i>0) { if(graph[i-1][j-1].reachable &&graph[i-1][j].reachable &&graph[i][j-1].reachable) //up-left節點可以到達 { graph[i][j].sur|=North_West; graph[i-1][j-1].sur|=South_East; } } } if(i>0) { if(graph[i-1][j].reachable) //up節點可以到達 { graph[i][j].sur|=North; graph[i-1][j].sur|=South; } if(j<Width-1) { if(graph[i-1][j+1].reachable &&graph[i-1][j].reachable &&map[i][j+1]==Reachable)//up-right節點可以到達 { graph[i][j].sur|=North_East; graph[i-1][j+1].sur|=South_West; } } } } }}intbfs(){ inttimes=0; inti,curX,curY,surX,surY; unsignedcharf=0,r=1; Close*p; Close*q[MaxLength]={&close[srcX][srcY]}; initClose(close,srcX,srcY,dstX,dstY); close[srcX][srcY].vis=1; while(r!=f) { p=q[f]; f=(f+1)%MaxLength; curX=p->cur->x; curY=p->cur->y; for(i=0;i<8;i++) { if(!(p->cur->sur&(1<<i))) { continue; } surX=curX+dir[i].x; surY=curY+dir[i].y; if(!close[surX][surY].vis) { close[surX][surY].from=p; close[surX][surY].vis=1; close[surX][surY].G=p->G+1; q[r]=&close[surX][surY]; r=(r+1)%MaxLength; } } times++; } returntimes;}intastar(){ //A*演算法遍歷 //inttimes=0; inti,curX,curY,surX,surY; floatsurG; Openq;//Open表 Close*p; initOpen(&q); initClose(close,srcX,srcY,dstX,dstY); close[srcX][srcY].vis=1; push(&q,close,srcX,srcY,0); while(q.length) { //times++; p=shift(&q); curX=p->cur->x; curY=p->cur->y; if(!p->H) { returnSequential; } for(i=0;i<8;i++) { if(!(p->cur->sur&(1<<i))) { continue; } surX=curX+dir[i].x; surY=curY+dir[i].y; if(!close[surX][surY].vis) { close[surX][surY].vis=1; close[surX][surY].from=p; surG=p->G+sqrt((curX-surX)*(curX-surX)+(curY-surY)*(curY-surY)); push(&q,close,surX,surY,surG); } } } //printf("times:%d ",times); returnNoSolution;//無結果}constintmap[Height][Width]={ {0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,1}, {0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1}, {0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,1}, {0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1}, {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}, {0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0}, {0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1}, {0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}};constcharSymbol[5][3]={"□","▓","▽","☆","◎"};voidprintMap(){ inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { printf("%s",Symbol[graph[i][j].value]); } puts(""); } puts("");}Close*getShortest(){ //獲取最短路徑 intresult=astar(); Close*p,*t,*q=NULL; switch(result) { caseSequential: //順序最近 p=&(close[dstX][dstY]); while(p) //轉置路徑 { t=p->from; p->from=q; q=p; p=t; } close[srcX][srcY].from=q->from; return&(close[srcX][srcY]); caseNoSolution: returnNULL; } returnNULL;}staticClose*start;staticintshortestep;intprintShortest(){ Close*p; intstep=0; p=getShortest(); start=p; if(!p) { return0; } else { while(p->from) { graph[p->cur->x][p->cur->y].value=Pass; printf("(%d,%d)→ ",p->cur->x,p->cur->y); p=p->from; step++; } printf("(%d,%d) ",p->cur->x,p->cur->y); graph[srcX][srcY].value=Source; graph[dstX][dstY].value=Destination; returnstep; }}voidclearMap(){ //ClearMapMarksofSteps Close*p=start; while(p) { graph[p->cur->x][p->cur->y].value=Reachable; p=p->from; } graph[srcX][srcY].value=map[srcX][srcY]; graph[dstX][dstY].value=map[dstX][dstY];}voidprintDepth(){ inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { if(map[i][j]) { printf("%s",Symbol[graph[i][j].value]); } else { printf("%2.0lf",close[i][j].G); } } puts(""); } puts("");}voidprintSur(){ inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { printf("%02x",graph[i][j].sur); } puts(""); } puts("");}voidprintH(){ inti,j; for(i=0;i<Height;i++) { for(j=0;j<Width;j++) { printf("%02d",close[i][j].H); } puts(""); } puts("");}intmain(intargc,constchar**argv){ initGraph(map,0,0,0,0); printMap(); while(scanf("%d%d%d%d",&srcX,&srcY,&dstX,&dstY)!=EOF) { if(within(srcX,srcY)&&within(dstX,dstY)) { if(shortestep=printShortest()) { printf("從(%d,%d)到(%d,%d)的最短步數是:%d ", srcX,srcY,dstX,dstY,shortestep); printMap(); clearMap(); bfs(); //printDepth(); puts((shortestep==close[dstX][dstY].G)?"正確":"錯誤"); clearMap(); } else { printf("從(%d,%d)不可到達(%d,%d) ", srcX,srcY,dstX,dstY); } } else { puts("輸入錯誤!"); } } return(0);}
❽ 圖的深度優先搜索和廣度優先搜索演算法的實現
//圖的遍歷演算法程序
//圖的遍歷是指按某條搜索路徑訪問圖中每個結點,使得每個結點均被訪問一次,而且僅被訪問一次。圖的遍歷有深度遍歷演算法和廣度遍歷演算法,程序如下:
#include <iostream>
//#include <malloc.h>
#define INFINITY 32767
#define MAX_VEX 20 //最大頂點個數
#define QUEUE_SIZE (MAX_VEX+1) //隊列長度
using namespace std;
bool *visited; //訪問標志數組
//圖的鄰接矩陣存儲結構
typedef struct{
char *vexs; //頂點向量
int arcs[MAX_VEX][MAX_VEX]; //鄰接矩陣
int vexnum,arcnum; //圖的當前頂點數和弧數
}Graph;
//隊列類
class Queue{
public:
void InitQueue(){
base=(int *)malloc(QUEUE_SIZE*sizeof(int));
front=rear=0;
}
void EnQueue(int e){
base[rear]=e;
rear=(rear+1)%QUEUE_SIZE;
}
void DeQueue(int &e){
e=base[front];
front=(front+1)%QUEUE_SIZE;
}
public:
int *base;
int front;
int rear;
};
//圖G中查找元素c的位置
int Locate(Graph G,char c){
for(int i=0;i<G.vexnum;i++)
if(G.vexs[i]==c) return i;
return -1;
}
//創建無向網
void CreateUDN(Graph &G){
int i,j,w,s1,s2;
char a,b,temp;
printf("輸入頂點數和弧數:");
scanf("%d%d",&G.vexnum,&G.arcnum);
temp=getchar(); //接收回車
G.vexs=(char *)malloc(G.vexnum*sizeof(char)); //分配頂點數目
printf("輸入%d個頂點.\n",G.vexnum);
for(i=0;i<G.vexnum;i++){ //初始化頂點
printf("輸入頂點%d:",i);
scanf("%c",&G.vexs[i]);
temp=getchar(); //接收回車
}
for(i=0;i<G.vexnum;i++) //初始化鄰接矩陣
for(j=0;j<G.vexnum;j++)
G.arcs[i][j]=INFINITY;
printf("輸入%d條弧.\n",G.arcnum);
for(i=0;i<G.arcnum;i++){ //初始化弧
printf("輸入弧%d:",i);
scanf("%c %c %d",&a,&b,&w); //輸入一條邊依附的頂點和權值
temp=getchar(); //接收回車
s1=Locate(G,a);
s2=Locate(G,b);
G.arcs[s1][s2]=G.arcs[s2][s1]=w;
}
}
//圖G中頂點k的第一個鄰接頂點
int FirstVex(Graph G,int k){
if(k>=0 && k<G.vexnum){ //k合理
for(int i=0;i<G.vexnum;i++)
if(G.arcs[k][i]!=INFINITY) return i;
}
return -1;
}
//圖G中頂點i的第j個鄰接頂點的下一個鄰接頂點
int NextVex(Graph G,int i,int j){
if(i>=0 && i<G.vexnum && j>=0 && j<G.vexnum){ //i,j合理
for(int k=j+1;k<G.vexnum;k++)
if(G.arcs[i][k]!=INFINITY) return k;
}
return -1;
}
//深度優先遍歷
void DFS(Graph G,int k){
int i;
if(k==-1){ //第一次執行DFS時,k為-1
for(i=0;i<G.vexnum;i++)
if(!visited[i]) DFS(G,i); //對尚未訪問的頂點調用DFS
}
else{
visited[k]=true;
printf("%c ",G.vexs[k]); //訪問第k個頂點
for(i=FirstVex(G,k);i>=0;i=NextVex(G,k,i))
if(!visited[i]) DFS(G,i); //對k的尚未訪問的鄰接頂點i遞歸調用DFS
}
}
//廣度優先遍歷
void BFS(Graph G){
int k;
Queue Q; //輔助隊列Q
Q.InitQueue();
for(int i=0;i<G.vexnum;i++)
if(!visited[i]){ //i尚未訪問
visited[i]=true;
printf("%c ",G.vexs[i]);
Q.EnQueue(i); //i入列
while(Q.front!=Q.rear){
Q.DeQueue(k); //隊頭元素出列並置為k
for(int w=FirstVex(G,k);w>=0;w=NextVex(G,k,w))
if(!visited[w]){ //w為k的尚未訪問的鄰接頂點
visited[w]=true;
printf("%c ",G.vexs[w]);
Q.EnQueue(w);
}
}
}
}
//主函數
void main(){
int i;
Graph G;
CreateUDN(G);
visited=(bool *)malloc(G.vexnum*sizeof(bool));
printf("\n廣度優先遍歷: ");
for(i=0;i<G.vexnum;i++)
visited[i]=false;
DFS(G,-1);
printf("\n深度優先遍歷: ");
for(i=0;i<G.vexnum;i++)
visited[i]=false;
BFS(G);
printf("\n程序結束.\n");
}
輸出結果為(紅色為鍵盤輸入的數據,權值都置為1):
輸入頂點數和弧數:8 9
輸入8個頂點.
輸入頂點0:a
輸入頂點1:b
輸入頂點2:c
輸入頂點3:d
輸入頂點4:e
輸入頂點5:f
輸入頂點6:g
輸入頂點7:h
輸入9條弧.
輸入弧0:a b 1
輸入弧1:b d 1
輸入弧2:b e 1
輸入弧3:d h 1
輸入弧4:e h 1
輸入弧5:a c 1
輸入弧6:c f 1
輸入弧7:c g 1
輸入弧8:f g 1
廣度優先遍歷: a b d h e c f g
深度優先遍歷: a b c d e f g h
程序結束.
已經在vc++內運行通過,這個程序已經達到要求了呀~
❾ 詳細介紹廣度優先搜索的實現,原理,c++程序
寬度優先搜索演算法(又稱廣度優先搜索)是最簡便的圖的搜索演算法之一,這一演算法也是很多重要的圖的演算法的原型。Dijkstra單源最短路徑演算法和Prim最小生成樹演算法都採用了和寬度優先搜索類似的思想。其別名又叫BFS,屬於一種盲目搜尋法,目的是系統地展開並檢查圖中的所有節點,以找尋結果。換句話說,它並不考慮結果的可能位址,徹底地搜索整張圖,直到找到結果為止。
已知圖G=(V,E)和一個源頂點s,寬度優先搜索以一種系統的方式探尋G的邊,從而「發現」s所能到達的所有頂點,並計算s到所有這些頂點的距離(最少邊數),該演算法同時能生成一棵根為s且包括所有可達頂點的寬度優先樹。對從s可達的任意頂點v,寬度優先樹中從s到v的路徑對應於圖G中從s到v的最短路徑,即包含最小邊數的路徑。該演算法對有向圖和無向圖同樣適用。
之所以稱之為寬度優先演算法,是因為演算法自始至終一直通過已找到和未找到頂點之間的邊界向外擴展,就是說,演算法首先搜索和s距離為k的所有頂點,然後再去搜索和S距離為k+l的其他頂點。
為了保持搜索的軌跡,寬度優先搜索為每個頂點著色:白色、灰色或黑色。演算法開始前所有頂點都是白色,隨著搜索的進行,各頂點會逐漸變成灰色,然後成為黑色。在搜索中第一次碰到一頂點時,我們說該頂點被發現,此時該頂點變為非白色頂點。因此,灰色和黑色頂點都已被發現,但是,寬度優先搜索演算法對它們加以區分以保證搜索以寬度優先的方式執行。若(u,v)∈E且頂點u為黑色,那麼頂點v要麼是灰色,要麼是黑色,就是說,所有和黑色頂點鄰接的頂點都已被發現。灰色頂點可以與一些白色頂點相鄰接,它們代表著已找到和未找到頂點之間的邊界。
在寬度優先搜索過程中建立了一棵寬度優先樹,起始時只包含根節點,即源頂點s.在掃描已發現頂點u的鄰接表的過程中每發現一個白色頂點v,該頂點v及邊(u,v)就被添加到樹中。在寬度優先樹中,我們稱結點u 是結點v的先輩或父母結點。因為一個結點至多隻能被發現一次,因此它最多隻能有--個父母結點。相對根結點來說祖先和後裔關系的定義和通常一樣:如果u處於樹中從根s到結點v的路徑中,那麼u稱為v的祖先,v是u的後裔。
❿ 用c++語言實現二分搜索演算法
這個就是二分法排序函數的源代碼 傳入參數是數組a和數組的大小n
template <class T>
void BinSort( T a[], int n ) {
int low,high,mid;
for (int i=1; i<n; i++) {
T t=a[i];
low=0; high=i-1;
while (low<=high) {
mid=(low+high)/2;
if (a[mid]>t) high=mid-1;
else low=mid+1;
}
for (int j=i-1; j>=high+1; j--) a[j+1]=a[j];
a[high+1]=t;
}
}