日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解数据结构和算法

發布時間:2024/4/11 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解数据结构和算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

hi,大家好,我是阿榮,今天分享一些對數據結構和算法精華總結,希望對大家的面試或者工作有一定的幫助;

看完本文可以學到什么

  • 知道哪些數據結構和算法在實際工作中最常用,最重要

  • 理解一些設計上注意事項(經驗總結)

  • 掌握常用數據結構和算法核心知識點

數據結構

工作中或者開源項目中最常用數據結構:數組/list + hash + tree

O(n)結構:list/棧/隊列

O(1)結構:數組/hash/位圖

O(logn)樹形結構:紅黑樹/B+樹/skip list

數組

核心點:

1 內存空間大小固定,如果支持動態擴展,需要內存遷移,有一定的性能代價,比如C++ STL的vector結構;

2 內存連續,對CPU cache友好,如果內存空間足夠,能用數組就最好用數組結構;

3 ?數組空間一般都是預分配的,不會頻繁申請和釋放,所以可以提供程序性能,這個做內存池優化的實現手段;

鏈表

核心點:

  • 可以動態項擴縮容,比較節約空間;

  • 鏈表編程邊界case檢查:??

  • 每個節點必須有個“指針“要么指向其他節點,要么為空,這樣才能把鏈表串起來,任何操作都必須保證鏈表完整性,不允許節點無故脫鏈,所以任何操作之前,都要思考會不會導致節點脫鏈,如果不下心脫鏈就會存在內存泄漏風險;

  • 鏈表作為最基礎數據結構,很多高級結構:隊列,棧,hash,二叉樹,都是在鏈表基礎上演化而來;

