久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

用 C++ 和 Java 寫算法,差別大嗎?

 池塘邊榕樹上 2018-09-20

為什么會有這篇文章,?

無論是七、八年前開始寫的 “算法博客”,,還是三年前出版的圖書《算法的樂趣》,,亦或是暢銷課《算法應(yīng)該怎么“玩”?》,,我介紹算法用的例子都是用 C++ 編寫的,。

盡管以前博客的留言里不乏抱怨之聲,但是在《算法的樂趣》出版的時候我仍然 “一意孤行” ,,最終招致讀者吐槽:“好好的一本算法書,,為什么要用 C++?” 

我的很多使用 Java 的朋友們也都為我 “打抱不平”,,但是在事實面前,,我不得不承認(rèn),這個拖了很久的需求必須要實現(xiàn)了。

盡管學(xué)習(xí) Java 了很長時間,,但是因為工作的需要,,很少用 Java 做過大型的項目,所以在公開算法實現(xiàn)的時候,,我本能地選擇最擅長的 C++ 語言,。

事實上,我在編寫《算法應(yīng)該怎么“玩”,?》的過程中,,參考資料里有不少 Java、Python 實現(xiàn)的算法,,原理都是相通的,,用何種編程語言實現(xiàn)只是對外展示的一張皮而已。

作為一個 Java 程序員時,,經(jīng)常會遇到 C++ 算法代碼,,有時候沒有更好的替代例子的情況下,還必須得啃一啃 C++,。

往好處想,,雖然 C++ 涉及的內(nèi)容廣泛,但是算法上能用到的部分并不多,,都是一些基本語言元素,,短時間內(nèi)了解一下 C++ 相關(guān)的內(nèi)容,能夠看懂小段的 C++ 代碼是完全有可能的,。

接下來,,我會在算法涉及的層面上,比較一下 C++ 和 Java 上的差異,,通過這些對比和比較,,Java 程序員能快速理解 C++ 算法實現(xiàn)的例子,C++ 程序員也能看懂簡單的 Java 算法代碼,。

PS:

兩種語言的對比會放在一起展示,,如不做特殊說明,上面的代碼是 C++ 的實現(xiàn)方式,,下面的是 Java 的實現(xiàn)方式,。

此外,C++ 語法層面使用的版本是 C++11之后的版本,,Java 使用的標(biāo)準(zhǔn)是 Java6 之后的版本,。

C++ 和 Java 語法特性的相似性

因為歷史原因,同為 C 語言家族的 Java 和 C++ 語言層面的相似性是有客觀基礎(chǔ)的,。

我通常是這樣理解的:Java 是跨平臺的 C++,,是一種更好的 C++(是不是有點拉仇恨的感覺)。

基本數(shù)據(jù)類型

C++ 的基本數(shù)據(jù)類型有:int、unsigned int,、long,、unsigned long、short,、unsigned short,、char、unsigned char,、bool,、float 和 double;

相應(yīng)的,,Java 也有 8 種基本數(shù)據(jù)類型,,分別是:byte、short,、int,、long、float,、double,、char 和 boolean。

大部分情況下,,兩種語言的基本數(shù)據(jù)類型可以根據(jù)下表進(jìn)行一對一的轉(zhuǎn)換,,但是也有差異,需要特別注意,。

首先是 char,,C++ 的 char 是 8 比特?zé)o符號整數(shù),順便表示了 ASCII 字符,;Java 的 char 是 16 比特,,天生就可以表示寬字符集的字符。

另一個需要注意的是 long 類型,,C++ 的 long 是不可移植類型,,在不同的系統(tǒng)上其長度不一樣,可能是 32 位,,也可能是 64 位,所以 C++ 程序員應(yīng)盡量避免使用 long,。

Java 的 long 比較單純,,無論是 32 位的系統(tǒng)還是 64 位的系統(tǒng),它都表示 64 位整數(shù),。

反過來,,Java 會用 d 或 D 表示一個直接數(shù)字是 double 類型的浮點數(shù),比如 200.0d 或(200.0D),但是 C++ 不支持,,因為 C++ 默認(rèn)一個浮點型的直接數(shù)字就是 double 類型,。

C++ 用字面量符號 f 或 F 表示一個直接數(shù)字是 float 類型浮點數(shù),比如 250.1 f(或 250.1F),,這一點 Java 也是一樣的,。

C++ 用字面量符號 l 或 L 表示 long,用 UL 表示 unsigned long,。

字符串

很多 C++ 程序員喜歡的用 char* 或 char 類型的數(shù)組存儲字符串,,這其實是 C 語言用戶帶過來的習(xí)慣,我給出的 C++ 算法實現(xiàn)對字符串一般都用 std::string,,對應(yīng) Java 的 String,。

