摘要:每個(gè)列表中的數(shù)據(jù)項(xiàng)稱為元素。棧被稱為一種后入先出,的數(shù)據(jù)結(jié)構(gòu)。散列使用的數(shù)據(jù)結(jié)構(gòu)叫做散列表。不包含任何成員的集合稱為空集,全集則是包含一切可能成員的集合。因此二叉搜索樹需要平衡,即左右子樹高度要相近。
樓樓非計(jì)算機(jī)專業(yè),但是對(duì)計(jì)算機(jī)也還算喜歡。個(gè)人理解若有偏差,歡迎各位批評(píng)指正!
對(duì)于數(shù)據(jù)結(jié)構(gòu)和算法一直是我的薄弱環(huán)節(jié),相信大多數(shù)前端工程師可能多少會(huì)有些這方面的弱點(diǎn),加上數(shù)據(jù)結(jié)構(gòu)和算法本來就有些枯燥,立下個(gè)flag,三天過后拋之腦后的也時(shí)有發(fā)生,好了,收起老媽子的叨叨叨,畢竟樓樓還是個(gè)美少女,哈哈哈~
在JS中,我所知的稍微復(fù)雜點(diǎn)的數(shù)據(jù)結(jié)構(gòu)有數(shù)組和對(duì)象。
但是統(tǒng)觀大多數(shù)語言,就會(huì)發(fā)現(xiàn)自己知道的太少了,當(dāng)然以下涉及到的我們可能會(huì)用的很少。但是個(gè)人認(rèn)為這些是思想上的沉淀,所發(fā)生的的變化帶給自己的影響也將會(huì)是潛移默化的,就當(dāng)是潤物細(xì)無聲了,哈哈哈~
樓樓借鑒了數(shù)據(jù)結(jié)構(gòu)與算法JavaScript描述一書,在寫這篇帖子時(shí)~
==開始----------------------------------------------------------------------------------------------==
關(guān)于那些定義:一個(gè)存儲(chǔ)元素的線性集合(collection),元素可以通過索引來任意存取,索引通常是數(shù)字,用來計(jì)算元素之間存儲(chǔ)位置的偏移量。
es6新增 Array.from()//偽數(shù)組轉(zhuǎn)數(shù)組 不支持的話我們還可以通過call和apply改變this指向,從而達(dá)到偽數(shù)組調(diào)用數(shù)組的方法 Array.of() //將一組值,轉(zhuǎn)換為數(shù)組 Array.prototype.copyWithin(target, start = 0, end = this.length) //指定位置的成員復(fù)制到其他位置(會(huì)覆蓋原有成員),然后返回當(dāng)前數(shù)組。也就是說,使用這個(gè)方法,會(huì)修改當(dāng)前數(shù)組。 target(必需):從該位置開始替換數(shù)據(jù)。如果為負(fù)值,表示倒數(shù)。 start(可選):從該位置開始讀取數(shù)據(jù),默認(rèn)為 0。如果為負(fù)值,表示倒數(shù)。 end(可選):到該位置前停止讀取數(shù)據(jù),默認(rèn)等于數(shù)組長度。如果為負(fù)值,表示倒數(shù)。 Array.find(item => item > 0) 找到數(shù)組中符合條件的元素返回,如果沒有符合條件的元素返回undefine Array.findIndex(item => item > 0) 返回第一個(gè)符合條件的數(shù)組成員的位置,如果所有成員都不符合條件,則返回-1。 Array.fill() //使用一個(gè)值來填充數(shù)組 entries()【對(duì)鍵值】 keys()【對(duì)鍵】 values()【對(duì)值】 用于遍歷數(shù)組。他們都返回一個(gè)遍歷器對(duì)象。 Array.includes() 這個(gè)方法必須力推,返回布爾值,表示某個(gè)數(shù)組是否包含特定的值,與字符串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 只支持一維數(shù)組,但是通過在數(shù)組里保存數(shù)組元素的方式,可以輕松創(chuàng)建多維數(shù)組。
列表是一組有序的數(shù)據(jù)。每個(gè)列表中的數(shù)據(jù)項(xiàng)稱為元素。在 JavaScript 中,列表中的元素可以是任意數(shù)據(jù)類型。列表中可以保存多少元素并沒有事先限定,實(shí)際使用時(shí)元素的數(shù)量受到程序內(nèi)存的限制。列表有前有后(分別對(duì)應(yīng) front 和 end)。
棧是一種特殊的列表,棧內(nèi)的元素只能通過列表的一端訪問,這一端稱為棧頂。棧被稱為一種后入先出(LIFO,last-in-first-out)的數(shù)據(jù)結(jié)構(gòu)。入棧使用 push() 方法,出棧使用 pop() 方法。
隊(duì)列是一種先進(jìn)先出(First-In-First-Out,F(xiàn)IFO)的數(shù)據(jù)結(jié)構(gòu)。插入操作也叫做入隊(duì),刪除操作也叫做出隊(duì)。入隊(duì)操作在隊(duì)尾插入新元素,出隊(duì)操作刪除隊(duì)頭的元素。
==背景:在很多編程語言中,數(shù)組的長度是固定的,所以當(dāng)數(shù)組已被數(shù)據(jù)填滿時(shí),再要加入新的元素就會(huì)非常困難。在數(shù)組中,添加和刪除元素也很麻煩,因?yàn)樾枰獙?shù)組中的其他元素向前或向后平移,以反映數(shù)組剛剛進(jìn)行了添加或刪除操作。然而JavaScript 的數(shù)組并不存在上述問題,因?yàn)槭褂?split() 方法不需要再訪問數(shù)組中的其他元素了。==
鏈表是由一組節(jié)點(diǎn)組成的集合。每個(gè)節(jié)點(diǎn)都使用一個(gè)對(duì)象的引用指向它的后繼。指向另一個(gè)節(jié)點(diǎn)的引用叫做鏈。
我們常說的鏈表是單向鏈表
雙向鏈表示意圖:
循環(huán)鏈表示意圖
通過這三個(gè)圖片希望你對(duì)鏈表有初步認(rèn)知。
字典是一種以鍵 - 值對(duì)形式存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),一般大家談到字典會(huì)說到電話簿,我覺得在JS里他更像是Object類,一個(gè)鍵對(duì)應(yīng)一個(gè)值。但是很多教材中會(huì)說,Dictionay 類的基礎(chǔ)是 Array 類,而不是 Object 類。OK,That"s OK! 畢竟JavaScript中萬物皆對(duì)象。
散列是一種常用的數(shù)據(jù)存儲(chǔ)技術(shù),散列后的數(shù)據(jù)可以快速地插入或取用。散列使用的數(shù)據(jù)結(jié)構(gòu)叫做散列表。在散列表上插入刪除和取用數(shù)據(jù)都非常快,但是對(duì)于查找操作來說卻效率低下,比如查找一組數(shù)據(jù)中的最大值和最小值。這些操作得求助于其他數(shù)據(jù)結(jié)構(gòu),二叉查找樹就是一個(gè)很好的選擇。
即使使用一個(gè)高效的散列函數(shù),仍然存在將兩個(gè)鍵映射成同一個(gè)值的可能,這種現(xiàn)象稱為碰撞(collision)
==hashTable的實(shí)現(xiàn)就是典型的基于散列的一種數(shù)據(jù)結(jié)構(gòu),在這里有興趣的話還可以去看一下霍納算法==
當(dāng)散列函數(shù)對(duì)于多個(gè)輸入產(chǎn)生同樣的輸出時(shí),就產(chǎn)生了碰撞。
碰撞的解決方法:開鏈法和線性探測法
開鏈法是指實(shí)現(xiàn)散列表的底層數(shù)組中,每個(gè)數(shù)組元素又是一個(gè)新的數(shù)據(jù)結(jié)構(gòu),比如另一個(gè)數(shù)組,這樣就能存儲(chǔ)多個(gè)鍵了。使用這種技術(shù),即使兩個(gè)鍵散列后的值相同,依然被保存在同樣的位置,只不過它們在第二個(gè)數(shù)組中的位置不一樣罷了。
線性探測法隸屬于一種更一般化的散列技術(shù):開放尋址散列。當(dāng)發(fā)生碰撞時(shí),線性探測法檢查散列表中的下一個(gè)位置是否為空。如果為空,就將數(shù)據(jù)存入該位置;如果不為空,則繼續(xù)檢查下一個(gè)位置,直到找到一個(gè)空的位置為止。該技術(shù)是基于這樣一個(gè)事實(shí):每個(gè)散列表都會(huì)有很多空的單元格,可以使用它們來存儲(chǔ)數(shù)據(jù)。
集合是由一組無序但彼此之間又有一定相關(guān)性的成員構(gòu)成的,每個(gè)成員在集合中只能出現(xiàn)一次。
? 不包含任何成員的集合稱為空集,全集則是包含一切可能成員的集合。
? 如果兩個(gè)集合的成員完全相同,則稱兩個(gè)集合相等。
? 如果一個(gè)集合中所有的成員都屬于另外一個(gè)集合,則前一集合稱為后一集合的子集。
? 并集
將兩個(gè)集合中的成員進(jìn)行合并,得到一個(gè)新集合。
? 交集
兩個(gè)集合中共同存在的成員組成一個(gè)新的集合。
? 補(bǔ)集
屬于一個(gè)集合而不屬于另一個(gè)集合的成員組成的
樹是一種非線性的數(shù)據(jù)結(jié)構(gòu),以分層的方式來存儲(chǔ)數(shù)據(jù)。
樹是一種非線性的數(shù)據(jù)結(jié)構(gòu),以分層的方式來存儲(chǔ)數(shù)據(jù)。
其中樹里面常被提起的應(yīng)當(dāng)是二叉樹。提起二叉樹補(bǔ)充一些,這是我一個(gè)朋友寫的,感覺寫的比較好。拿出來分享一下~
表達(dá)順序集比較合適的數(shù)據(jù)結(jié)構(gòu)樹。。。樹最合適。為什么?
二叉搜索樹天然可用于排序的二分查找,左子樹小于根節(jié)點(diǎn),右子樹大于根節(jié)點(diǎn),樹的高度即為最大搜索次數(shù),是很小的常數(shù)。 二叉搜索樹 改進(jìn)為 二叉平衡搜索樹 二叉搜索樹有什么劣勢?樹的構(gòu)建受數(shù)據(jù)集合的順序影響,極端情況下,蛻化為單項(xiàng)鏈表,失去二叉樹的意義,檢索復(fù)雜度退化到順序遍歷。 因此二叉搜索樹需要平衡,即左右子樹高度要相近。 二叉平衡搜索樹 改進(jìn)為 B樹 搜索復(fù)雜度為 log2 (n),要想進(jìn)一步降低搜索次數(shù)即樹高度,怎么辦?增大對(duì)數(shù)的底,底越大,對(duì)數(shù)值越小。 因此改進(jìn)為 m 階樹,并對(duì)非根節(jié)點(diǎn)的key個(gè)數(shù)進(jìn)行約定(m/2 ~ m),成為B樹。 B樹 改進(jìn)為 B+樹 B樹的劣勢:B樹每個(gè)節(jié)點(diǎn)包含數(shù)據(jù)記錄本身或指針,內(nèi)存空間占用大,反復(fù)換頁導(dǎo)致訪存低效;典型業(yè)務(wù)場景查詢的都是一段范圍的數(shù)據(jù)記錄,不僅僅是單條,B樹比較慢。 改進(jìn)措施:樹的非葉子節(jié)點(diǎn)不包含數(shù)據(jù)記錄,葉子節(jié)點(diǎn)包含數(shù)據(jù)記錄的指針(聚集索引的key),整體減小索引樹占用的內(nèi)存,提高訪存效率;所有數(shù)據(jù)記錄被葉子節(jié)點(diǎn)覆蓋,葉子節(jié)點(diǎn)天然是有序的,以單項(xiàng)鏈表連接,很方便遍歷一段范圍的記錄。 改進(jìn)后即為 B+ 樹。mariadb-10.3使用的即為B+樹。 B+樹 改進(jìn)為 B*樹 B+樹的劣勢:每個(gè)非葉子節(jié)點(diǎn)可能只包含 m/2 個(gè)key,有一半空閑,內(nèi)存使用率低。 改進(jìn)措施:將非葉子節(jié)點(diǎn)的最小key數(shù)增加為 2m/3,提高內(nèi)存使用率。付出的代價(jià)是需要對(duì)非葉子節(jié)點(diǎn)增加指向兄弟的指針,以便于節(jié)點(diǎn)拆分、合并。 改進(jìn)后即為 B* 樹。 基于B+樹的一些推論 select * from xxx offset N limit M,不用特別在意N對(duì)效率的影響。如果N可能很大,例如過萬,區(qū)分維護(hù)冷、熱數(shù)據(jù),確保N不會(huì)太大。 select * from xxx order by a order by b,聯(lián)合索引受索引樹的影響,天然要求左匹配原則,能利用到聯(lián)合索引時(shí)查找效率很高。 主鍵用 uuid 還是 int 更好?innobase數(shù)據(jù)引擎下單調(diào)增長的 int 更好。uuid 32字節(jié),用于索引必然比 int 4字節(jié)大,索引樹占用的內(nèi)存越大訪存效率越低,所以 uuid 差;innobase的文件物理存儲(chǔ)結(jié)構(gòu)內(nèi)涵為主鍵索引(聚集索引),單調(diào)遞增的主鍵確保在連續(xù)的disk page 上不斷 append 數(shù)據(jù),訪存效率高,而uuid導(dǎo)致新增數(shù)據(jù)隨機(jī)插入disk page,需要大量移動(dòng)數(shù)據(jù),訪存效率低??傮w上看uuid較差。當(dāng)然id本身也存在生成時(shí)的鎖競爭等問題。
對(duì)于樹結(jié)構(gòu)有興趣的可以再深入探討,因?yàn)檫@塊確實(shí)水比較深
圖由邊的集合及頂點(diǎn)的集合組成。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/107335.html
摘要:基于時(shí)間的動(dòng)畫算法其實(shí)思路和實(shí)現(xiàn)都很簡單。而基于時(shí)間的動(dòng)畫算法要注意邊緣時(shí)間的損失,最好采取積累時(shí)間,然后分固定片更新動(dòng)畫的方式。 作者:戴嘉華 轉(zhuǎn)載請注明出處,保留原文鏈接和作者信息 目錄 前言 基于幀的動(dòng)畫算法(Frame-based) 基于時(shí)間的動(dòng)畫算法(Time-based) 改良基于時(shí)間的動(dòng)畫算法 總結(jié) 前言 前段時(shí)間無聊或有聊地做了幾個(gè)移動(dòng)端的HTML5游戲。...
摘要:這是因?yàn)槲覀冊L問了數(shù)組中不存在的數(shù)組元素它超過了最后一個(gè)實(shí)際分配到內(nèi)存的數(shù)組元素字節(jié),并且有可能會(huì)讀取或者覆寫的位。包含個(gè)元素的新數(shù)組由和數(shù)組元素所組成中的內(nèi)存使用中使用分配的內(nèi)存主要指的是內(nèi)存讀寫。 原文請查閱這里,本文有進(jìn)行刪減,文后增了些經(jīng)驗(yàn)總結(jié)。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第三章。 我們將會(huì)討論日常使用中另一個(gè)被開發(fā)...
摘要:大多數(shù)情況下,對(duì)一個(gè)直接量和一個(gè)局部變量數(shù)據(jù)訪問的性能差異是微不足道的。 前端性能優(yōu)化之 JavaScript 前言 本文為 《高性能 JavaScript》 讀書筆記,是利用中午休息時(shí)間、下班時(shí)間以及周末整理出來的,此書雖有點(diǎn)老舊,但談?wù)摰男阅軆?yōu)化話題是每位同學(xué)必須理解和掌握的,業(yè)務(wù)響應(yīng)速度直接影響用戶體驗(yàn)。 一、加載和運(yùn)行 大多數(shù)瀏覽器使用單進(jìn)程處理 UI 更新和 JavaScri...
閱讀 1855·2021-11-11 16:55
閱讀 2654·2021-08-27 13:11
閱讀 3692·2019-08-30 15:53
閱讀 2361·2019-08-30 15:44
閱讀 1478·2019-08-30 11:20
閱讀 1100·2019-08-30 10:55
閱讀 990·2019-08-29 18:40
閱讀 3111·2019-08-29 16:13