導航:首頁 > 編程語言 > 一致代價搜索代碼

一致代價搜索代碼

發布時間:2023-06-14 06:38:01

『壹』 人工智慧的搜索方式就搜索策略是否被預先確定一般可以分為

 人工智慧中的搜索策略大體分為兩種:無信息搜索和有信息搜索。無信息搜索是指我們不知道接下來要搜索的狀態哪一個更加接近目標的搜索策略,因此也常被成為盲目搜索;而有信息搜索則是用啟發函數f(n)來衡量哪一個狀態更加接近目標狀態,並優先對該狀態進行搜索,因此與無信息搜索相比往往能夠更加高效得解決問題。
  要衡量一個搜索策略的好壞,我們需要從四個方面對其進行判斷:完備性、時間復雜度、空間復雜度和最優性。因此以下通過這四個方面來比較常見搜索策略之間的優劣。
無信息搜索策略
寬度優先搜索(BFS)
  首先擴展根節點,然後擴展根節點的所有後繼,接著再擴展它們的後繼,從而一層一層的對節點進行擴展。BFS是一個簡單的搜索策略,在搜索過程中會對所有狀態進行遍歷,因此它是完備的;假設搜索樹每個節點有b個後繼,深度為d,則時間復雜度和空間復雜度均為O(bd);最後考慮最優性,因為我們總會在最淺那一層找到目標狀態,因此當且僅當每一步的代價都一致的時候,BFS可以得到最優解。
一致代價搜索
  在BFS的基礎上,一致代價搜索不在擴展深度最淺的節點,而是通過比較路徑消耗g(n),並選擇當前代價最小的節點進行擴展,因此可以保證無論每一步代價是否一致,都能夠找到最優解。
深度優先搜索(DFS)
  DFS擴展根節點的一個後繼,然後擴展它的一個後繼,直到到達搜索樹的最深層,那裡的節點沒有後繼,於是DFS回溯到上一層,擴展另外一個未被擴展的節點。在有限狀態空間中,DFS是完備的,因為它可以把所有空間遍歷一遍;而在無限空間中,DFS則有可能會進入深度無限的分支,因此是不完備的。DFS的時間復雜度為為O(bd),而空間復雜度僅為O(d),因為我們只需要保存當前分支的狀態,因此空間復雜度遠遠好於BFS。然而DFS並不能保證找到最優解。
深度受限搜索
  深度受限搜索設定一個最大深度dmax,當搜索深度大於dmax的時候立即回溯,從而避免了在無窮狀態空間中陷入深度無限的分支。
迭代加深的深度有限搜索
  迭代加深的深度有限搜索也設定一個最大深度dmax,開始我們把dmax設為1,然後進行深度受限搜索,如果么有找到答案,則讓dmax加一,並再次進行深度有限搜索,以此類推直到找到目標。這樣既可以避免陷入深度無限的分支,同時還可以找到深度最淺的目標解,從而在每一步代價一致的時候找到最優解,再加上其優越的空間復雜度,因此常常作為首選的無信息搜索策略。
有信息搜索
貪婪最佳優先搜索
貪婪最佳優先搜索總是擴展距離目標最近的節點,其啟發函數f(n)=h(n)其中:
f(n)=節點n到目標節點的最小代價路徑的估計值
貪婪最佳優先搜索的最大問題是它往往不能找到最優解。
A*
為了找到最優解,A*演算法對一個節點的評估結合了h(n)和g(n)從開始節點到節點n的路徑代價,即f(n)=g(n)+h(n)
f(n)=經過節點n的最小代價解的估計代價
因為A*搜索總是搜索f(n)最小的點,因此它總能找到最優解。

『貳』 如何寫出更好的java代碼