std::stringString 的用法對照如下表所示:

基本語法

雖然 Java 的語法和 C++ 十分地相似,但是語言層面還有一些不同,。C++ 允許全局函數(shù)的存在,,但是 Java 不允許,不過 Java 也留了個口子,,就是用靜態(tài)成員函數(shù),。

Java 沒有指針,對象的傳遞和返回都是用的引用的方式,,并且不需要像 C++ 那樣用 “&” 做特殊的語法標(biāo)記,。

大多數(shù)介紹 Java 的書籍開篇就是類和抽象,然后才是基本的語法,,這和 Java 上等人的氣質(zhì)是一致的,,連這都不會,咋做程序員,?C++ 應(yīng)該多提升一下氣質(zhì),,少用點指針和全局函數(shù)。

不過本文是為了對比 C++ 和 Java 的相似性,,所以就從基本語法結(jié)構(gòu)開始介紹,。

運算符和賦值

二者的運算符幾乎一樣,甚至 “++” 和 “—” 運算符都一樣有前綴式和后綴式兩種形式,,意義也一樣,;運算符的優(yōu)先級規(guī)則也是一樣的。

賦值語句兩者基本上是一樣的,,看看每一行結(jié)尾的 “;” 你就知道它們有多相似,。

條件判斷與循環(huán)

條件判斷方面,C++ 與 Java 的 if 語句,、switch 語句用法都相同,;邏輯表達(dá)式的結(jié)構(gòu)和語法,、邏輯運算符的優(yōu)先級也都相同。

C++ 的三種基本循環(huán)方式是 while 循環(huán),、do…while 循環(huán)和 for 循環(huán),,Java 都支持,甚至連關(guān)鍵字和 break,、continue 控制語句的意義也一樣,。

C++11 版本引入了一種根據(jù)范圍循環(huán)的語法,一般理解和 Java 的增強 for 循環(huán)類似,,比如這種 C++ 循環(huán)形式:

Java 與之對應(yīng)的形式是:

C++ 的基于范圍的 for 循環(huán)也可用于 C++ 的標(biāo)準(zhǔn)庫對象,,用于取代老舊的迭代器循環(huán)方式:

同樣,Java 的增強 for 循環(huán)也支持基于 Collection 的遍歷,,理解起來不成問題:

傳統(tǒng)的 C++ 語言是用迭代器對標(biāo)準(zhǔn)庫的容器進(jìn)行遍歷,,比如:

C++ 的容器都有 begin()end() 接口,分別得到起始位置的迭代器的值和結(jié)束位置的迭代器的值,,很多標(biāo)準(zhǔn)庫的算法都會用到迭代器,。

C++ 用當(dāng)前迭代器的值是否等于 end() 代表的結(jié)束位置迭代器的值來判斷是否遍歷結(jié)束。

Java 的 Collection 也有迭代器的機制,,Java 用 hasNext() 判斷是否遍歷結(jié)束,。

C++ 直接用 “ * ” 提領(lǐng)迭代器,得到對象本身的引用,,Java 用迭代器的 next() 接口得到對象本身的引用,。以上 C++ 代碼可以翻譯成如下 Java 代碼:

除了以上的 for 循環(huán)語句,C++ 還支持 for_each() 形式的遍歷 + 處理操作,,也是配合迭代器使用,,for_each() 的前兩個參數(shù)是一對迭代器,代表循環(huán)的起始位置和結(jié)束位置,。

第三個參數(shù)是一個可調(diào)用對象,,即函數(shù)對象(C++11 版本之后,這個參數(shù)還可以是一個 Lambda 表達(dá)式),,舉個栗子:

Java 沒有與之對應(yīng)的泛型函數(shù)接口,,但是 Java 的很多 Collection 都支持 forEach() 接口:

C++ 的 for_each()其實用起來并不好用,自從 C++11 之后,,除了懷舊派 C++ 程序員,,其他人應(yīng)該很少會再用 for_each() 了,基于范圍的 for 循環(huán)簡直絲滑的不要不要的,。

函數(shù)

C++ 的函數(shù)結(jié)構(gòu)和 Java 也一樣,,函數(shù)調(diào)用的形參和實參對應(yīng)方式也一樣,也無需多做說明,。

數(shù)組

C++ 和 Java 都支持原生數(shù)組,,并且數(shù)組索引都是從 0 開始。

C++ 中定義數(shù)組的同時就分配了存儲空間,,所以在定義時要指定長度,,使用 new 動態(tài)申請內(nèi)存時,要指定長度,。

但是一種情況除外,,那就是靜態(tài)初始化數(shù)組的形式,因為此時編譯器知道需要多少空間存儲這些數(shù)據(jù),,如下是 C++ 定義數(shù)組的常用形式:

