數據結構與算法JavaScript (不定時更新)

樓樓非計算機專業,可是對計算機也還算喜歡。我的理解如有誤差,歡迎各位批評指正!前端

對於數據結構和算法一直是個人薄弱環節,相信大多數前端工程師可能多少會有些這方面的弱點,加上數據結構和算法原本就有些枯燥,立下個flag,三天事後拋之腦後的也時有發生,好了,收起老媽子的叨叨叨,畢竟樓樓仍是個美少女,哈哈哈~es6

在JS中,我所知的稍微複雜點的數據結構有數組和對象。算法

可是統觀大多數語言,就會發現本身知道的太少了,固然如下涉及到的咱們可能會用的不多。可是我的認爲這些是思想上的沉澱,所發生的的變化帶給本身的影響也將會是潛移默化的,就當是潤物細無聲了,哈哈哈~編程

樓樓借鑑了數據結構與算法JavaScript描述一書,在寫這篇帖子時~數組

==開始----------------------------------------------------------------------------------------------==前端工程師

關於那些定義:

數組:

一個存儲元素的線性集合(collection),元素能夠經過索引來任意存取,索引一般是數字,用來計算元素之間存儲位置的偏移量。數據結構

數組的那些方法(js)
es6新增
Array.from()//僞數組轉數組  不支持的話咱們還能夠經過call和apply改變this指向,從而達到僞數組調用數組的方法
Array.of() //將一組值,轉換爲數組
Array.prototype.copyWithin(target, start = 0, end = this.length) //指定位置的成員複製到其餘位置(會覆蓋原有成員),而後返回當前數組。也就是說,使用這個方法,會修改當前數組。
    target(必需):從該位置開始替換數據。若是爲負值,表示倒數。
    start(可選):從該位置開始讀取數據,默認爲 0。若是爲負值,表示倒數。
    end(可選):到該位置前中止讀取數據,默認等於數組長度。若是爲負值,表示倒數。
Array.find(item => item > 0) 找到數組中符合條件的元素返回,若是沒有符合條件的元素返回undefine
Array.findIndex(item => item > 0) 返回第一個符合條件的數組成員的位置,若是全部成員都不符合條件,則返回-1。
Array.fill() //使用一個值來填充數組
entries()【對鍵值】 keys()【對鍵】 values()【對值】 用於遍歷數組。他們都返回一個遍歷器對象。
Array.includes() 這個方法必須力推,返回布爾值,表示某個數組是否包含特定的值,與字符串includes方法相似
    
另外還有這些,就不一一贅述了
join()  push()和pop() shift() 和 unshift() sort()  reverse()  concat()  slice()
splice()  indexOf()和 lastIndexOf() (ES5新增) forEach() (ES5新增)  map() (ES5新增)
filter() (ES5新增)  every() (ES5新增)  some() (ES5新增) reduce()和 reduceRight() (ES5新增)
數組中較爲複雜的應爲二維和多維數組。
JavaScript 只支持一維數組,可是經過在數組裏保存數組元素的方式,能夠輕鬆建立多維數組。
列表

列表是一組有序的數據。每一個列表中的數據項稱爲元素。在 JavaScript 中,列表中的元素能夠是任意數據類型。列表中能夠保存多少元素並無事先限定,實際使用時元素的數量受到程序內存的限制。列表有前有後(分別對應 front 和 end)。app

棧是一種特殊的列表,棧內的元素只能經過列表的一端訪問,這一端稱爲棧頂。棧被稱爲一種後入先出(LIFO,last-in-first-out)的數據結構。入棧使用 push() 方法,出棧使用 pop() 方法。數據結構和算法

隊列

隊列是一種先進先出(First-In-First-Out,FIFO)的數據結構。插入操做也叫作入隊,刪除操做也叫作出隊。入隊操做在隊尾插入新元素,出隊操做刪除隊頭的元素。編程語言

鏈表

==背景:在不少編程語言中,數組的長度是固定的,因此當數組已被數據填滿時,再要加入新的元素就會很是困難。在數組中,添加和刪除元素也很麻煩,由於須要將數組中的其餘元素向前或向後平移,以反映數組剛剛進行了添加或刪除操做。然而JavaScript 的數組並不存在上述問題,由於使用 split() 方法不須要再訪問數組中的其餘元素了。==
鏈表是由一組節點組成的集合。每一個節點都使用一個對象的引用指向它的後繼。指向另外一個節點的引用叫作鏈。

咱們常說的鏈表是單向鏈表
圖片描述

雙向鏈表示意圖:
圖片描述

循環鏈表示意圖
圖片描述

經過這三個圖片但願你對鏈表有初步認知。

字典

字典是一種以鍵 - 值對形式存儲數據的數據結構,通常你們談到字典會說到電話簿,我以爲在JS裏他更像是Object類,一個鍵對應一個值。可是不少教材中會說,Dictionay 類的基礎是 Array 類,而不是 Object 類。OK,That's OK! 畢竟JavaScript中萬物皆對象。

散列

散列是一種經常使用的數據存儲技術,散列後的數據能夠快速地插入或取用。散列使用的數據結構叫作散列表。在散列表上插入刪除和取用數據都很是快,可是對於查找操做來講卻效率低下,好比查找一組數據中的最大值和最小值。這些操做得求助於其餘數據結構,二叉查找樹就是一個很好的選擇。

