嗨嘍,你們好,我是CrazyCodes, 近一年寫的文章,都是一些廣度方面的思考,新的一年,在技術深度上也須要有更多的探索,感謝各位的持續支持!算法
先聊聊你們熟知的MySQL,咱們使用MySQL確定是有數據存儲的需求。數據庫
咱們從基礎開始看,首先咱們建立一張用戶表數組
CREATE TABLE `user` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
這是一張簡單的用戶表,包含id和name兩個字段,id爲主鍵自增,name上沒有索引。想必你們對索引都有必定的認識,索引是一種數據結構,即本篇的核心議題「樹」結構,索引能夠達到快速命中某條記錄,「快速」一詞表明着在時間和空間相結合的最優解,固然也並不表明索引越多,數據表設計越合理,要根據實際業務去選擇。數據結構
咱們隨機向表中插入幾條記錄學習
INSERT INTO `user` VALUES(1,"Join"); INSERT INTO `user` VALUES(2,"Tom"); INSERT INTO `user` VALUES(3,"Jeein");
按照預期,數據庫內出現三條對應的記錄,這裏我使用語句spa
SELECT * FROM `user`;
對數據進行查詢
看到這裏,你可能說了,這是在講什麼,增刪改查都是常識,有什麼好講的,那咱們如今就正式進入正題,首先從插入記錄開始提及,MySQL會使用B+樹來存儲數據記錄,B+樹是B樹的延伸,而B樹又是平衡二叉樹的延伸,除了平衡二叉樹還有二叉查找樹,依次基於其概念延伸的排序,大概是以下這樣設計
B+樹 -> B樹 -> 平衡二叉樹 -> 二叉查找樹 -> 二叉樹 -> 樹
固然也不只僅是全部跟樹有關的數據結構,這裏爲了提升學習樹這種數據結構的興趣,因此以MySQL講起,糾其根源,再結合MySQL的數據記錄將這一串知識連接起來,那咱們把這個順序倒過來依次講起3d
樹 -> 二叉樹 -> 二叉查找樹 -> 平衡二叉樹 -> B樹 -> B+樹
我儘可能不把這些數據結構講成教科書的樣子。code
你要不知道樹是什麼玩意,就別繼續看下去了😂,就是大街上咱們看到的樹,大街的樹也就是咱們常識認知的樹,是經過「樹根」、「樹枝」和「樹葉」組成,缺同樣,這樹也不是一顆完整的樹。blog
那麼數據結構中的樹指的什麼,你能夠把手機或者電腦倒過來看上圖,數據結構中的樹,就是一個倒過來的樹,並非他非要倒過來才能說,而是根據人類正常的視覺與思惟,就例如你看書總不能從最後一頁的最後一個字開始從後往前讀把,倒過來只是便於理解和閱讀它罷了。
在數據結構中倒過來的樹大概是張下面這個樣子
倒樹
正樹
正樹、倒樹,都貼出來了,你能夠嘗試對比這兩張圖,看看那張圖更容易理解,接下來的案例只會以倒樹展現。
樹是其餘樹型數據結構的基礎,這裏你必需要熟記一些基本概念
相信根據上圖多看幾遍,這很容易理解
那咱們生搬硬套,把MySQL的數據放到這個最簡單的樹中
這是我隨意擺放的,固然你想怎麼擺就怎麼擺,例如
這看起來像跟棍,或者
不管怎樣,咱們建立了一個樹,那根據SQL語句
SELECT * FROM `user`;
咱們須要查到根節點,這很簡單,而後去判斷根節點的左子節點是否有值,有的話取出來,右子節點也是同樣的道理,這就是所謂的樹的遍歷。那麼咱們如今在SQL上加些條件
SELECT * FROM `user` WHERE `id` = 1;
那這個條件,在樹結構中如何查呢,到這裏,你會發現一個問題
不管條件是什麼,咱們都須要遍歷整棵樹,遍歷樹的深度,徹底取決於要查詢的數據所在的位置,位置靠前,就少遍歷些,位置靠後就多遍歷下。
這裏講一個更基礎的知識,時間複雜度,時間複雜度用於表示某個算法所計算的時間長度,那咱們根據上面這個例子,能夠分析出其平均時間複雜度爲 O(n) , 固然最好的狀況是 O(1) , 這種狀況就是根節點就是咱們要找的數據。
數據的不斷增長,才使得咱們沒法繼續使用最原始的數據結構,哎,都是數據逼得呀。
假設咱們不只僅有3條記錄,而是在3000萬條查找Join,恰巧仍是第3000萬條,那麼若是使用最基本的樹結構去查詢的話,那麼咱們將要進行3000萬去查詢才能夠得到最終結果。是否是感受不切實際了?
其實這樣的話,是否是樹結構都不重要了,他能夠是一個數組、鏈表或者隊列等等,能夠用任意數據結構去存儲,固然每種數據結構的出現都有其存在的緣由。那麼咱們使用原始樹的結構感受不靠譜,那麼跟隨個人文字來到二叉樹的世界!
二叉樹,顧名思義是隻有兩個叉的樹,每一個節點只有兩個叉,這是它的特性,這時候你就疑問了,爲啥不能是三叉樹,四叉樹,N叉樹呢?固然能夠有,那麼咱們舉一個例子,咱們再往user表內插幾行數據
INSERT INTO `user` VALUES(4,"Jorr"); INSERT INTO `user` VALUES(5,"Queie"); INSERT INTO `user` VALUES(6,"Kioa");
如今咱們庫裏有6條記錄
咱們拿三叉樹舉例
我把每一個節點須要查詢的次數列個表,這裏我使用前序遍歷樹的方式,讓你簡單的清楚樹有幾叉意味着什麼
tips :樹有三種遍歷方式,分別爲 前序、中序、後序 ,根據具體需求使用不一樣的遍歷方式
節點 | 次數 |
---|---|
1,join | 1 |
3,jeein | 2 |
5,queie | 3 |
6,kioa | 4 |
2,tom | 5 |
4,jorr | 6 |
若是是二叉樹呢?
節點 | 次數 |
---|---|
1,join | 1 |
3,jeein | 2 |
5,queie | 3 |
6,kioa | 4 |
2,tom | 5 |
4,jorr | 6 |
有沒有很奇怪?不管幾叉,查詢4,jorr數據都須要6次,感受用哪一個都同樣是不?並非這樣,你能夠這樣考慮一個問題,在使用程序去遍歷這兩棵樹時,二叉樹須要判斷左右子節點,而三叉樹則須要判斷左中右三個節點,他們所在的內存空間不一樣,專業點說,他們的空間複雜度不一樣。
解答了你的一點點小疑惑後,咱們回到正題,仍是聊聊二叉樹的事。
二叉樹分爲徹底二叉樹和不徹底二叉樹
上述展現了MySQL的數據生搬硬套放到二叉樹中玩法,但你發現沒?咱們依舊沒法避免樹被所有遍歷的問題。
我將在下一篇文章講述剩餘的「幾顆樹」,這裏我給你留一道思考題。
問題一:樹和二叉樹(N叉樹)都沒法避免遍歷整棵樹,那下一篇要講的平衡二叉樹爲何能夠作到只須要遍歷「半棵樹」?
問題二:時間複雜度的表示方式 O(1) O(n) O(log2^n) 分別表明什麼?
感謝你看到這裏,2021 我會在思否發佈本身電商設計的錄播課,也是我首個錄播課。
但願本篇文章能夠幫助到你,謝謝。