Java 如果僅僅是聲明一個數(shù)組,,可以不指定長度,因為此時并不分配存儲空間,,需要分配空間的時候,,用 new。與之對應(yīng)的 Java 語言的形式是:

C++ 中二維數(shù)組的每一維長度必須相同,,因為 C++ 的二維數(shù)組實際上只是一塊連續(xù)的存儲空間而已,,甚至可以用一維數(shù)組的下標(biāo)遍歷全部二維數(shù)組的存儲空間。

Java 沒這要求,,因為 Java 的每一維都是可以單獨申請存儲空間的,。但是二者在使用形式上是一樣的。C++ 定義和初始化二維數(shù)組一般有這幾種形式:

與之對應(yīng)的 Java 語言初始化二維數(shù)組的形式是:

C++ 也支持動態(tài)內(nèi)存形式的二維數(shù)組,,一般有兩種使用方法,,Java 都有與之對應(yīng)的習(xí)慣用法:

與之對應(yīng)的 Java 的方法是:

這代碼相似度很高。C++ 代碼最后要用 delete[] 手動釋放為數(shù)組申請的內(nèi)存,,Java 是不需要的,。

C++ 還可以利用二維數(shù)組在內(nèi)存中是連續(xù)存儲這一特性,使用時用下標(biāo)計算將一維數(shù)組當(dāng)成二維數(shù)組使用,,計算的方法是:a\[i]\[j] = b[i * 2 + j],,如下代碼示例:

遇到這樣的代碼,需要根據(jù)上述對應(yīng)關(guān)系,,小心地理解算法代碼的意圖,。一些棋盤類游戲通常喜歡用一維數(shù)組存儲二維的邏輯棋盤結(jié)構(gòu),好在 Java 也可以這么做,,轉(zhuǎn)換起來也沒什么難度,。

枚舉

與 C 相比,C++ 強化了類型差異,,枚舉變量和整數(shù)變量之間不能互相賦值,,但是使用方法依然是直接使用枚舉值,沒有限制域,。

C++11 之后,,開始支持強類型枚舉,,這一點就和 Java 很像了,越來越像一家人了:

I/O 系統(tǒng)

C++ 代碼中一般用 std::cinstd::cout 進(jìn)行控制臺的輸入和輸出,。

也有一些半吊子 C++ 程序員會在 C++ 代碼中混用 C 語言的 printf() 打印輸出信息,。

不過話說回來,很多語言都支持 printf 方式的格式化輸出,,比如 Java,、 Python,為啥 C++ 就不能提供一個呢,?比如以下代碼接受用戶輸入一個字符串和一個整數(shù),,并將其輸出出來:

將其翻譯成 Java,是這個樣子的:

上述代碼示例中,,C++ 和 Java 的輸入分隔符都是空格或回車,,如果希望輸入帶空格的一整行內(nèi)容怎么辦?

C++ 提供了 getline() 函數(shù),,getline() 會從緩沖區(qū)中取輸入流,,直到遇到結(jié)束符。

結(jié)束符默認(rèn)是 '\n',,實際上是 getline() 函數(shù)有三個參數(shù),,第三個參數(shù)可指定結(jié)束符:

Java 也有與之對應(yīng)的 Buffer IO 方式,請看:

C++ 程序員有時候也會用 std::cin::get() 函數(shù),,這個函數(shù)也是從緩沖區(qū)中讀入一行,,直到遇到結(jié)束符,和 getline() 函數(shù)一樣,,這個函數(shù)也可以指定結(jié)束符,,如果不指定,默認(rèn)是'\n',。

但是 std::cin::get() 函數(shù)有個小個性,,就是它不從緩沖區(qū)中讀出結(jié)束符,而是將結(jié)束符留在緩沖區(qū)中,。

為了適應(yīng)它的這個小個性,,C++ 程序員通常會在后面跟一個 get,將結(jié)束符讀出并丟棄掉,,所以代碼看起來有點怪怪的:

理解了這一點,,看懂 C++ 代碼也就不難了。當(dāng)然,,無論是 C++ 還是 Java,,其 I/O 系統(tǒng)都非常復(fù)雜,有流式 I/O,也有緩沖區(qū) I/O,,操作的數(shù)據(jù)可以是控制臺 I/O,,也可以是文件 I/O。

類和封裝

首先說說 C++ 的 struct,,Java 沒有與之對應(yīng)的相似物的,,但是完全可以用 class 來替換這個概念。為什么這么說呢,?

因為在 C++ 中,struct 的位置有點尷尬,,它是個 POD 吧,,但它的成員又可以用非 POD 的數(shù)據(jù)類型,比如 std::string,,甚至還可以定義虛接口,,一旦有了這些東西,它就算不上 POD 了,,除了成員默認(rèn)是公有之外,,和 class 沒有太大差別。