編程技巧

  • 頭結點解決什么問題?

  • 頭結點:是虛擬出來的一個節點,不保存數據。頭結點的next指針指向鏈表中的第一個節點。對于頭結點,數據域可以不存儲任何信息,也可存儲如鏈表長度等附加信息。頭結點不是鏈表所必需的。

    頭指針:是指向第一個結點的指針,如果鏈表沒有引入頭結點,那么頭指針指向的是鏈表的第一個結點。頭指針是鏈表所必需的。

    [注意]無論是否有頭結點,頭指針始終指向鏈表的第一個結點。如果有頭結點,頭指針就指向頭結點。

    1)對鏈表的刪除、插入操作時,第一個結點的操作更方便

    如果鏈表沒有頭結點,那么頭指針指向的是鏈表的第一個結點,當在第一個結點前插入一個節點時,那么頭指針要相應指向新插入的結點,把第一個結點刪除時,頭指針的指向也要更新。也就是說如果沒有頭結點,我們需要維護著頭指針的指向更新。因為頭指針指向的是鏈表的第一個結點,如果引入頭結點的話,那么頭結點的next始終都是鏈表的第一個結點。

    2)統一空表和非空表的處理

    有了頭結點之后頭指針指向頭結點,不論鏈表是否為空,頭指針總是非空,而且頭結點的設置使得對鏈表的第一個位置上的操作與在表中其它位置上的操作一致,即統一空表和非空表的處理

  • 鏈表最常規操作

  • 刪除: ?遍歷鏈表,找到刪除的節點,保存刪除節點的pre節點和next節點;

    然后pre和next 串起來

    static inline void __list_del(struct list_head * prev, struct list_head * next) {next->prev = prev;prev->next = next; }

    再釋放刪除節點內存;

    添加: ?遍歷鏈表找到要加入位置(或者節點),保存該節點的pre節點和next節點,然后把新接入插入到鏈表中:

    static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next) {next->prev = new;new->next = next;new->prev = prev;prev->next = new; }

    2 ?快慢指針,快慢指針一般都初始化指向鏈表的頭結點 head,前進時快指針 fast 在前,慢指針 slow 在后,巧妙解決一些鏈表中的問題。比如:判定鏈表中是否含有環,尋找鏈表的中點, 尋找距離尾部第K個節點等;

    3 dummy node,dummy node是鏈表問題中一個重要的技巧,中文翻譯叫“啞節點”,使用通常針對單鏈表沒有前向指針的問題,保證鏈表的 head不會在刪除操作中丟失,當鏈表的 head 有可能變化(被修改或者被刪除)時,使用 dummy node 可以很好的簡化代碼,最終返回 dummy.next 即新的鏈表。

    4 通常鏈表有兩種實現方式,一種是抽象獨立型,一種是傳統耦合型

    list作為常用數據結構,寫代碼時候經常會遇到,可以看一下傳統list設計和抽象list設計有什么不一樣。

    一般的雙向鏈表一般是如下的結構:

    • 有個單獨的頭結點(head)

    • 每個節點(node)除了包含必要的數據之外,還有2個指針(pre,next)

    • pre指針指向前一個節點(node),next指針指向后一個節點(node)

    • 頭結點(head)的pre指針指向鏈表的最后一個節點

    • 最后一個節點的next指針指向頭結點(head)

    傳統list如下圖:

    傳統的鏈表不同node類型,需要重新定義結構,不夠通用化,還需要為node實現脫鏈、入鏈操作等。

    我們需要抽象出一個“基類”來實現鏈表的功能,其他數據結構只需要簡單的繼承這個鏈表類就可以了。

    抽象型list設計如下:

    • 鏈表不是將用戶數據保存在鏈表節點中,而是將鏈表節點保存在用戶數據中

    • 鏈表節點只有2個指針(prev和next)

    • prev指針指向前一個節點的鏈表節點,next指針指向后一個節點(node)的鏈表節點

    如下圖:

    這樣設計的好處是鏈表的節點將獨立于用戶數據之外,便于把鏈表的操作獨立出來,和具體數據節點無關,這里可能有些人會問,數據節點怎么訪問呢?通過一個container_of的宏從鏈表節點找到數據節點起始地址:

    找到數據節點起始地址后,通過數據節點定義就可以訪問數據。

    5 鏈表最核心技巧,就是理解指針操作(包括安全檢查-空指針判斷),不要被指針復雜的賦值操作搞暈,多敲代碼,找到經典的鏈表練習題(28原則)不斷練習,比如:判斷鏈表是否有環,反轉鏈表,合并鏈表等,寫好每一題,再認真總結,唯有熟才能生巧。


    核心點:

    • 需要關注棧的深度大小(容量);

    • 棧各個極端情況處理,比如空,滿,溢出等;

    • 多線程下實現安全的棧操作;

    • 堆棧很容易被攻擊(緩沖區溢出攻擊),程序員必須特別注意避免這些實現的陷阱, 防止代碼產生安全漏洞;

    使用場景

    1 ?操作系統程序運行棧,實現函數調用運行機制;

    2 ?操作前進和后退,比如編輯器,瀏覽器等;

    3 ?編譯器使用,比如表達式解析,語法檢查等;

    隊列

    核心點:

    • 隊列核心作用:應用耦合、異步處理、流量削鋒(緩沖);

    • 隊列各個極端情況處理,比如空,滿,溢出等;

    • 隊列支持多線程并發操作,加鎖或者無鎖隊列實現;

    • 隊列零拷貝優化,比如隊列操作零拷貝(操作指針地址或者索引),IO零拷貝;

    使用場景

    1 各種消息隊列中間件,比如RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等;

    2 各種排隊(緩沖區)系統,操作系統任務FIFO調度隊列,數據包發送隊列,凡是需要滿足FIFO場景,都是可以用隊列實現;

    Hash結構:

    hash結構核心點:

  • Hash是以空間換時間結構,需要評估好所有Hash頭結構的內存使用量;

  • Hash桶選擇需要考慮到內存和沖突鏈長度大小(影響查找效率);

  • hash的優化 --解決hash沖突

    3.1 內存有限場景下,就需要優化沖突鏈結構(鏈表轉紅黑樹);

    3.2 優化hash函數,讓hash結果更均勻;

    3.3 可以考慮雙重hash(空間和時間,還有編碼復雜度的一種折中方案)

    ?

  • 需要考慮hash擴容

    4.1 在設計hash結構的時候,需要考慮未來可用戶量增長后導致規格變大,這樣原先hash結構已經不合適,沖突鏈太長,導致查詢效率急速降低,所以再最初設計的時候,需要考慮到rehash設計(為什么不一次設置為最大,因為內存不是無限的,需要考慮一定時間還可以提供很好的服務,不需要升級版本),當hash沖突鏈太長后,進行rehash流程;

    4.2 rehash算法有很多,需要考慮幾點:

    a. 要不要保證hash一致性,擴容后,重hash還是不變,這個在負載均衡網關里面很重要,需要保證hash選擇RS后端服務節點不變,否則會到存量連接走到其他RS節點,讓服務變得不可用,甚至斷開(tcp需要建立會話,其他RS沒有這個會話)等。?所以這里可能會采用一致性hash算法,或者其他hash算法,保證相同client去相同RS。

  • b. 在rehash過程中,由于需要保證業務正常,需要保證在修改過程中,所以為了減少鎖影響,一般采用雙份內存,逐步把原hash數據遷移到新hash結構(防止大規模rehash導致CPU性能瓶頸),當存量遷移完后,可以快速加鎖切換hash結構,這樣可以減少服務不可用時間;

  • 其實redis的rehash算法,就是類似這種,屬于漸進式rehash算法, 好處在于它采取分而治之的方式, 將 rehash 鍵值對所需的計算工作均灘到對字典的每個添加、刪除、查找和更新操作上, 從而避免了集中式 rehash 而帶來的龐大計算量。

    業界還有其他擴容的算法,比如Linear Hash Tables是一種動態擴展空間的哈希表,會隨著插入的元素的增多而自動擴展空間等;

    使用場景

    1 redis的dict結構設計;

    2 簽名算法MD5算法;

    3 數據包校驗 CRC算法;

    4 負載均衡LB選擇后端服務器hash算法;

    5 布隆過濾器:布隆過濾器被廣泛用于黑名單過濾、垃圾郵件過濾、爬蟲判重系統以及緩存穿透問題。對于數量小,內存足夠大的情況,我們可以直接用hashMap或者hashSet就可以滿足這個活動需求了。但是如果數據量非常大,比如5TB的硬盤上放滿了用戶的參與數據,需要一個算法對這些數據進行去重,取得活動的去重參與用戶數。這種時候,布隆過濾器就是一種比較好的解決方案了。

    位圖(Bitmap)

    核心點:

    • 即位(Bit)的集合,是一種數據結構,可用于記錄大量的0-1狀態,在很多地方都會用到,優勢是可以在一個非常高的空間利用率下保存大量0-1狀態。

    • 本質上是采用了bit位來表示元素狀態,從而在特定場景下能夠極大的節省存儲空間,非常適合對海量數據的查找,判重,刪除等問題的處理;

    • 數據稀疏。又比如要存入(10,8887983,93452134)這三個數據,我們需要建立一個 99999999 長度的 BitMap ,但是實際上只存了3個數據,這時候就有很大的空間浪費,碰到這種問題的話,可以通過引入 Roaring BitMap 來解決,就是通過壓縮算法進行空間壓縮。

    • 數據碰撞。比如將字符串映射到 BitMap 的時候會有碰撞的問題,那就可以考慮用 Bloom Filter 來解決,Bloom Filter 使用多個 Hash 函數來減少沖突的概率

    使用場景

    1 在Java里面一個int類型占4個字節,假如要對于10億個int數據進行處理呢?10億*4/1024/1024/1024=4個G左右,需要4個G的內存。如果能夠采用bit儲,10_0000_0000Bit=1_2500_0000byte=122070KB=119MB, 那么在存儲空間方面可以大大節省。在Java里面,BitMap已經有對應實現的數據結構類java.util.BitSet,BitSet的底層使用的是long類型的數組來存儲元素。

    2 redis bitmap;

    3 布隆過濾器;

    4 ?Linux內核(如inode,磁盤塊);

    紅黑樹

    核心點

    • 在已經有了AVL之類的BBST,為什么還需要引入紅黑樹?我們希望數據結構具有關聯性,即相鄰版本之間,比如說第一次插入,和第二次插入時,樹的結構不能發生太大變化,應該可以經過O(1)次數就可以變化完成。對于AVL樹來說,插入是滿足這個條件的,刪除卻不滿足這個條件。紅黑樹就滿足這一特性,插入和刪除操作后的拓撲變化不會超過O(1)。

    • 紅黑樹與AVL樹相似,但提供更快的實時有界最壞情況下的插入和刪除性能(分別達到最多兩輪和三輪以平衡樹),但速度稍慢(但仍為O(log n))查找時間;

    • 紅黑樹和AVL樹一樣都對插入時間、刪除時間和查找時間提供了最好可能的最壞情況擔保。這不只是使它們在時間敏感的應用,如實時應用(real time application)中有價值,而且使它們有在提供最壞情況擔保的其他數據結構中作為基礎模板的價值;例如,在計算幾何中使用的很多數據結構都可以基于紅黑樹實現。

    • 紅黑樹在函數式編程中也特別有用,在這里它們是最常用的持久數據結構(persistent data structure)之一,它們用來構造關聯數組和集合,每次插入、刪除之后它們能保持為以前的版本。除了的時間之外,紅黑樹的持久版本對每次插入或刪除需要的空間。

    • 紅黑樹相對于AVL樹來說,犧牲了部分平衡性以換取插入/刪除操作時少量的旋轉操作,整體來說性能要優于AVL樹。

    • 維護紅黑樹的平衡需要考慮7種不同的情況:

    • 紅黑樹為什么綜合性能好?

    因為紅黑樹利用了緩存。

    Robert Sedgewick, ?紅黑樹的發明人,在《算法(第4版)》 中說過, 紅黑樹等價于2-3樹, 換句話說,對于每個2-3樹,都存在至少一個數據元素是同樣次序的紅黑樹。在2-3樹上的插入和刪除操作也等同于在紅黑樹中顏色翻轉和旋轉。這使得2-3樹成為理解紅黑樹背后的邏輯的重要工具,這也是很多介紹算法的教科書在紅黑樹之前介紹2-3樹的原因,盡管2-3樹在實踐中不經常使用。

    其中2-節點 等價于普通平衡二叉樹的節點,3-節點 本質上是非平衡性的緩存

    當需要再平衡(rebalance)時,增刪操作時,2-節點 與 3-節點間 的 轉化會吸收不平衡性,減少旋轉次數,使再平衡盡快結束。

    在綜合條件下,增刪操作相當時,數據的隨機性強時,3-節點的非平衡性緩沖效果越明顯。因此紅黑樹的綜合性能更優。

    繼續追根溯源,紅黑樹的性能優勢,本質上是用空間換時間

    發展:

    我們將紅黑樹分成這么幾種類型:左傾紅黑樹、右傾紅黑樹、AA樹。

    左傾紅黑樹(LLRB,Left-Learning Red-Black Tree),一個節點如果有紅色子節點,那么,它的紅色子節點是向左傾斜的。

    右傾紅黑樹(RLRB,Right-Learning Red-Black Tree),也是一樣的道理,即紅色子節點向右傾斜。

    左傾紅黑樹(*LLRB**)是一種類型的自平衡二叉查找樹。它是紅黑樹的變體,并保證對操作相同漸近的復雜性,但被設計成更容易實現。

    AA樹是紅黑樹的一種變種,是Arne Andersson教授在1993年年在他的論文"Balanced search trees made simple"中介紹,設計的目的是減少紅黑樹考慮的不同情況,區別于紅黑樹的是,AA樹的紅節點只能作為右葉子,從而大大簡化了維護2-3樹的模擬,因為AA樹有嚴格的條件(紅節點只能為右節點),故只需考慮2種情形:

    使用場景

    1 C++

    廣泛用在C++的STL中。如map和set都是用紅黑樹實現的;

    2 Java

    Java的TreeMap實現;

    HashMap的底層實現,在JDK1.8中為了解決過度哈希沖突帶來的長鏈表,當鏈表長度大于某個閾值會將鏈表轉為紅黑樹;

    3 Linux操作系統

    ?????CFS進程調度算法中,vruntime利用紅黑樹來進行存儲,選擇最小vruntime節點調度。

    數據包CD / DVD驅動程序執行相同的操作。

    高分辨率計時器代碼使用rbtree來組織未完成的計時器請求。

    ext3文件系統跟蹤紅黑樹中的目錄條目。

    虛擬內存結構管理(VMA).。

    多路復用技術的Epoll的核心結構也是紅黑樹+雙向鏈表。

    加密密鑰和網絡數據包均由紅黑樹跟蹤。

    4 Linux應用程序

    nginx用紅黑樹管理timer等。

    5 實際工作中也會用到紅黑樹

    1 我們做的是大流量網關,100G 流量,pps 實際是5000w pps 左右, 我們路由表項總共是5000w。

    2 當時采用數據結構是hash+list,路由規模還會不斷增大,但不能無腦增加hash桶,這個會增加內存,本身當時網關內存就不是很充裕,所以這里要把list換成紅黑樹。

    3 ?但之前list都是用RCU鎖(因為鏈表操作可以原子化(64位指針))實現多核并發訪問,但紅黑樹這種樹形結構要實現無鎖多核并發一直是比較困難的點,每次變更可能會產生多次位移(旋轉)操作,多個操作比較困實現原子化。

    4 ?最終想到一個比較好方法是 雙份指針,用空間換時間,紅黑樹維護兩份指針(骨架),當前使用的active指針,更新操作backup指針,等更新backup指針后,再原子交換根節點,這樣不妨礙其他核讀,然后再同步指針拓撲關系到備份指針。

    跳表(skip list)

    核心點:

    1 跳表本質上是對鏈表的一種優化,通過逐層跳步采樣的方式構建索引,以加快查找速度。使用概率均衡的思路,確定新插入節點的層數,使其滿足集合分布,在保證相似的查找效率簡化了插入實現。

    2 skiplist的復雜度和紅黑樹一樣,而且實現起來更簡單;

    3 在并發環境下skiplist有另外一個優勢,紅黑樹在插入和刪除的時候可能需要做一些rebalance的操作,這樣的操作可能會涉及到整個樹的其他部分,而skiplist的操作顯然更加局部性一些,鎖需要盯住的節點更少,因此在這樣的情況下性能好一些;

    使用場景

    1 HBase MemStore 的數據結構:HBase 屬于 LSM Tree 結構的數據庫,LSM Tree 結構的數據庫有個特點,實時寫入的數據先寫入到內存,內存達到閾值往磁盤 flush 的時候,會生成類似于 StoreFile 的有序文件,而跳表恰好就是天然有序的,所以在 flush 的時候效率很高。

    2 Google 開源的 key/value 存儲引擎 LevelDB 以及 Facebook 基于 LevelDB 優化的 RocksDB 都是 LSM Tree 結構的數據庫,他們內部的 MemTable 都是使用了跳表這種數據結構;

    3 ?redis的sorted set內部實現;

    B/B+樹(平衡多路查找樹)

    核心點:

    1 B樹和B+樹的出現是因為磁盤IO;眾所周知,IO操作的效率很低,那么,當在大量數據存儲中,查詢時我們不能一下子將所有數據加載到內存中,只能逐一加載磁盤頁,每個磁盤頁對應樹的節點。造成大量磁盤IO操作(最壞情況下為樹的高度)。平衡二叉樹由于樹深度過大而造成磁盤IO讀寫過于頻繁,進而導致效率低下。所以,我們為了減少磁盤IO的次數,就你必須降低樹的深度,將“瘦高”的樹變得“矮胖”。一個基本的想法就是:

  • 每個節點存儲多個元素

  • 摒棄二叉樹結構,采用多叉樹

  • 這樣就引出來了一個新的查找樹結構 ——多路查找樹(multi-way search tree)。一顆平衡多路查找樹自然可以使得數據的查找效率保證在O(logN)這樣的對數級別上。

    2 B-Tree是為磁盤等外存儲設備設計的一種平衡查找樹。系統從磁盤讀取數據到內存時是以磁盤塊(block)為基本單位的,位于同一個磁盤塊中的數據會被一次性讀取出來,B+Tree是在B-Tree基礎上 ? 的一種優化,使其更適合實現外存儲索引結構;

    3 B+Tree 只有葉子結點存儲數據,所有非葉子結點(內部結點)不存儲數據,只有指向子結點的指針。葉子結點均在同一層,且葉子結點之間類似于鏈表結構,即有指針指向下一個葉子結點;

    4 由于B+樹在內部節點上不包含數據信息,因此在內存頁中能夠存放更多的key。數據存放的更加緊密,具有更好的空間局部性。因此訪問葉子節點上關聯的數據也具有更好的緩存命中率

    5 B+樹的葉子結點都是相鏈的,因此對整棵樹的便利只需要一次線性遍歷葉子結點即可。而且由于數據順序排列并且相連,所以便于區間查找和搜索。而B樹則需要進行每一層的遞歸遍歷,相鄰的元素可能在內存中不相鄰,所以緩存命中性沒有B+樹好,B樹也有優點,其優點在于:由于B樹的每一個節點都包含key和value,因此經常訪問的元素可能離根節點更近,因此訪問也更迅速。

    使用場景

    MySQL InnoDB存儲引擎就是用B+Tree實現:

    • 每個級別的所有頁面都相互雙向鏈接,并且在每個頁面內,記錄按升序單獨鏈接。非葉頁包含“指針”(包含子頁碼)而不是非關鍵行數據。

    算法

    一些的重要算法,很多算法在工作中都經常使用;

    排序算法核心:

    核心點:

    • 穩定性得好處:從一個鍵上排序,然后再從另一個鍵上排序,第一個鍵排序的結果可以為第二個鍵排序所用,多重key值排序;

    • 大多數語言的標準庫排序算法是快速排序

    核心原理是通過選擇一個元素作為基點,然后通過與基點比較,根據比較結果進行分類(移動元素),再遞歸下去,直到不能遞歸為止,這樣整個數組就有序了;

    標準庫中的sort,是通過先快排,遞歸深度超過一個閥值就改成堆排,然后對最后的幾個進行插入排序來實現的;

    快速排序復雜度是nlogn,但實際綜合性能最好;

    原因:

    1. 快速排序中,每次數據移動都意味著該數據距離它正確的位置越來越近,而在其他同等級排序中,類似將堆尾部的數據移到堆頂這樣的操作只會使相應的數據遠離它正確的位置,后續必然有一些操作再將其移動,即“做了好多無用功”。

    2. 快速排序通常比其他排序算法快得多,因為它就地運行,無需創建任何輔助數組來保存臨時值。與歸并排序之類的東西相比,這可能是一個巨大的優勢,因為分配和取消分配輔助數組所需的時間可能很明顯。就地操作還提高了快速排序的局部性。?????????????????

    ? ? ? ? ? ?

    • 增量型排序(比如實時計算topN這種)采用是堆排序(最小堆或者最大堆);

    字符串匹配算法

    核心點:

    • 盡可能利用一切可以利用信息,比如模式串本身信息,后綴信息,比較后的殘余信息等;

    • 掌握正則表達式語法;

    • 理解模式匹配:KMP、Boyer-Moore算法;

    使用場景:

    1 ?linux文本處理三劍客 grep ,awk, sed 等用了大量正則表達式算法。

    2 文本編輯器使用大量字符串匹配算法。

    圖論

    核心點:

    • 實際工作中網絡會用到部分圖算法,比如網絡拓撲排序,OSPF路由協議(最短路徑);

    • 如果你要參加ACM or OJ 這種比賽,可以學一些常用圖算法:最短路徑、最小生成樹、網絡流建模;

    使用場景:

    1 游戲開發中會用到大量的圖算法:路徑搜索算法(BFS,DFS,A*);

    2 導航軟件會用到大量的圖算法:最短路徑,路徑搜索算法;

    3 網絡bridge的STP協議用到最小生成樹算法;

    4 網頁排名中PageRank 算法;

    搜索(遍歷)+剪枝

    核心點:

    • 核心是減少解空間,窮舉+排除法;

    • 核心是減少解空間,遞歸+判斷;

    使用場景:

    1 ?深度優先搜索、廣度優先搜索、A*算法、回溯算法、蒙特卡洛樹搜索;

    二分法

    核心點:

    • 前置條件,需要有序;

    • 全面考慮算法邊界點,實現細節,溢出等問題;

    • 不能在線增量計算;

    使用場景:

    1 用二分法計算方程近似解;

    2 機器學習二分分類算法;

    3?有序序列快速查找場景;

    分治算法

    核心點:

    • 一是自頂向下分解問題,二是自底向上抽象合并;

    • 將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之;?

    使用場景:

    1 二分搜索,排序算法(快速排序,歸并排序),動態規劃;

    2 傅立葉變換(快速傅立葉變換);

    3 程序模塊化設計;

    動態規劃(DP)

    ?

    核心點:

    • 實際工作中很少用到,工作多年,從來沒有在工作中使用過動態規劃。

    • 核心是了解其思想和原理:

  • 動態規劃最核心的思想,就在于拆分子問題,記住過往,減少重復計算;

  • 深刻理解最優子結構,重疊子問題,狀態轉移方程,無后效性,以及邊界條件;

  • 熟悉各種類型DP特點,普通DP,區間DP,樹形DP,數位DP,狀態壓縮DP等;

    • 應對面試,刷幾道題就行,一般面試很少出動態規劃的題,校招可能會出,社招基本上不會出;

    • 如果你要參加ACM or OJ 這種比賽,必須掌握, 這個區分菜鳥的分界點。

    使用場景:

    1 切割鋼條問題, Floyd最短路問題,最大不下降子序列,矩陣鏈乘,凸多邊形三角剖分,0-1背包,最長公共子序列,最優二分搜索樹;

    2 運籌學,經濟學等;

    最后總結

    程序 = 數據結構 + 算法?? ? ? ? ? ? ? ? ? ? ?

    ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ?---Niklaus EmilWirth

    程序本質是數據結構+算法,任何一門語言都可以這樣理解,這個公式對計算機科學的影響程度足以類似物理學中愛因斯坦的“E=MC^2”——一個公式展示出了程序的本質

    其實在工作中,最重要是設計好數據結構,因為在設計數據結構的時候,就是性能和實現難度的權衡,程序當然是越簡單越好,但為了性能,有時候不得不設計出像紅黑樹這種復雜數據結構。

    希望我們都可以掌握好算法核心思想,和常見數據結構精妙設計,幫助我們在面試和工作中打好堅實的基礎;

    擴展閱讀

    https://www.cnblogs.com/binarylei/p/12419863.html

    https://en.wikipedia.org/wiki/Quicksort

    https://mp.weixin.qq.com/s/7PZ6L1YzPZdiMNK25sUqjg

    https://blog.jcole.us/2013/01/10/btree-index-structures-in-innodb/

    https://www.drdobbs.com/parallel/choose-concurrency-friendly-data-structu/208801371

    https://cloud.tencent.com/developer/article/1136054

    Robert Sedgewick. Left-leaning Red–Black Trees

    https://cloud.tencent.com/developer/news/652039

    https://github.com/greyireland/algorithm-pattern

    https://www.huaweicloud.com/articles/1bce95370dbe6348fe3f277968cf078c.html

    - END -


    看完一鍵三連在看轉發,點贊

    是對文章最大的贊賞,極客重生感謝你

    推薦閱讀

    深入理解Kafka的設計思想

    深入理解RCU|核心原理

    TCP/IP協議精華指南pdf發布


    文末小彩蛋

    總結

    以上是生活随笔為你收集整理的深入理解数据结构和算法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。