即便使用一個高效的散列函數,仍然存在將兩個鍵映射成同一個值的可能,這種現象稱爲碰撞(collision)

==hashTable的實現就是典型的基於散列的一種數據結構,在這裏有興趣的話還能夠去看一下霍納算法==

當散列函數對於多個輸入產生一樣的輸出時,就產生了碰撞。

碰撞的解決方法:開鏈法和線性探測法

開鏈法是指實現散列表的底層數組中,每一個數組元素又是一個新的數據結構,好比另外一個數組,這樣就能存儲多個鍵了。使用這種技術,即便兩個鍵散列後的值相同,依然被保存在一樣的位置,只不過它們在第二個數組中的位置不同罷了。

線性探測法隸屬於一種更通常化的散列技術:開放尋址散列。當發生碰撞時,線性探測法檢查散列表中的下一個位置是否爲空。若是爲空,就將數據存入該位置;若是不爲空,則繼續檢查下一個位置,直到找到一個空的位置爲止。該技術是基於這樣一個事實:每一個散列表都會有不少空的單元格,可使用它們來存儲數據。

集合

集合是由一組無序但彼此之間又有必定相關性的成員構成的,每一個成員在集合中只能出現一次。

• 不包含任何成員的集合稱爲空集,全集則是包含一切可能成員的集合。
• 若是兩個集合的成員徹底相同,則稱兩個集合相等。
• 若是一個集合中全部的成員都屬於另一個集合,則前一集合稱爲後一集合的子集。

對集合的基本操做有下面幾種。

• 並集
將兩個集合中的成員進行合併,獲得一個新集合。
• 交集
兩個集合中共同存在的成員組成一個新的集合。
• 補集
屬於一個集合而不屬於另外一個集合的成員組成的

樹:

樹是一種非線性的數據結構,以分層的方式來存儲數據。

樹:

樹是一種非線性的數據結構,以分層的方式來存儲數據。
其中樹裏面常被提起的應當是二叉樹。提起二叉樹補充一些,這是我一個朋友寫的,感受寫的比較好。拿出來分享一下~
表達順序集比較合適的數據結構樹。。。樹最合適。爲何?

二叉搜索樹自然可用於排序的二分查找,左子樹小於根節點,右子樹大於根節點,樹的高度即爲最大搜索次數,是很小的常數。
    二叉搜索樹 改進爲 二叉平衡搜索樹
    二叉搜索樹有什麼劣勢?樹的構建受數據集合的順序影響,極端狀況下,蛻化爲單項鍊表,失去二叉樹的意義,檢索複雜度退化到順序遍歷。
    所以二叉搜索樹須要平衡,即左右子樹高度要相近。
二叉平衡搜索樹 改進爲 B樹
    搜索複雜度爲 log2 (n),要想進一步下降搜索次數即樹高度,怎麼辦?增大對數的底,底越大,對數值越小。
    所以改進爲 m 階樹,並對非根節點的key個數進行約定(m/2 ~ m),成爲B樹。
B樹 改進爲 B+樹
    B樹的劣勢:B樹每一個節點包含數據記錄自己或指針,內存空間佔用大,反覆換頁致使訪存低效;典型業務場景查詢的都是一段範圍的數據記錄,不只僅是單條,B樹比較慢。
    改進措施:樹的非葉子節點不包含數據記錄,葉子節點包含數據記錄的指針(彙集索引的key),總體減少索引樹佔用的內存,提升訪存效率;全部數據記錄被葉子節點覆蓋,葉子節點自然是有序的,以單項鍊錶鏈接,很方便遍歷一段範圍的記錄。
改進後即爲 B+ 樹。mariadb-10.3使用的即爲B+樹。
B+樹 改進爲 B*樹
    B+樹的劣勢:每一個非葉子節點可能只包含 m/2 個key,有一半空閒,內存使用率低。
    改進措施:將非葉子節點的最小key數增長爲 2m/3,提升內存使用率。付出的代價是須要對非葉子節點增長指向兄弟的指針,以便於節點拆分、合併。
    改進後即爲 B* 樹。
基於B+樹的一些推論
select * from xxx offset N limit M,不用特別在乎N對效率的影響。若是N可能很大,例如過萬,區分維護冷、熱數據,確保N不會太大。
select * from xxx order by a order by b,聯合索引受索引樹的影響,自然要求左匹配原則,能利用到聯合索引時查找效率很高。
主鍵用 uuid 仍是 int 更好?innobase數據引擎下單調增加的 int 更好。uuid 32字節,用於索引必然比 int 4字節大,索引樹佔用的內存越大訪存效率越低,因此 uuid 差;innobase的文件物理存儲結構內涵爲主鍵索引(彙集索引),單調遞增的主鍵確保在連續的disk page 上不斷 append 數據,訪存效率高,而uuid致使新增數據隨機插入disk page,須要大量移動數據,訪存效率低。整體上看uuid較差。固然id自己也存在生成時的鎖競爭等問題。

對於樹結構有興趣的能夠再深刻探討,由於這塊確實水比較深

圖和圖算法

圖由邊的集合及頂點的集合組成。

相關文章
相關標籤/搜索