從MySQL開始聊聊「樹」結構 (上)

image.png

前言

嗨嘍,你們好,我是CrazyCodes, 近一年寫的文章,都是一些廣度方面的思考,新的一年,在技術深度上也須要有更多的探索,感謝各位的持續支持!算法

MySQL

image.png

先聊聊你們熟知的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`;

對數據進行查詢
image.png
看到這裏,你可能說了,這是在講什麼,增刪改查都是常識,有什麼好講的,那咱們如今就正式進入正題,首先從插入記錄開始提及,MySQL會使用B+樹來存儲數據記錄,B+樹是B樹的延伸,而B樹又是平衡二叉樹的延伸,除了平衡二叉樹還有二叉查找樹,依次基於其概念延伸的排序,大概是以下這樣設計

B+樹 -> B樹 -> 平衡二叉樹 -> 二叉查找樹 -> 二叉樹 -> 樹

固然也不只僅是全部跟樹有關的數據結構,這裏爲了提升學習樹這種數據結構的興趣,因此以MySQL講起,糾其根源,再結合MySQL的數據記錄將這一串知識連接起來,那咱們把這個順序倒過來依次講起3d

樹 -> 二叉樹 -> 二叉查找樹 -> 平衡二叉樹 -> B樹 -> B+樹

我儘可能不把這些數據結構講成教科書的樣子。code

樹🌲

image.png
你要不知道樹是什麼玩意,就別繼續看下去了😂,就是大街上咱們看到的樹,大街的樹也就是咱們常識認知的樹,是經過「樹根」、「樹枝」和「樹葉」組成,缺同樣,這樹也不是一顆完整的樹。blog

那麼數據結構中的樹指的什麼,你能夠把手機或者電腦倒過來看上圖,數據結構中的樹,就是一個倒過來的樹,並非他非要倒過來才能說,而是根據人類正常的視覺與思惟,就例如你看書總不能從最後一頁的最後一個字開始從後往前讀把,倒過來只是便於理解和閱讀它罷了。

在數據結構中倒過來的樹大概是張下面這個樣子

倒樹
image.png

正樹
image.png

正樹、倒樹,都貼出來了,你能夠嘗試對比這兩張圖,看看那張圖更容易理解,接下來的案例只會以倒樹展現。

樹是其餘樹型數據結構的基礎,這裏你必需要熟記一些基本概念

  • 樹根,樹的根節點
  • 子節點,樹枝1、2、三是樹根的子節點
  • 兄弟節點,樹枝1、2、三互爲兄弟節點
  • 父節點,樹根是樹枝一的父節點,樹枝一是樹枝1-1的父節點

相信根據上圖多看幾遍,這很容易理解

那咱們生搬硬套,把MySQL的數據放到這個最簡單的樹中
image.png
這是我隨意擺放的,固然你想怎麼擺就怎麼擺,例如
image.png
這看起來像跟棍,或者
image.png
不管怎樣,咱們建立了一個樹,那根據SQL語句

SELECT * FROM `user`;

咱們須要查到根節點,這很簡單,而後去判斷根節點的左子節點是否有值,有的話取出來,右子節點也是同樣的道理,這就是所謂的樹的遍歷。那麼咱們如今在SQL上加些條件

SELECT * FROM `user` WHERE `id` = 1;

image.png

那這個條件,在樹結構中如何查呢,到這裏,你會發現一個問題

不管條件是什麼,咱們都須要遍歷整棵樹,遍歷樹的深度,徹底取決於要查詢的數據所在的位置,位置靠前,就少遍歷些,位置靠後就多遍歷下。

這裏講一個更基礎的知識,時間複雜度,時間複雜度用於表示某個算法所計算的時間長度,那咱們根據上面這個例子,能夠分析出其平均時間複雜度爲 O(n) , 固然最好的狀況是 O(1) , 這種狀況就是根節點就是咱們要找的數據。

數據的不斷增長,才使得咱們沒法繼續使用最原始的數據結構,哎,都是數據逼得呀。

假設咱們不只僅有3條記錄,而是在3000萬條查找Join,恰巧仍是第3000萬條,那麼若是使用最基本的樹結構去查詢的話,那麼咱們將要進行3000萬去查詢才能夠得到最終結果。是否是感受不切實際了?

其實這樣的話,是否是樹結構都不重要了,他能夠是一個數組、鏈表或者隊列等等,能夠用任意數據結構去存儲,固然每種數據結構的出現都有其存在的緣由。那麼咱們使用原始樹的結構感受不靠譜,那麼跟隨個人文字來到二叉樹的世界!

二叉樹

image.png

二叉樹,顧名思義是隻有兩個叉的樹,每一個節點只有兩個叉,這是它的特性,這時候你就疑問了,爲啥不能是三叉樹,四叉樹,N叉樹呢?固然能夠有,那麼咱們舉一個例子,咱們再往user表內插幾行數據

INSERT INTO `user` VALUES(4,"Jorr");
INSERT INTO `user` VALUES(5,"Queie");
INSERT INTO `user` VALUES(6,"Kioa");

如今咱們庫裏有6條記錄
image.png
咱們拿三叉樹舉例
image.png
我把每一個節點須要查詢的次數列個表,這裏我使用前序遍歷樹的方式,讓你簡單的清楚樹有幾叉意味着什麼

tips :樹有三種遍歷方式,分別爲 前序、中序、後序 ,根據具體需求使用不一樣的遍歷方式
節點 次數
1,join 1
3,jeein 2
5,queie 3
6,kioa 4
2,tom 5
4,jorr 6

若是是二叉樹呢?
image.png

節點 次數
1,join 1
3,jeein 2
5,queie 3
6,kioa 4
2,tom 5
4,jorr 6

有沒有很奇怪?不管幾叉,查詢4,jorr數據都須要6次,感受用哪一個都同樣是不?並非這樣,你能夠這樣考慮一個問題,在使用程序去遍歷這兩棵樹時,二叉樹須要判斷左右子節點,而三叉樹則須要判斷左中右三個節點,他們所在的內存空間不一樣,專業點說,他們的空間複雜度不一樣。

解答了你的一點點小疑惑後,咱們回到正題,仍是聊聊二叉樹的事。

二叉樹分爲徹底二叉樹和不徹底二叉樹

  • 徹底二叉樹表明每一個節點都有2個樹枝(就是不缺胳膊少腿)
  • 不徹底二叉樹反之就是(缺胳膊少腿),某個樹叉上可能只有左子樹,沒有右子樹

上述展現了MySQL的數據生搬硬套放到二叉樹中玩法,但你發現沒?咱們依舊沒法避免樹被所有遍歷的問題。

思考

我將在下一篇文章講述剩餘的「幾顆樹」,這裏我給你留一道思考題。

問題一:樹和二叉樹(N叉樹)都沒法避免遍歷整棵樹,那下一篇要講的平衡二叉樹爲何能夠作到只須要遍歷「半棵樹」?

問題二:時間複雜度的表示方式 O(1) O(n) O(log2^n) 分別表明什麼?

致謝

感謝你看到這裏,2021 我會在思否發佈本身電商設計的錄播課,也是我首個錄播課。

但願本篇文章能夠幫助到你,謝謝。

相關文章
相關標籤/搜索