環境資訊中心綜合外電;姜唯 編譯;林大利 審校
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※回頭車貨運收費標準
※推薦評價好的iphone維修中心
※超省錢租車方案
※台中搬家遵守搬運三大原則,讓您的家具不再被破壞!
※推薦台中搬家公司優質服務,可到府估價
摘錄自2020年4月24日中央社報導
一般帶大量超級細菌的恆河,在印度全國封鎖近一個月後,因為幾乎沒有人類污染,瑜伽聖城瑞詩凱詩(Rishikesh)這段恆河河水,經政府檢測水質達到可飲用的標準。
印度北部北阿坎德省(Uttarakhand)污染控制局最近從瑞詩凱詩及哈里德瓦(Haridwar)的恆河河段抽樣進行化驗,發現水質可以飲用。
官方報告表示,哈基寶里河壇段的恆河水,生化需氧量(Biochemical oxygen demand)也下降20%。專家說,這意味著恆河水含氧量變高,水族可舒適地在河中呼吸。
印度中央污染控制局(Central Pollution Control Board)近日發表的調查報告顯示,恆河36個監測站中,有27個監測站測得恆河水質已變為可安全沐浴和水中生物可安全生活的水準。
生活環境
土地水文
土地利用
國際新聞
印度
封城
武漢肺炎
恆河
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※回頭車貨運收費標準
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※推薦評價好的iphone維修中心
※教你寫出一流的銷售文案?
※台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!
※台中搬家遵守搬運三大原則,讓您的家具不再被破壞!
28-15。88萬長安CS75可謂算得上自主SUV老牌勁旅中的一員了,整體外觀很硬派卻又不失時尚,天使眼造型的大燈犀利又帥氣。內飾整體是家族式的設計,1。5T車型全系標配了自動啟停功能,還有自動駐車、無鑰匙進入/啟動、倒車影像、感應雨刷等配置一應俱全。
又到了冷空氣入侵的時候了,你媽媽有沒有喊你穿秋褲呢,雖然南方的小夥伴還可以沐浴在溫暖的陽光中,但是北方的小夥伴們已經在激烈的雪球大戰中了,凍成狗的小學生都裹着棉被去上學了。
擠公交地鐵上班的就稍微沒那麼難受了,起碼不會再穩到那股難聞的汗酸味,最舒服的要數開車上班的孩子了,風吹日晒雨淋完全沒關係,不過一些沒有座椅加熱的真皮座椅還是給人冰涼涼的感覺。
廣汽乘用車-傳祺GA6
指導價:10.28-19.68萬
說起自主品牌中型車,傳祺GA6絕對是一款代表作,車身造型有很強的設計感,凌雲翼家族式設計元素,圓潤飽滿的大燈有着很高的辨識度;內飾的設計布局和做工有着堪比合資車的水準,配置上無鑰匙進入/啟動、自動駐車、上坡輔助、方向盤換擋等配置非常豐富。
4850×1830×1485mm的車身尺寸,軸距2720mm,乘坐空間表現良好,儲物空間設計很人性化,隨手可及;有着阿爾法羅密歐技術調校的底盤是一大亮點,行駛品質在自主品牌車型中屬於一流水平,1.5T(最大功率152馬力)+7擋雙離合的動力組合兼顧了動力和燃油經濟性,是比較實惠的一款車型。
一汽奔騰-奔騰B70
指導價:9.98-14.98萬
奔騰B70改款後設計風格上有了明顯的轉變,時尚動感的外觀視覺效果上還是相當吸引人的,熏黑的尾燈、黑色車頂、后擾流板彰顯了其運動氣息;搪塑工藝處理的中控台質感出色,中控屏波浪開口設計很個性化,黑色內飾搭配紅色縫線的設計突出了運動氛圍。
長*寬*高為4800*1820*1472mm,軸距達到了2725mm,最具亮點的就是它使用了與馬自達6相同的動力系統和底盤,技術成熟,開起來有合資車的感覺,1.8T(最大功率186馬力)+6擋手自一體變速器的組合動力響應很积極,轉向精準,車身緊湊底盤硬朗,懸挂支撐到位,操控感覺非常棒。
長安汽車-長安CS75
指導價:9.28-15.88萬
長安CS75可謂算得上自主SUV老牌勁旅中的一員了,整體外觀很硬派卻又不失時尚,天使眼造型的大燈犀利又帥氣;內飾整體是家族式的設計,1.5T車型全系標配了自動啟停功能,還有自動駐車、無鑰匙進入/啟動、倒車影像、感應雨刷等配置一應俱全。
新推出的1.5T(最大功率170馬力)車型動力表現已經超越2.0L(最大功率158馬力)發動機的表現,低扭表現相當出色,輕鬆帶動1.6噸的車身,動力輸出的線性程度堪比自然吸氣發動機,齒比設定相對密集的6擋手動變速器使得各個擋位的動力銜接更加順暢,唯一比較遺憾的就是1.5T車型暫時沒配備自動變速器了。
長城汽車-哈弗H2
指導價:8.68-12.88萬
紅藍雙標的戰略在哈弗H2看來是非常的成功的,藍標外觀更加年輕時尚化,紅標側重豪華家用,適合不同人群的需求;內飾無論是做工還是用料都給人很豪華的感覺,配置上也是越級的享受,自動頭燈、車內氛圍燈、倒車影像、定速巡航、陡坡緩降等配置在一款11萬的車型都能擁有。
其車身尺寸為4335*1814*1695mm,顯得比較緊湊,2560mm的軸距帶來的空間感受並不會感到擁擠,大量皮革包裹的門邊觸感良好;動力上依舊是我們熟悉的1.5T(最大功率150馬力)發動機,搭配6AT/6MT,起步輕鬆,渦輪介入後勁足,整體加速較為線性。
總結:自主車型現在無論是外觀還是內飾配置,相比於合資車都有很大的優勢,三大件方面質量也在逐步提高,尤其是哈弗品牌車型,個個都內外兼修,自主品牌已經有了非常大的提升了,值得入手。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※台北網頁設計公司全省服務真心推薦
※想知道最厲害的網頁設計公司"嚨底家"!
※推薦評價好的iphone維修中心
※網頁設計最專業,超強功能平台可客製化
※別再煩惱如何寫文案,掌握八大原則!
而這次加入1。5T發動機,就讓CR-V在現今的緊湊型SUV中立於不敗地位,燃油經濟性以及動力都可以達到一個相當優秀的地步,外觀上的改變也是能吸引更多的年輕用戶。不過競爭對手中的馬自達CX-4以及CX-5在燃油經濟性以及性能並不輸給CRV-V,以及奇駿在空間上的優點,CR-V要想突破這番困局還是需要視乎具體售價以及具體價格,若是能維持現今2。
編者總結:
毫無疑問,2.0L發動機被取代是毫無疑問的,畢竟現今服役的2.0L發動機有着不短的“年頭”。而這次加入1.5T發動機,就讓CR-V在現今的緊湊型SUV中立於不敗地位,燃油經濟性以及動力都可以達到一個相當優秀的地步,外觀上的改變也是能吸引更多的年輕用戶。不過競爭對手中的馬自達CX-4以及CX-5在燃油經濟性以及性能並不輸給CRV-V,以及奇駿在空間上的優點,CR-V要想突破這番困局還是需要視乎具體售價以及具體價格,若是能維持現今2.0L的價格,相信能給對手造成不少的衝擊。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線
※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整
※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!
※教你寫出一流的銷售文案?
※超省錢租車方案
※回頭車貨運收費標準
80萬其外觀犹如其名般,就是甲殼蟲的造型,外觀設計也非常可愛,圓圓的大燈,具有獨特的氣質,敞篷版甲殼蟲外形上和基本車型相比更拉風。車身比MX5還是霸氣不少,顯得更“強壯”些,復古式的輪圈設計十分扎眼,也更體現甲殼蟲其優雅端莊的形象。
汽車並不只是代步工具,還能成為另外一種生活方式、態度。說起敞篷車,我想每個人心中都想擁有屬於自己的敞篷車。沒有什麼比駕駛着敞篷車,沐浴在蔚藍海岸暖陽下,更為令人陶醉,享受當下!有些人會覺得這種生活離自己太遙遠、讓人觸手不及。但小編覺得只要心中所想,按着心裏想法去走,努力,必定實現。
馬自達(進口)-馬自達MX-5
(以下簡稱:MX-5)
平行進口價:34.5萬(手動)35.5萬(自動)
MX5給人第一感覺,非常親切,前臉就像一大大的微笑,很討人喜歡,車燈方面,更像雪亮雙眼,有神韻,感覺這就是一部充滿活力朝氣的車子。
車身很小巧、流暢車身線條,視覺效果動感十足。
內飾我想大家也非常熟悉,MX-5也不例外,內飾設計也是沿用馬自達一貫風格,但值得一提,MX-5螺旋狀出風口設計,顯得戰鬥力十足。
MX-5採用的軟頂敞篷設計,車身重量更輕。開蓬時間絕對要比上百萬級別要快!在2-3s就可以完成開蓬關蓬,夠快吧!這也完全取決你個人速度夠不夠快,因為MX-5開/關蓬是純手動開啟。
MX-5在動力方面,搭載了2.0L自然吸氣發動機,峰值扭矩201牛米,但由於車身較輕,和上代車型相比動力更出色。傳動系統配備6擋手動和6擋自動變速箱,手動車型動力輸出更直接,而且具有挑逗性。自動變速箱反應也是特別迅速,降檔积極,開起來很活躍。無論是購買手動還是自動,MX-5都能給你很好的駕駛樂趣。
大眾(進口)-甲殼蟲 2015款 180TSI 敞篷版
(以下簡稱:甲殼蟲)
指導價:28.80萬
其外觀犹如其名般,就是甲殼蟲的造型,外觀設計也非常可愛,圓圓的大燈,具有獨特的氣質,敞篷版甲殼蟲外形上和基本車型相比更拉風。
車身比MX5還是霸氣不少,顯得更“強壯”些,復古式的輪圈設計十分扎眼,也更體現甲殼蟲其優雅端莊的形象。
甲殼蟲內飾與外形設計一樣,很可愛,中控台設計也很簡潔,檔次感還是蠻高的。不同顏色裝飾板的點綴,讓其更具個性化。
甲殼蟲同樣和MX5一樣,採用了軟頂敞篷設計,但其開/關蓬時間卻要比MX5,慢了幾倍,車頂棚開啟時間為11s,而MX5,只需要2s,摺疊收起時間為9.5s,MX5隻需要2s!
甲殼蟲可在不超過50公里車速進行開關,而MX5卻是無論在任何車速都能隨時隨地去開關蓬!現在汽車開關蓬還分快慢?!而甲殼蟲更有逼格!逼格才是最重要!
這款甲殼蟲動力總成,搭載1.2T渦輪增壓發動機,最大功率77千瓦,峰值扭矩175牛米。或許你在想1.2T排量太小,但這你並無需擔心,因渦輪介入較早,油門初段很輕快,你甚至感覺這會是1.2T排量的車型嗎!時速在100公里以後,還是仍然感覺到較強的後勁,底盤行駛質感很紮實、從容。
編者點評:
當擁有足夠資金買一台敞篷車,其實更注重是其顏值與內飾是否高端大氣上檔次,而動力只是其次,開敞篷車,更多是一種情懷,另一種生活方式,可以享受比全景天窗更直接的陽光,比普通車型也更拉風。但在當今社會,敞篷車也有自身不足地方,例如空氣污染,要是天天敞開蓬駕駛,吸入的廢氣不容樂觀,有人說,戴口罩唄,那麼帶口罩開還買這車幹啥?還有就是中國的氣候,時冷時熱,敞篷駕駛,要麼冷死,要麼熱死曬死等問題,那麼當你去買一部敞篷車這些都是要去克服接納的問題,裝逼拉風可都是需要付出點代價啊。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※別再煩惱如何寫文案,掌握八大原則!
※網頁設計最專業,超強功能平台可客製化
※回頭車貨運收費標準
主觀加速感受還行,渦輪遲滯現象輕微,在國內限速的範圍內,動力輸出杠杠的夠用。地板油時會一臉懵逼地問你:“主人,要加速。”,遲滯一會兒才開始賣力加速,激烈駕駛時稱不上得心應手。CX-4: 動力輸出持續、線性,給你一種恰到好處的加速感,容易掌控,會給你持續有力、綿密的推背感。
十代思域憑藉其強悍的動力、驚艷的外觀和強大的綜合產品力在緊湊型車市場里呼風喚雨,儼然就是不少年輕人、中年消費群體心目中的神車。加價提車、排期候車自不用說,競品車型紛紛降價促銷、改款換代提高競爭力來應對思域。
友商們不可能眼睜睜看着本田獨攬着龐大的新消費群體,時隔兩個月,倔強的馬自達不甘示弱,推出了為年輕人而打造的轎跑SUV——CX-4,概念車般的外觀設計以及大膽的流體線條,以錯位的車型與思域短兵相接。
下面為手拿15萬預算,躊躇于思域與CX-4之間的年輕人提供點選車建議。
車身尺寸
前臉設計
思域:集未來感、科技感於一身,“X”樣式的前臉設計,粗碩的鍍鉻飾條延伸至兩邊眼角,十分提神。
CX-4:繼續沿用家族式的魂動設計,流星眼LED大燈,低俯的車頭給人以時刻準備衝刺的感覺,魂動紅配色(2000元)更是彰顯個性的一抹艷麗。
車身腰線
思域:溜背的造型是外觀設計最大的亮點,尾部過渡自然,甚顯修長。
CX-4: 最小離地間隙196mm, 有轎車低矮扁平的發動機蓋高度,亦有SUV高人一等的的氣勢,車身比例恰到好處,越看越有韻味,令人愛不釋手。
車尾設計
思域:大膽的迴旋鏢狀尾燈設計,尾標與時俱進地改為220Turbo,緊隨德系車以扭矩數值作為尾標銘牌的潮流。十分可惜的是雙邊共兩出的排氣管採用隱藏式設計,這是刻意為年輕人提供改裝餘地嗎?改改改!
CX-4:貫穿兩邊車尾燈的鍍鉻飾條承托着銀色車標,恰到好處的美。2.0L車型同樣採用了雙邊兩出的排氣布局,相比其他車型要厚道。
內飾設計
思域:整體風格簡潔,符合大眾審美。用料看起來不錯,但實際體現一般,滿滿的塑料感,很多摸得到的地方例如擋把的邊上、車窗按鈕、內部門拉手、駕駛座大腿右側頂到的地方、A柱和B柱都是硬塑料。慶幸的是,金屬拉絲面板的運用彰顯出科技感。
CX-4:強調簡約、清新的內飾風格,相比過去長安昂克賽拉和CX-5的整體視覺好的不是一星半點。運用了最新的懸浮式中控屏,採用不少金屬拉絲面板進行點綴,觀感和質感都得到提升。
空間
思域:貫徹本田MM Concept理念:乘員空間最大化、机械空間最小化理念。空間表現比大多數競品車型要優秀,尤其橫向空間,絲毫沒有緊湊型車壓迫的感覺。溜背造型並未對頭部空間造成太大影響,淺色頂棚加上較薄的前排座椅,不會覺得壓抑。
CX-4:漂亮的流體車身線條,必然要犧牲乘坐空間,頭部空間方面受影響更大,工程師只能將座位高度盡可能調低,實際體驗只能算差強人意。後排中央地板隆起較高,且窗口面積較少、採光不理想,給乘坐人員壓迫的感覺。
實用配置
發動機
思域:實測百公里提速時間讓人瞠目結舌——7.3秒,同價位車型中難覓對手。主觀加速感受還行,渦輪遲滯現象輕微,在國內限速的範圍內,動力輸出杠杠的夠用。地板油時會一臉懵逼地問你:“主人,要加速?”,遲滯一會兒才開始賣力加速,激烈駕駛時稱不上得心應手。
CX-4: 動力輸出持續、線性,給你一種恰到好處的加速感,容易掌控,會給你持續有力、綿密的推背感。值得一提的是,馬自達工程師稱將CX-4的油門遲滯時間調校為0.3秒(與人體肌肉慣性相關),油門反應跟駕駛者預期處於一個基本同步的狀態。實測百公里提速時間9.8秒,對動力要求較高的選2.5L版本。
變速箱
思域:動力迅而不猛,因為駕駛者與發動機之間隔着台溫文爾雅的變速箱,CVT在行駛過程中存在感低,但不拖泥帶水,能化解生硬的頓挫,淡化了加速時的衝擊感。會通過轉速切換去模擬一些細小的換擋頓挫,轉速變化的換擋控制與駕駛者的意圖、預期判斷基本一致、同步,整體表現不錯。
CX-4: 這台創馳藍天6AT變速箱在車速超過8km/h后其離合器完全鎖止,防止動力輸出在液力變矩器上出現過多損耗,提高傳動效率和優化燃油經濟性。很明白駕駛員意圖,執行力非常到位,一路上用細微的油門變化去挑逗它,都能很好滿足,彷彿時刻在等待你的命令。
底盤
思域:前麥弗遜式獨立懸架、后多連桿獨立懸架。路面小顛簸過濾得不錯,但保留了一定的路感信息傳遞給駕駛者,中後段對車身的支撐到位,富有運動感的懸架。
CX-4:前麥弗遜式獨立懸架、后多連桿獨立懸架。懸架支撐性出色,過彎、掉頭時的車身姿態控制到位,保留了清晰的路感,行駛表現接近“彎道王”昂克賽拉,比絕大多數SUV的行駛質感要好。
操控
思域:路感被過濾得所剩無幾,懸架行程較長,有一定曠量,過彎、掉頭姿態傾側明顯,屬於舒適家用車的調校範疇。所幸轉彎半徑小,掉頭方便。轉向低速沉穩,但速度上來后變輕。
CX-4:定位轎跑SUV不單是在外觀做文章,CX-4在操控方面亦盡量嚮往轎車方面靠攏。電動助力,指向精準,車頭指向靈活,車尾循跡性好,和不錯的駕駛樂趣,開起來不像是一台SUV。
總結:目前年輕消費群體對思域、CX-4兩款車青睞有加,前瞻性的外觀設計、優秀的動力表現和出眾的操控都是它們的亮點,預算有限的建議選思域1.5T自動尊貴版,而預算充足不妨體驗下CX-4 2.5L 自動四驅藍天激情版,動力相比2.0L得到提升的同時還配備了四驅系統,適應更多路況的行駛。 它們就像是未來汽車走向的先行者,期待有更多的後起之秀面世,讓年輕消費者有更多的選擇。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※南投搬家公司費用需注意的眉眉角角,別等搬了再說!
※教你寫出一流的銷售文案?
※回頭車貨運收費標準
※別再煩惱如何寫文案,掌握八大原則!
與此同時,還能通過手機遠程控制安防系統(T-BOX),隨時隨地了解控制車內外各種信息。新增的愛信6AT變速箱, 最大的優點就是平順性處於行業領先水平,質量穩定可靠,駕駛舒適性得到了提升。i-4WD智能適時四驅系統,具有兩驅、智能適時四驅及強制四驅等三種模式,極大地提高了傳祺GS4的越野性能。
如果說自主SUV的崛起,是得益於精品車型的話,那麼就不得不提傳祺GS4了,不俗的原創外觀+成熟的動力組合+大空間,正好符合了我們對一輛緊湊SUV的所有需求。
縱使傳祺GS4一經推出就取得了成功,但作為一款新車,還存在着很多進步的空間 。比如當時呼聲很高的“動力如果能有更多選擇就好了”,在今年初的時候,傳祺GS4 就順勢推出了235T(1.5T)動力配置,繼續鞏固了GS4銷量地位,在10月銷量中,傳祺GS4的成績已突破3.5萬。
後來,有更高要求的消費者又提出 “能不能增配6AT+四驅+後排出風口呢”?傳祺這次依舊沒讓我們失望!在半個月前,傳祺GS4就發布了2017新款,上述的功能都如我們所願,總共超過15項性能與配置升級!
2017款 傳祺GS4 235T 6AT版
指導價格:13.38-16.18萬
在廣州車展期間,小編也前往了傳祺展台目睹了新款GS4,但那個人山人海的場景依然歷歷在目,作為本地車企,在主場的人氣還是非常火爆的。
傳祺GS4 2017款15項配置升級中
最大的變化主要有以下3點
●車載互聯繫統
●愛信6AT+i-4WD
●後排出風口+USB接口
2017款GS4整合了百度CarLife車載互聯繫統,理論上支持所有Andriod系統手機,可實現語音控制,觸摸屏控制電話、音樂、地圖及其它App應用。
與此同時,還能通過手機遠程控制安防系統(T-BOX),隨時隨地了解控制車內外各種信息。
新增的愛信6AT變速箱, 最大的優點就是平順性處於行業領先水平,質量穩定可靠,駕駛舒適性得到了提升。
i-4WD智能適時四驅系統,具有兩驅、智能適時四驅及強制四驅等三種模式,極大地提高了傳祺GS4的越野性能。只需輕轉控制旋鈕,即可自由切換,兼顧燃油經濟性和通過性,最大爬坡度輕鬆≥40%。
後排新增出風口、雙USB接口與手機儲物盒,對於後排乘客而言,也豐富了乘車樂趣,因為都是非常實用的配置。同時,後排中央扶手及中央頭枕與後排隱私玻璃在2017款GS4中配車型即有所體現。
除這幾項大的升級之外,其餘的功能、性能升級在這就一一闡述了,想了解的朋友可以自己查一下產品資料。
小編最後點評
放眼所有汽車品牌,幾乎每個品牌都有屬於自己的品牌符號,像高爾夫之於大眾、卡羅拉之於豐田、3系之於寶馬。GS4之于于傳祺正是這樣,一款細分市場明星車型全面打響了品牌,成為了家喻戶曉的標杆產品。隨後又推出了GS8這款豪華大七座SUV,據小編了解,到目前為止已經收穫2萬個訂單了!在國產高端SUV銷量普遍不濟的情況下,GS8的勢頭非常奪人眼球。
在國產車裡,小編也不止一次推薦過GS4了,它和其他品牌不一樣,傳祺的原創設計、做工和自主核心技術非常成熟,不僅有了與合資同台競技的硬實力,還有了以後長久發展的根基,小編對它還是比較看好的。
2017款GS4的改款是成功的,豐富的產品線也趨於完善,配置升級非常實用,滿足了更多人的選車訴求。
更重要的是,價格方面也沒想象中大幅上漲,而是與1.5T 7速雙離合配置的價格保持了一致,聰明的定價相信也能俘虜不少新的消費者,繼續鞏固傳祺GS4在銷量榜的領先地位。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※想知道最厲害的網頁設計公司"嚨底家"!
※別再煩惱如何寫文案,掌握八大原則!
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※回頭車貨運收費標準
※台中搬家公司費用怎麼算?
二叉查找樹可能因為多次插入新節點導致失去平衡,使得查找效率低,查找的複雜度甚至可能會出現線性的,為了解決因為新節點的插入而導致查找樹不平衡,此時就出現了紅黑樹。
紅黑樹它一種特殊的二叉查找樹。紅黑樹的每個節點上都有存儲位表示節點的顏色,可以是紅(Red)或黑(Black)。它具有以下特點:
(1)每個節點或者是黑色,或者是紅色。
(2)根節點是黑色。
(3)每個恭弘=叶 恭弘子節點(恭弘=叶 恭弘子節點,是指為空(NIL或NULL)的恭弘=叶 恭弘子節點)是黑色。
(4)如果一個節點是紅色的,則它的子節點一定是黑色(即從根節點到恭弘=叶 恭弘子節點的路徑上不能有兩個重複的紅色節點)。
(5)從一個節點到其上每一個恭弘=叶 恭弘節點的所有路徑都具有相同的黑色節點個數。
① 將紅黑樹當作一顆二叉查找樹,將節點插入。
② 將插入的節點着色為”紅色”。(因為條件5,從一個節點到其中每一個節點的的所有路徑都具有相同的黑色節點)。
③通過一系列的旋轉(左旋或右旋操作)或着色等操作,使之重新成為一顆紅黑樹。
在java 1.7之前是用數組和鏈表一起組合構成HashMap,在java1.8之後就使用當鏈表長度超過8之後,就會將鏈錶轉化為紅黑樹,縮小查找的時間(紅黑樹維護也會花費大量時間,包含左旋、右旋和變色過程)。
hashmap構造函數會初始化三個值:
在初始化一個hashmap對象的時候,指定鍵值對的同時,也可以指定初始map的容量大小,假設此處我們指定大小為11,則會在構造函數中調用tableSizeFor將容量改為2的n冪次,即比當前容量大,而且必須是2的指數次冪的最小數,就會變成16。這是因為2的指數次冪便於計算進行位運算操作,提升運行效率問題(位運算>加法>乘法>除法>取模)。
hashmap的的默認值是16,負載因子默認是0.75,代碼如下:
//HashMap<String,String> hashMap = new HashMap<String, String>(11);
/**
* Returns a power of two size for the given target capacity.
**/
static final int tableSizeFor(int cap) {
int n = cap - 1; //10 防止在cap已經是2的n次冪的情況下
// >>> 表示不關心符號位,對數據的二進制形式進行右移 |表示或運算
n |= n >>> 1; //15
n |= n >>> 2; //15
n |= n >>> 4; //15
n |= n >>> 8; //15
n |= n >>> 16; //15
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; //16
}
這裏可以介紹一下&位運算,當我們將一對KV存儲到hashmap當中時,會通過(n – 1) & hash運算來定位將要插入的鍵值對放入到哈希表的某個桶中。其中n表示哈希表的長度,通常n為2的倍數,通過n-1即可n所表示的二進制數,除最高位外,全部轉化為1,藉助與運算即可快速完成取模操作。
//hashMap.put("2020", "good luck");
/**
* Implements Map.put and related methods.
*
* @param hash hash for key
* @param key the key
* @param value the value to put
* @param onlyIfAbsent if true, don't change existing value
* @param evict if false, the table is in creation mode.
* @return previous value, or null if none
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果hashtable沒有初始化,則初始化該table數組
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//通過位運算找到數組中的下標位置,如果數組中對應下標為空,則可以直接存放下去
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
//數組元素對應的位置已經有元素,產生碰撞
Node<K,V> e; K k;
//如果插入的元素key是已經存在的,則將新的value替換掉原來的舊值
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
//如果此時table數組對應的位置是紅黑樹結構,則將該節點插入紅黑樹中
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
//如果此時table數組對應的位置是鏈表結構
for (int binCount = 0; ; ++binCount) {
//遍歷到數組尾端,沒有與插入鍵值對相同的key,則將新的鍵值對插入鏈表尾部
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
//鏈表過長,將鏈錶轉化為紅黑樹
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
//發現鏈表中的某個節點有與插入鍵值對相同的key,則跳出循環,在循環外部重新賦值
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
//該key在hashmap已存在,更新與在鏈表跳出循環節點對應的值
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
//超過閾值則更新
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
/**
* Implements Map.get and related methods.
*
* @param hash hash for key
* @param key the key
* @return the node, or null if none
*/
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
//table數組不為空,且對應的下標位置也不為空。
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
//如果第一個位置是對應的key,則返回
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
//遍歷其他元素
if ((e = first.next) != null) {
//紅黑樹
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
//鏈表
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
/**
* Initializes or doubles table size. If null, allocates in
* accord with initial capacity target held in field threshold.
* Otherwise, because we are using power-of-two expansion, the
* elements from each bin must either stay at same index, or move
* with a power of two offset in the new table.
*
* @return the table
*/
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
//table不為空,且容量大於0
if (oldCap > 0) {
//如果舊的容量到達閾值,則不再擴容,閾值直接設置為最大值
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
//如果舊的容量沒有到達閾值,直接操作
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // double threshold
}
//閾值大於0,直接使用舊的閾值
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
//如果閾值為零,則使用默認的初始化值
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
//更新數組桶
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
//將之前舊數組桶的數據重新移到新數組桶中
if (oldTab != null) {
//依次遍歷舊table中每個數組桶的元素
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
//如果數組桶中含有元素
if ((e = oldTab[j]) != null) {
//將下標數據清空
oldTab[j] = null;
//如果元組的某一桶中只有一個元素,則直接將該元素移到新的位置去
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
//如果是紅黑樹結構
else if (e instanceof TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
//鏈表 -- 對舊桶里鏈表中的每一個元素重新計算哈希值得到下標
else { // preserve order
//將原先桶中的鏈表分為兩個鏈表
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
/*
* e.hash & oldCap 對hash取模運算,
* 雖然數組大小擴大了一倍,
* 但是同一個key在新舊table中對應的index卻存在一定聯繫:
* 要麼一致,要麼相差一個 oldCap。
*/
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
此處在處理鏈表的時候,如何將鏈表中的節點重新分配到新的哈希表需要做一些解釋。在擴容的時候,將原來的哈希表擴大了一倍,原來屬於同一個桶中的數據會被重新分配,此時取模運算時(a mod b),會注意到,b會擴大兩倍(a mod 2b),此時如果該桶中的某一個數據的哈希值是c1(0<c<b),則它必定還是會落入原來的位置,而如果桶中的某一個數據的哈希值是c2(b<c2<2b),則它會被重新分配到一個新的位置(這個位置是原先的哈希桶位置+舊桶的大小)。
HashMap在多線程的情況下出現的死循環現象
在某些java版本中擴容機制如果使用鏈表,且再插入時使用尾插法會出現死循環,具體原因可以參考老生常談,HashMap的死循環,在本文中所參考的java版本使用了頭插法的方式將元素添加到鏈表當中,可以避免死循環的出現,但是會出現一部分節點丟失的問題。如圖:
假設原始的哈希map的某個桶的數據如下,此時線程開始擴容,將桶中的數據分配到lo和hi桶的鏈表中。
初始時刻線程1和線程2開始運行,線程1在執行完以下代碼后,線程1的時間片運行結束。線程1運行的結果如圖所示
線程2與線程1同時運行,線程2的時間片未用完,還在繼續執行,根據代碼的分配策略,線程2直到時間片運行結束,出現如圖所示的結果:
此時CPU的時間片又被分配到了線程1,線程1繼續運行,因為此時A所在的鏈表結構已經發生了變化,只能處理A,B,D三個元素。此時線程1創建的hashmap如圖:
教你初步了解紅黑樹
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※別再煩惱如何寫文案,掌握八大原則!
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※超省錢租車方案
※教你寫出一流的銷售文案?
※網頁設計最專業,超強功能平台可客製化
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※台中搬家遵守搬運三大原則,讓您的家具不再被破壞!
在應用開發過程中經常需要對其他應用或者客戶端提供 RESTful API 接口,尤其是在版本快速迭代的開發過程中,修改接口的同時還需要同步修改對應的接口文檔,這使我們總是做着重複的工作,並且如果忘記修改接口文檔,就可能造成不必要的麻煩。
為了解決這些問題,Swagger 就孕育而生了,那讓我們先簡單了解下。
Swagger 是一個規範和完整的框架,用於生成、描述、調用和可視化 RESTful 風格的 Web 服務。
總體目標是使客戶端和文件系統作為服務器,以同樣的速度來更新。文件的方法、參數和模型緊密集成到服務器端的代碼中,允許 API 始終保持同步。
下面我們在 Spring Boot 中集成 Swagger 來構建強大的接口文檔。
Spring Boot 集成 Swagger 主要分為以下三步:
首先創建一個項目,在項目中加入 Swagger 依賴,項目依賴如下所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
接下來在 config 包下創建一個 Swagger 配置類 Swagger2Configuration,在配置類上加入註解 @EnableSwagger2,表明開啟 Swagger,注入一個 Docket 類來配置一些 API 相關信息,apiInfo() 方法內定義了幾個文檔信息,代碼如下:
@Configuration
@EnableSwagger2
public class Swagger2Configuration {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// swagger 文檔掃描的包
.apis(RequestHandlerSelectors.basePackage("com.wupx.interfacedoc.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("測試接口列表")
.description("Swagger2 接口文檔")
.version("v1.0.0")
.contact(new Contact("wupx", "https://www.tianheyu.top", "wupx@qq.com"))
.license("Apache License, Version 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.build();
}
}
列舉其中幾個文檔信息說明下:
在 domain 包下創建一個 User 實體類,使用 @ApiModel 註解表明這是一個 Swagger 返回的實體,@ApiModelProperty 註解表明幾個實體的屬性,代碼如下(其中 getter/setter 省略不显示):
@ApiModel(value = "用戶", description = "用戶實體類")
public class User {
@ApiModelProperty(value = "用戶 id", hidden = true)
private Long id;
@ApiModelProperty(value = "用戶姓名")
private String name;
@ApiModelProperty(value = "用戶年齡")
private String age;
// getter/setter
}
最後,在 controller 包下創建一個 UserController 類,提供用戶 API 接口(未使用數據庫),代碼如下:
@RestController
@RequestMapping("/users")
@Api(tags = "用戶管理接口")
public class UserController {
Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());
@GetMapping("/")
@ApiOperation(value = "獲取用戶列表", notes = "獲取用戶列表")
public List<User> getUserList() {
return new ArrayList<>(users.values());
}
@PostMapping("/")
@ApiOperation(value = "創建用戶")
public String addUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
@GetMapping("/{id}")
@ApiOperation(value = "獲取指定 id 的用戶")
@ApiImplicitParam(name = "id", value = "用戶 id", paramType = "query", dataTypeClass = Long.class, defaultValue = "999", required = true)
public User getUserById(@PathVariable Long id) {
return users.get(id);
}
@PutMapping("/{id}")
@ApiOperation(value = "根據 id 更新用戶")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用戶 id", defaultValue = "1"),
@ApiImplicitParam(name = "name", value = "用戶姓名", defaultValue = "wupx"),
@ApiImplicitParam(name = "age", value = "用戶年齡", defaultValue = "18")
})
public User updateUserById(@PathVariable Long id, @RequestParam String name, @RequestParam Integer age) {
User user = users.get(id);
user.setName(name);
user.setAge(age);
return user;
}
@DeleteMapping("/{id}")
@ApiOperation(value = "刪除用戶", notes = "根據 id 刪除用戶")
@ApiImplicitParam(name = "id", value = "用戶 id", dataTypeClass = Long.class, required = true)
public String deleteUserById(@PathVariable Long id) {
users.remove(id);
return "success";
}
}
啟動項目,訪問 http://localhost:8080/swagger-ui.html,可以看到我們定義的文檔已經在 Swagger 頁面上显示了,如下圖所示:
到此為止,我們就完成了 Spring Boot 與 Swagger 的集成。
同時 Swagger 除了接口文檔功能外,還提供了接口調試功能,以創建用戶接口為例,單擊創建用戶接口,可以看到接口定義的參數、返回值、響應碼等,單擊 Try it out 按鈕,然後點擊 Execute 就可以發起調用請求、創建用戶,如下圖所示:
由於 Swagger 2 提供了非常多的註解供開發使用,這裏列舉一些比較常用的註解。
@Api 用在接口文檔資源類上,用於標記當前類為 Swagger 的文檔資源,其中含有幾個常用屬性:
@ApiOperation 用在接口文檔的方法上,主要用來註解接口,其中包含幾個常用屬性:
@ApiResponses 和 @ApiResponse 二者配合使用返回 HTTP 狀態碼。@ApiResponses 的 value 值是 @ApiResponse 的集合,多個 @ApiResponse 用逗號分隔,其中 @ApiResponse 包含的屬性如下:
@ApiParam 用於方法的參數,其中包含以下幾個常用屬性:
二者配合使用在 API 方法上,@ApiImplicitParams 的子集是 @ApiImplicitParam 註解,其中 @ApiImplicitParam 註解包含以下幾個參數:
API 文檔的響應頭,如果需要設置響應頭,就將 @ResponseHeader 設置到 @ApiResponse 的 responseHeaders 參數中。@ResponseHeader 提供了以下幾個參數:
設置 API 響應的實體類,用作 API 返回對象。@ApiModel 提供了以下幾個參數:
設置 API 響應實體的屬性,其中包含以下幾個參數:
到此為止,我們就介紹完了 Swagger 提供的主要註解。
Swagger 可以輕鬆地整合到 Spring Boot 中構建出強大的 RESTful API 文檔,可以減少我們編寫接口文檔的工作量,同時接口的說明內容也整合入代碼中,可以讓我們在修改代碼邏輯的同時方便的修改接口文檔說明,另外 Swagger 也提供了頁面測試功能來調試每個 RESTful API。
如果項目中還未使用,不防嘗試一下,會發現效率會提升不少。
本文的完整代碼在 https://github.com/wupeixuan/SpringBoot-Learn 的 interface-doc 目錄下。
最好的關係就是互相成就,大家的在看、轉發、留言三連就是我創作的最大動力。
參考
http://swagger.io
https://github.com/wupeixuan/SpringBoot-Learn
《Spring Boot 2 實戰之旅》
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※超省錢租車方案
※別再煩惱如何寫文案,掌握八大原則!
※回頭車貨運收費標準
※教你寫出一流的銷售文案?
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※網頁設計最專業,超強功能平台可客製化
本文始發於個人公眾號:TechFlow,原創不易,求個關注
今天這篇是算法與數據結構專題的第23篇文章,我們繼續數論相關的算法,來看看大名鼎鼎的埃式篩法。
我們都知道在數學領域,素數非常重要,有海量的公式和研究關於素數,比如那個非常著名至今沒有人解出來的哥德巴赫猜想。和數學領域一樣,素數在信息領域也非常重要,有着大量的應用。舉個簡單的例子,很多安全加密算法也是利用的質數。我們想要利用素數去進行各種計算之前,總是要先找到素數。所以這就有了一個最簡單也最不簡單的問題,我們怎麼樣來尋找素數呢?
尋找素數最樸素的方法當然是一個一個遍歷,我們依次遍歷每一個數,然後分別判斷是否是素數。所以問題的核心又回到了判斷素數上,那麼怎麼判斷一個數是不是素數呢?
素數的性質只有一個,就是只有1和它本身這兩個因數,我們要判斷素數也只能利用這個性質。所以可以想到,假如我們要判斷n是否是素數,可以從2開始遍歷到n-1,如果這n-1個數都不能整除n,那麼說明n就是素數。這個我沒記錯在C語言的練習題當中出現過,總之非常簡單,可以說是最簡單的算法了。
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
return n != 1
顯然,這個算法是可以優化的,比如當n是偶數的時候,我們根本不需要循環,除了2意外的偶數一定是合數。再比如,我們循環的上界其實也沒有必要到n-1,到就可以了。因為因數如果存在一定是成對出現的,如果存在小於根號n的因數,那麼n除以它一定大於根號n。
這個改進也很簡單,稍作改動即可:
def is_prime(n):
if n % 2 == 0 and n != 2:
return False
for i in range(3, int(math.sqrt(n) + 1)):
if n % i == 0:
return False
return n != 1
這樣我們把O(n)的算法優化到了O()也算是有了很大的改進了,但是還沒有結束,我們還可以繼續優化。數學上有一個定理,只有形如6n-1和6n+1的自然數可能是素數,這裏的n是大於等於1的整數。
這個定理乍一看好像很高級,但其實很簡單,因為所有自然數都可以寫成6n,6n+1,6n+2,6n+3,6n+4,6n+5這6種,其中6n,6n+2,6n+4是偶數,一定不是素數。6n+3可以寫成3(2n+1),顯然也不是素數,所以只有可能6n+1和6n+5可能是素數。6n+5等價於6n-1,所以我們一般寫成6n-1和6n+1。
利用這個定理,我們的代碼可以進一步優化:
def is_prime(n):
if n % 6 not in (1, 5) and n not in (2, 3):
return False
for i in range(3, int(math.sqrt(n) + 1)):
if n % i == 0:
return False
return n != 1
雖然這樣已經很快了,但仍然不是最優的,尤其是當我們需要尋找大量素數的時候,仍會消耗大量的時間。那麼有沒有什麼辦法可以批量查找素數呢?
有,這個方法叫做埃拉托斯特尼算法。這個名字念起來非常拗口,這是一個古希臘的名字。此人是個古希臘的大牛,是大名鼎鼎的阿基米德的好友。他雖然沒有阿基米德那麼出名,但是也非常非常厲害,在數學、天文學、地理學、文學、歷史學等多個領域都有建樹。並且還自創方法測量了地球直徑、地月距離、地日距離以及黃赤交角等諸多數值。要知道他生活的年代是兩千五百多年前,那時候中國還是春秋戰國時期,可以想見此人有多厲害。
我們今天要介紹的埃拉托斯特尼算法就是他發明的用來篩選素數的方法,為了方便我們一般簡稱為埃式篩法或者篩法。埃式篩法的思路非常簡單,就是用已經篩選出來的素數去過濾所有能夠被它整除的數。這些素數就像是篩子一樣去過濾自然數,最後被篩剩下的數自然就是不能被前面素數整除的數,根據素數的定義,這些剩下的數也是素數。
舉個例子,比如我們要篩選出100以內的所有素數,我們知道2是最小的素數,我們先用2可以篩掉所有的偶數。然後往後遍歷到3,3是被2篩剩下的第一個數,也是素數,我們再用3去篩除所有能被3整除的數。篩完之後我們繼續往後遍歷,第一個遇到的數是7,所以7也是素數,我們再重複以上的過程,直到遍歷結束為止。結束的時候,我們就獲得了100以內的所有素數。
如果還不太明白,可以看下下面這張動圖,非常清楚地還原了這整個過程。
不見圖 請翻牆
這個思想非常簡單,理解了之後寫出代碼來真的很容易:
def eratosthenes(n):
primes = []
is_prime = [True] * (n + 1)
for i in range(2, n+1):
if is_prime[i]:
primes.append(i)
# 用當前素數i去篩掉所有能被它整除的數
for j in range(i * 2, n+1, i):
is_prime[j] = False
return primes
我們運行一次代碼看看:
和我們的預期一樣,獲得了小於100的所有素數。我們來分析一下篩法的複雜度,從代碼當中我們可以看到,我們一共有了兩層循環,最外面一層循環固定是遍歷n次。而裏面的這一層循環遍歷的次數一直在變化,並且它的運算次數和素數的大小相關,看起來似乎不太方便計算。實際上是可以的,根據素數分佈定理以及一系列複雜的運算(相信我,你們不會感興趣的),我們是可以得出篩法的複雜度是。
篩法的複雜度已經非常近似了,因為即使在n很大的時候,經過兩次ln的計算,也非常近似常數了,實際上在絕大多數使用場景當中,上面的算法已經足夠應用了。
但是仍然有大牛不知滿足,繼續對算法做出了優化,將其優化到了的複雜度。雖然從效率上來看並沒有數量級的提升,但是應用到的思想非常巧妙,值得我們學習。在我們理解這個優化之前,先來看看之前的篩法還有什麼可以優化的地方。比較明顯地可以看出來,對於一個合數而言,它可能會被多個素數篩去。比如38,它有2和19這兩個素因數,那麼它就會被置為兩次False,這就帶來了額外的開銷,如果對於每一個合數我們只更新一次,那麼是不是就能優化到了呢?
怎麼樣保證每個合數只被更新一次呢?這裏要用到一個定理,就是每個合數分解質因數只有的結果是唯一的。既然是唯一的,那麼一定可以找到最小的質因數,如果我們能夠保證一個合數只會被它最小的質因數更新為False,那麼整個優化就完成了。
那我們具體怎麼做呢?其實也不難,我們假設整數n的最小質因數是m,那麼我們用小於m的素數i乘上n可以得到一個合數。我們將這個合數消除,對於這個合數而言,i一定是它最小的質因數。因為它等於i * n,n最小的質因數是m,i 又小於m,所以i是它最小的質因數,我們用這樣的方法來生成消除的合數,這樣來保證每個合數只會被它最小的質因數消除。
根據這一點,我們可以寫出新的代碼:
def ertosthenes(n):
primes = []
is_prime = [True] * (n+1)
for i in range(2, n+1):
if is_prime[i]:
primes.append(i)
for j, p in enumerate(primes):
# 防止越界
if p > n // i:
break
# 過濾
is_prime[i * p] = False
# 當i % p等於0的時候說明p就是i最小的質因數
if i % p == 0:
break
return primes
到這裏,我們關於埃式篩法的介紹就告一段落了。埃式篩法的優化版本相對來說要難以記憶一些,如果記不住的話,可以就只使用優化之前的版本,兩者的效率相差並不大,完全在可以接受的範圍之內。
篩法看着代碼非常簡單,但是非常重要,有了它,我們就可以在短時間內獲得大量的素數,快速地獲得一個素數表。有了素數表之後,很多問題就簡單許多了,比如因數分解的問題,比如信息加密的問題等等。我每次回顧篩法算法的時候都會忍不住感慨,這個兩千多年前被發明出來的算法至今看來非但不過時,仍然還是那麼巧妙。希望大家都能懷着崇敬的心情,理解算法當中的精髓。
如果喜歡本文,可以的話,請點個關注,給我一點鼓勵,也方便獲取更多文章。
本文使用 mdnice 排版
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計最專業,超強功能平台可客製化
※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面
※回頭車貨運收費標準
※推薦評價好的iphone維修中心
※教你寫出一流的銷售文案?
※台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!
※台中搬家公司費用怎麼算?