1. 優雅需要付出代價。
從短期利益來看,對某個問題提出優雅的解決方法,似乎可能花你更多的時間。但當它終於能夠正確執行並可輕易套用於新案例中,不需要花上數以時計,甚至以天計或以月計的辛苦代價時,你會看得到先前所花功夫的回報(即使沒有人可以衡量這一點)。這不僅給你一個可更容易開發和調試的程序,也更易於理解和維護。這正是它在金錢上的價值所在。這一點有賴某種人生經驗才能夠了解,因為當你努力讓某一段程序代碼變得比較優雅時,你並不是處於一種具生產力的狀態下。但是,請抗拒那些催促你趕工的人們,因為那麼做只會減緩你的速度罷了。
2. 先求能動,再求快。
即使你已確定某段程序代碼極為重要,而且是系統的重要瓶頸,這個准則依然成立。盡可能簡化設計,讓系統能夠先正確動作。如果程序的執行不夠快,再量測其效能。幾乎你總是會發現,你所認為的」瓶頸」其實都不是問題所在。把你的時間花在刀口上吧。
3. 記住」各個擊破」的原理。
如果你所探討的問題過於混雜,試著想像該問題的基本動作會是什麼,並假設這一小塊東西能夠神奇地處理掉最難的部分。這」一小塊」東西其實就是對象–請撰寫運用該對象的程序代碼,然後檢視對象,並將其中困難的部分再包裝成其他對象,依此類推。
4. 區分class開發者和class使用者(使用端程序員)。
Class 使用者扮演著」客戶」角色,不需要(也不知道)class的底層運作方式。Class開發者必須是class設計專家,並撰寫class,使它能夠盡可能被大多數新手程序員所用,而且在程序中能夠穩當執行。一套程序庫只有在具備通透性的情況下,使用起來才會容易。
5.當你撰寫class時,試著給予明了易懂的名稱,減少不必要的註解。
你給客戶端程序員的介面,應該保持概念上的單純性。不了這個目的,當函數的重載(overloading)適合製作出直覺、易用的介面時,請善加使用。
6. 也必你的分析和設計必須讓系統中的classes保持最少,須讓其Public interfaces保持最少,以及讓這些classes和其他classes之間的關聯性( 尤其是base classes)保持最少。
如果你的設計所得結果更甚於此,請問問自己,是否其中每一樣東西在整個程序生命期中都饒富價值?如果並非如此,那麼,維護它們會使你付出代價。開發團隊的成員都有不維護」無益於生產力提升」的任何東西的傾向;這是許多設計方法無法解釋的現象。
7. 讓所有東西盡量自動化。先撰寫測試用的程序代碼(在你撰寫class之前),並讓它和class結合在一起。請使用makefile或類似工具,自動進行測試動作。
通過這種方式,只要執行測試程序,所有的程序變動就可以自動獲得驗證,而且可以立即發現錯誤。由於你知道的測試架構所具備的安全性,所以當你發現新的需求時,你會更勇於進行全面修改。請記住,程序語言最大的改進,是來自型別檢查、異常處理等機制所賦予的內置測試動作。但這些功能只能協助你到達某種程度。開發一個穩固系統時,你得自己驗證自己的classes或程序的性質。
8. 在你撰寫class之前先寫測試碼,以便驗證你的class 是否設計完備。如果你無法撰寫測試碼,你便無法知道你的class 的可能長相。撰寫測試碼通常能夠顯現出額外的特性(features)或限制 ( constraints)__它們並不一定總是能夠在分析和設計過程中出現。測試碼也可做為展示class 用法的示常式序。
9. 所有軟體設計上的問題,都可以通過」引入額外的概念性間接層(conceptual indirection)」加以簡化。這個軟體工程上的基礎法則是抽象化概念的根據,而抽象化概念正是面向對象程序設計的主要性質。
10. 間接層(indirection)應該要有意義(和准則-9致)。
這里所指的意義可以像」將共用程序代碼置於惟一函數」這么簡單。如果你加入的間接層(或抽象化、或封裝等等)不具意義,它可能就和沒有適當的間接層一樣糟糕。
11. 讓class盡可能微小而無法切割(atomic)。
賦予每個class單一而清楚的用途。如果你的classes或你的系統成長得過於復雜,請將復雜的classes切割成比較簡單的幾個classes。最明顯的一個判斷指針就是class的大小:如果它很大,那麼它工作量過多的機會就可能很高,那就應該被切割。重新設計class的建議線索是:
1) 復雜的switch語句:請考慮運用多態(Polymorphism)。
2) 許多函數各自處理類型極為不同的動作:請考慮切割為多個不同的(classes)。
12. 小心冗長的引數列(argument lists)。
冗長的引數列會使函數的調用動作不易撰寫、閱讀、維護。你應該試著將函數搬移到更適當的class中,並盡量以對象為引數。
13. 不要一再重復。
如果某段程序代碼不斷出現於許多derived class函數中,請將該段程序代碼置於某個base class 函數內,然後在derived class函數中調用。這么做不僅可以省下程序代碼空間,也可以讓修改該段程序代碼動作更易於進行。有時候找出此種共通程序代碼還可以為介面增加實用功能。
14. 小心switch語句或成串的if-else 子句。
通常這種情況代表所謂的」type-check coding」。也就是說究竟會執行哪一段程序代碼,乃是依據某種型別信息來做抉擇(最初,確切型別可能不十分明顯)。你通常可以使用繼承和多態來取代此類程序代碼;Polymorphical method (多態函數)的調用會自動執行此類型別檢驗,並提供更可靠更容易的擴充性。
15. 從設計觀點來看,請找出變動的事物,並使它和不變的事物分離。
也就是說,找出系統中可能被你改變的元素,將它們封裝於classes中。你可以在《Thinking in Patterns with Java》(可免費下載於 www. BruceEckel. Com)大量學習到這種觀念。
16. 不要利用subclassing來擴充基礎功能。
如果某個介面元素對class而言極重要,它應該被放在base class 里頭,而不是直到衍生(derivation)時才被加入。如果你在繼承過程中加入了函數,或許你應該重新思考整個設計。
17. 少就是多。
從class 的最小介面開始妨展,盡可能在解決問題的前提下讓它保持既小又單純。不要預先考量你的class被使用的所有可能方式。一旦class被實際運用,你自然會知道你得如何擴充介面。不過,一旦class被使用後,你就無法在不影響客戶程序代碼的情況下縮減其介面。如果你要加入更多函數倒是沒有問題–不會影響既有的客戶程序代碼,它們只需重新編譯即可。但即使新函數取代了舊函數的功能,也請你保留既有介面。如果你得通過」加入更多引數」的方式來擴充既有函數的介面,請你以新引數寫出一個重載化的函數;通過 這種方式就不會影響既有函數的任何客戶了。
18. 大聲念出你的classes,確認它們符合邏輯。
請base class和derived class 之間的關系是」is-a」(是一種),讓class和成員對象之間的關系是」has-a」(有一個)。
19. 當你猶豫不決於繼承(inheritance)或合成(組合,composition)時,請你問問自己,是否需要向上轉型(upcast)為基礎型別。
如果不需要,請優先選擇合成(也就是是使用成員對象)。這種作法可以消除」過多基礎型別」。如果你採用繼承,使用者會認為他們應該可以向上轉型。
20. 運用數據成員來表示數值的變化,運用經過覆寫的函數(overrided method)來代錶行為的變化 。
也就是說,如果你找到了某個 class, 帶有一些狀態變數,而其函數會依據這些變數值切換不同的行為,那麼你或許就應該重新設計,在subclasses 和覆寫後的函數(overrided methods)中展現行為止的差異。
21. 小心重載(overloading)。
函數不應該依據引數值條件式地選擇執行某一段程序代碼。這種情況下你應該撰寫兩個或更多個重載函數(overloaded methods)
22. 使用異常體系(exception hierarchies)
最好是從Java標准異常體系中衍生特定的classes, 那麼,捕捉異常的人便可以捕捉特定異常,之後才捕捉基本異常。如果你加入新的衍生異常,原有的客戶端程序仍能通過其基礎型別來捕捉它。
23. 有時候簡單的聚合(aggregation)就夠了。
飛機上的」旅客舒適系統」包括數個分離的元素:座椅、空調、視訊設備等等,你會需要在飛機上產生許多這樣的東西。你會將它們聲明為Private成員並開發出一個全新的介面嗎?不會的,在這個例子中,元素也是Public介面的一部分,所以仍然是安全的。當然啦,簡單聚合並不是一個常被運用的解法,但有時候的確是。
24. 試著從客戶程序員和程序維護的角度思考。
你的class應該設計得盡可能容易使用。你應該預先考量可能性有的變動,並針對這些 可能的變動進行設計,使這些變動日後可輕易完成。
25. 小心」巨大對象並發症」。
這往往是剛踏OOP領域的過程式(proceral)程序員的一個苦惱,因為他們往往最終還是寫出一個過程式程序,並將它們擺放到一個或兩個巨大對象中。注意,除了application framework (應用程序框架,譯註:一種很特殊的、大型OO程序庫,幫你架構程序本體)之外,對象代表的是程序中的觀念,而不是程序本身。
26. 如果你得用某種醜陋的方式來達成某個動作,請將醜陋的部分局限在某個class里頭。
27. 如果你得用某種不可移植方式來達成某個動作,請將它抽象化並局限於某個class里頭。這樣一個」額外間接層」能夠防止不可移植的部分擴散到整個程序。這種作法的具體呈現便是Bridge設計模式(design pattern)。
28. 對象不應僅僅只用來持有數據。
對象也應該具有定義明確界限清楚的行為。有時候使用」數據對象」是適當的,但只有在通用形容器不適用時,才適合刻意以數據對象來包裝、傳輸一群數據項。
29. 欲從既有的classes身上產生新的classes時,請以組合(composition)為優先考量。
你應該只在必要時才使用繼承。如果在組合適用之處你卻選擇了繼承,你的設計就滲雜了非必要的復雜性。
30. 運用繼承和函數覆寫機制來展現行為上的差異,運用fields(數據成員)來展現狀態上的差異。
這句話的極端例子,就是繼承出不同的classes表現各種不同的顏色,而不使用」color」field.
31. 當心變異性(variance)。
語意相異的兩個對象擁有相同的動作(或說責任)是可能的。OO世界中存在著一種天生的引誘,讓人想要從某個class繼承出另一個subclass,為的是獲得繼承帶來的福利。這便是所謂」變異性」。但是,沒有任何正當理由足以讓我們強迫製造出某個其實並不存在的superclass/subclass關系。比較好的解決方式是寫出一個共用的base class,它為兩個derived classes製作出共用介面–這種方式會耗用更多空間,但你可以如你所盼望地從繼承機制獲得好處,而且或許能夠在設計上獲得重大發現。
32. 注意繼承上的限制。
最清晰易懂的設計是將功能加到繼承得來的class里頭;繼承過程中拿掉舊功能(而非增加新功能)則是一種可疑的設計。不過,規則可以打破。如果你所處理的是舊有的class程序庫,那麼在某個class的subclass限制功能,可能會比重新制定整個結構(俾使新class得以良好地相稱於舊 class)有效率得多。
33. 使用設計模式(design patterns)來減少」赤裸裸無加掩飾的機能(naked functionality)」。
舉個例子,如果你的class只應該產出惟一一個對象,那麼請不要以加思索毫無設計的手法來完成它,然後撰寫」只該產生一份對象」這樣的註解就拍拍屁股走人。請將它包裝成singleton(譯註:一個有名的設計模式,可譯為」單件」)。如果主程序中有多而混亂的」用以產生對象」的程序代碼,請找出類似 factory method這樣的生成模式(creational patterns),使價錢可用以封裝生成動作減少」赤裸裸無加掩飾的機能」(naked functionality)不僅可以讓你的程序更易理解和維護,也可以阻止出於好意卻帶來意外的維護者。
34. 當心」因分析而導致的癱瘓(analysis paralysis)」。
請記住,你往往必須在獲得所有信息之前讓項目繼續前進。而且理解未知部分的最好也最快的方式,通常就是實際前進一步而不只是紙上談兵。除非找到解決辦法,否則無法知道解決辦法。Java擁有內置的防火牆,請讓它們發揮作用。你在單一class或一組classes中所犯的錯誤,並不會傷害整個系統的完整性。
35. 當你認為你已經獲得一份優秀的分析、設計或實現時,請試著加以演練。
將團隊以外的某些人帶進來-他不必非得是個顧問不可,他可以是公司其他團隊的成員。請那個人以新鮮的姿態審視你們的成果,這樣可以在尚可輕易修改的階段找出問題,其收獲會比因演練而付出的時間和金錢代價來得高。實現 (Implementation)
36. 一般來說,請遵守Sun的程序編寫習慣。
價錢可以在以下網址找到相關文檔:java.sun.com/docs/codeconv/idex.html。本書盡可能遵守這些習慣。眾多Java程序員看到的程序代碼,都有是由這些習慣構成的。如果你固執地停留在過去的編寫風格中,你的(程序代碼)讀者會比較辛苦。不論你決定採用什麼編寫習慣,請在整個程序中保持一致。你可以在home.wtal.de/software-solutions/jindent上找到一個用來重排Java程序的免費工具。
37. 無論使用何種編寫風格,如果你的團隊(或整個公司,那就更好了)能夠加以標准化,那麼的確會帶來顯著效果。這代表每個人都可以在其他人不遵守編寫風格修改其作品,這是個公平的游戲。標准化的價值在於,分析程序代碼時所花的腦力較小,因而可以專心於程序代碼的實質意義。
38. 遵守標準的大小寫規范。
將 class名稱的第一個字母應為大寫。數據成員、函數、對象(references)的第一個字母應為小寫。所有識別名稱的每個字都應該連在一塊兒,所有非首字的第一個字母都應該大寫。例如: ThisIsAClassName thisIsAMethodOrFieldName 如果你在static final 基本型別的定義處指定了常量初始式(constant initializers),那麼該識別名稱應該全為大寫,代表一個編譯期常量。 Packages是個特例,其名稱皆為小寫,即使非首字的字母亦是如此。域名(org, net, e 等等)皆應為小寫。(這是Java 1.1遷移至Java 2時的一項改變) 。
39、不要自己發明」裝飾用的」Private數據成員名稱。
通常這種的形式是在最前端加上底線和其他字元,匈牙利命名法(Hungarian notation)是其中最差的示範。在這種命名法中,你得加入額外字元來表示數據的型別、用途、位置等等。彷彿你用的是匯編語言(assembly language)而編譯器沒有提供任何協肋似的。這樣的命名方式容易讓人混淆又難以閱讀,也不易推行和維護。就讓classes和packages來進行」名稱上的范
圍制定(name scoping)」吧。
40、當你擬定通用性的class時,請遵守正規形式(canonical form)。
包括equals( )、hashCode( )、clone( ) ( 實現出Cloneable),並實現出Comparable和Serialiable等等。

閱讀全文

與一致代價搜索代碼相關的資料

熱點內容
iphone程序加密 瀏覽:884
win10文件夾調整文件行高 瀏覽:681
創意手繪教程 瀏覽:754
微信刪除帳號信息 瀏覽:596
mysql操作類文件 瀏覽:649
繞過xp密碼 瀏覽:158
大眾速騰專用app有哪些 瀏覽:455
arpa首先將計算機網路劃分為 瀏覽:617
蘋果系統開機音樂 瀏覽:875
windows8顯示隱藏文件 瀏覽:603
ipad2可以升級到92嗎 瀏覽:857
如何打開ps保存的文件 瀏覽:744
幼兒編程教育有哪些 瀏覽:453
汽車發外地用什麼app 瀏覽:810
網路如何贊美女人漂亮 瀏覽:143
如何把桌面文件放到excel裡面 瀏覽:363
照片文件名是怎麼查的 瀏覽:876
c怎麼在cmd模式下顯示文件 瀏覽:325
手機怎麼把文件夾的圖片移到相冊 瀏覽:440
hjc是啥文件的格式 瀏覽:298

友情鏈接