在我看來,,C++ 保留 struct 的主要意義是為了兼容舊的 C 或 C++ 的庫,,這些庫中很多接口用到了 struct,其次是純粹作為一種 POD 的 value type 來使用,。

我的算法代碼中也會用到 struct,,大概是為了懷舊吧,其實完全可以用 class 代替,,當(dāng)然也可以很容易地翻譯成 Java 的 class,。來看個例子,對于這個 struct:

可以很輕松的轉(zhuǎn)成 class:

自從 C++11 發(fā)布以后,,我就覺得 C++ 和 Java 的 class 越來越像了,,分開這么多年后,C++ 終于也支持 final 和 override 了,。

從語法層面看,,二者的差異很小,就小規(guī)模的算法而言,,也很少會用到繼承和重載之類的情況,,所以,Java 程序員看懂 C++ 的 class 定義與實現(xiàn)一點都不難,。

少有的一些差異,,比如 C++ 的函數(shù)可以設(shè)置參數(shù)默認(rèn)值,或者 C++ 的抽象機制采用的虛函數(shù)要使用 virtual 關(guān)鍵字等,。先看一個典型的 C++ 類的定義與實現(xiàn):

C++ 的類成員訪問控制采用分節(jié)控制,,用 public:protected: 作為分節(jié)的標(biāo)志,,如果沒有分節(jié)標(biāo)志的類成員,則是默認(rèn)的 private: 控制,。

C++ 的成員函數(shù)可以有默認(rèn)值,,并且構(gòu)造函數(shù)也支持默認(rèn)值。以 Bucket 類為例,,構(gòu)造函數(shù)第二個參數(shù)默認(rèn)值是 0,,即在構(gòu)造 Bucket 對象時,可以只確定一個參數(shù) capicity,,也可以在確定 capicity 參數(shù)的同時,,確定 Bucket 的水量,比如:

Java 不支持參數(shù)默認(rèn)值,,但是可以通過重載函數(shù)解決這個問題,,即增加一個只有 capicity 參數(shù)的構(gòu)造函數(shù):

C++ 沒有抽象基類的語法,但是又抽象基類的概念,,一般當(dāng)一個類中有一個純虛函數(shù)的時候,,這個類是不能被直接實例化的,它就類似于是一個抽象基類,,比如:

C++ 的函數(shù)有很多類型修飾,,比如常見的 const,C++11 后新增了 final 和 override,,但是 = 0 一直是一個比較奇怪的存在,,它表明這個函數(shù)沒有實現(xiàn),需要在派生類中實現(xiàn),,同時,,也說明這個類是不能被實例化的。

對于這樣的機制,,Java 可以理解為這就是個抽象基類:

C++ 的繼承體系的語法與 Java 類似,,只是語法形式上不同,Java 采用關(guān)鍵字:extends,。

C++ 對于基類聲明的虛函數(shù),,繼承類中不需要再用 virtual 關(guān)鍵字修飾,當(dāng)然,,加了 virtual 關(guān)鍵字也沒錯誤,。Java 也一樣,abstract 關(guān)鍵字再繼承類中可以省去,。

從 Shape 抽象類派生一個 Circle 類,,C++ 的典型代碼是:

Circle 構(gòu)造函數(shù)后面的 :Shape(color),表示對基類的初始化,對于 Java 語言來說,,相當(dāng)于調(diào)用 super(color),。

以上代碼翻譯成 Java 語言,應(yīng)該是這樣的形式:

C++ 有時候也會將一個類聲明為 final,,意味著它不希望被其他類繼承,,從語法上做了限制,比如:

有時候,,是某個不希望被派生類重載,,比如:

這些對于 Java 程序員來說,并不陌生,,語法上只是 final 關(guān)鍵字的位置不同,,理解上應(yīng)該不存在任何問題。

總結(jié)

本文介紹了 C++ 和 Java 在基本語法層面的對應(yīng)關(guān)系,,因為算法代碼涉及的語言方面深度有限,所以本文介紹的內(nèi)容也比較基礎(chǔ),。

通過對比發(fā)現(xiàn)不管是用 C++ 還是用 Java 來寫算法,,差別基本不大,如果朋友們對算法想再深度了解,,可以看一下《算法應(yīng)該怎么“玩”,?》

課程中選擇了三十多個簡單且實用的算法實例,,這些算法實例基本覆蓋了各種算法比賽中經(jīng)常出現(xiàn)的題目以及生活中常見的一些有趣的算法實現(xiàn),。

每個算法實現(xiàn)都將講解的側(cè)重點放在各種算法的設(shè)計方法和思想在算法中的體現(xiàn),通過一個個算法例子,,來引導(dǎo)大家掌握常見的算法設(shè)計思想,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多