導航:首頁 > 源碼編譯 > btree演算法

btree演算法

發布時間:2022-10-30 19:11:13

A. MySQL索引的Index method中btree和hash的區別

當分片索引不是純整型的字元串時,只接受整型的內置 hash 演算法是無法使用的。為此,stringhash 按照用戶定義的起點和終點去截取分片索引欄位中的部分字元,根據當中每個字元的二進制 unicode 值換算出一個長整型數值,然後就直接調用內置 hash 演算法求解分片路由:先求模得到邏輯分片號,再根據邏輯分片號直接映射到物理分片。


B. 二叉樹遍歷演示

四、 遍歷二叉樹 二叉樹是一種非線性的數據結構,在對它進行操作時,總是需要逐一對每個數據元素實施 操作,這樣就存在一個操作順序問題,由此提出了二叉樹的遍歷操作。所謂遍歷二叉樹就 是按某種順序訪問二叉樹中的每個結點一次且僅一次的過程。這里的訪問可以是輸出、比 較、更新、查看元素內容等等各種操作。
二叉樹的遍歷方式分為兩大類:一類按根、左子樹和右子樹三個部分進行訪問;另一類按 層次訪問。下面我們將分別進行討論。
1、 按根、左子樹和右子樹三部分進行遍歷 遍歷二叉樹的順序存在下面6種可能: TLR(根左右), TRL(根右左) LTR(左根右), RTL(右根左) LRT(左右根), RLT(右左根) 其中,TRL、RTL和RLT三種順序在左右子樹之間均是先右子樹後左子樹,這與人們先左後右的習慣不同,因此,往往不予採用。餘下的三種順序TLR、LTR和LRT根據根訪問的位置不同分別被稱為先序遍歷、中序遍歷和後序遍歷。(1)先序遍歷若二叉樹為空,則結束遍歷操作;否則訪問根結點;先序遍歷左子樹;先序遍歷右子樹。(2)中序遍歷若二叉樹為空,則結束遍歷操作;否則中序遍歷左子樹;訪問根結點;中序遍歷右子樹。(3)後序遍歷若二叉樹為空,則結束遍歷操作;否則後序遍歷左子樹;後序遍歷右子樹;訪問根結點。例如。以下是一棵二叉樹及其經過三種遍歷所得到的相應遍歷序列二叉樹的兩種遍歷方法:(1)對一棵二叉樹中序遍歷時,若我們將二叉樹嚴格地按左子樹的所有結點位於根結點的左側,右子樹的所有結點位於根右側的形式繪制,就可以對每個結點做一條垂線,映射到下面的水平線上,由此得到的順序就是該二叉樹的中序遍歷序列
(2)任何一棵二叉樹都可以將它的外部輪廓用一條線繪制出來,我們將它稱為二叉樹的包線,這條包線對於理解二叉樹的遍歷過程很有用。 由此可以看出:(1)遍歷操作實際上是將非線性結構線性化的過程,其結果為線性序列,並根據採用的遍歷順序分別稱為先序序列、中序序列或後序序列;(2)遍歷操作是一個遞歸的過程,因此,這三種遍歷操作的演算法可以用遞歸函數實現。(1)先序遍歷遞歸演算法
void PreOrder(BTree BT) {
if (BT) { Visit(BT);
PreOrder(BT->Lchild);
PreOrder(BT->Rchild);
}(2)中序遍歷遞歸演算法
void InOrder(BTree BT) {
if (BT) {
InOrder(BT->Lchild);
Visit(BT);
InOrder(BT->Rchild);
}
}(3)後序遍歷遞歸演算法
void PostOrder(BTree BT) {
if (BT) {
PostOrder(BT->Lchild);
PostOrder(BT->Rchild);
Visit(BT);
}
} 2 、按層次遍歷二叉樹 實現方法為從上層到下層,每層中從左側到右側依次訪問每個結點。下面我們將給出一棵二叉樹及其按層次順序訪問其中每個結點的遍歷序列。
void LevelOreder(QBTree BT) {
for (i=1;i<=BT.n;i++)
if (BT.elem[i]!='#') Visite(BT.elem[i]);
}二叉樹用鏈式存儲結構表示時,按層遍歷的演算法實現訪問過程描述如下:訪問根結點,並將該結點記錄下來;若記錄的所有結點都已處理完畢,則結束遍歷操作;否則重復下列操作。取出記錄中第一個還沒有訪問孩子的結點,若它有左孩子,則訪問左孩子,並將記錄下來;若它有右孩子,則訪問右孩子,並記錄下來。 在這個演算法中,應使用一個隊列結構完成這項操作。所謂記錄訪問結點就是入隊操作; 而取出記錄的結點就是出隊操作。這樣一來,我們的演算法就可以描述成下列形式:(1)訪問根結點,並將根結點入隊;(2)當隊列不空時,重復下列操作:從隊列退出一個結點;若其有左孩子,則訪問左孩子,並將其左孩子入隊;若其有右孩子,則訪問右孩子,並將其右孩子入隊;void LevelOrder(BTree *BT) {
if (!BT) exit;
InitQueue(Q); p=BT; //初始化
Visite(p); EnQueue(&Q,p); //訪問根結點,並將根結點入隊
while (!QueueEmpty(Q)) { //當隊非空時重復執行下列操作
DeQueue(&Q,&p); //出隊
if (!p->Lchild) {Visite(p->Lchild);EnQueue(&Q,p->Lchild); //處理左孩子<br> if (!p->Rchild) {Visite(p->Rchild);EnQueue(&Q,p->Rchild); //處理右孩子<br> }
}
五、典型二叉樹的操作演算法 1、 輸入一個二叉樹的先序序列,構造這棵二叉樹 為了保證唯一地構造出所希望的二叉樹,在鍵入這棵樹的先序序列時,需要在所有空二叉 樹的位置上填補一個特殊的字元,比如,'#'。在演算法中,需要對每個輸入的字元進行判 斷,如果對應的字元是'#',則在相應的位置上構造一棵空二叉樹;否則,創建一個新結 點。整個演算法結構以先序遍歷遞歸演算法為基礎,二叉樹中結點之間的指針連接是通過指針 參數在遞歸調用返回時完成。演算法:BTree Pre_Create_BT( ) {
getch(ch);
if (ch=='#') return NULL; //構造空樹
else { BT=(BTree)malloc(sizeof(BTLinklist)); //構造新結點
BT->data=ch;
BT->lchild =Pre_Create_BT( ); //構造左子樹
BT->rchild =Pre_Create_BT( ); //構造右子樹
return BT;
}
} 2、 計算一棵二叉樹的葉子結點數目 這個操作可以使用三種遍歷順序中的任何一種,只是需要將訪問操作變成判斷該結點是否 為葉子結點,如果是葉子結點將累加器加1即可。下面這個演算法是利用中序遍歷實現的。演算法:void Leaf(BTree BT,int *count) {
if (BT) {
Leaf(BT->child,&count); //計算左子樹的葉子結點個數
if (BT->lchild==NULL&&BT->rchild==NULL) (*count)++;
Leaf(BT->rchild,&count); //計算右子樹的葉子結點個數
}
} 3、 交換二叉樹的左右子樹 許多操作可以利用三種遍歷順序的任何一種,只是某種遍歷順序實現起來更加方便一 些。而有些操作則不然,它只能使用其中的一種或兩種遍歷順序。將二叉樹中所有結點的左右子樹進行交換這個操作就屬於這類情況。演算法:void change_left_right(BTree BT) {
if (BT) {
change_left_right(BT->lchild);
change_left_right(BT->rchild);
BT->lchild<->BT->rchild;
}
} 4 、求二叉樹的高度 這個操作使用後序遍歷比較符合人們求解二叉樹高度的思維方式。首先分別求出左右子樹 的高度,在此基礎上得出該棵樹的高度,即左右子樹較大的高度值加1。演算法:int hight(BTree BT) { //h1和h2分別是以BT為根的左右子樹的高度
if (BT==NULL) return 0;
else {
h1=hight(BT->lchild);
h2=hight(BT->right);
return max{h1,h2}+1;
}
} 六、樹、森林與二叉樹的轉換 1、 樹、森林轉換成二叉樹 將一棵樹轉換成二叉樹的方法: 將一棵樹轉換成二叉樹實際上就是將這棵樹用孩子兄弟表示法存儲即可,此時,樹中的每個結點最多有兩個指針:一個指針指向第一個孩子,另一個指針指向右側第一個兄弟。當你將這兩個指針看作是二叉樹中的左孩子指針和孩子右指針時,就是一棵二叉樹了。 特點:一棵樹轉換成二叉樹後,根結點沒有右孩子。 將森林轉換成二叉樹的方法與一棵樹轉換成二叉樹的方法類似,只是把森林中所有樹的根 結點看作兄弟關系,並對其中的每棵樹依依地進行轉換。 2 、二叉樹還原成樹或森林 這個過程實際上是樹、森林轉換成二叉樹的逆過程,即將該二叉樹看作是樹或森林的孩子兄弟表示法。比如,若二叉樹為空,樹也為空;否則,由二叉樹的根結點開始,延右指針向下走,直到為空,途經的結點個數是相應森林所含樹的棵數;若某個結點的左指針非空,說明這個結點在樹中必有孩子,並且從二叉樹中該結點左指針所指結點開始,延右指針向下走,直到為空,途經的結點個數就是這個結點的孩子數目。
第 3 節 哈夫曼樹及其應用 1、哈夫曼樹的定義及特點
在二叉樹中,一個結點到另一個結點之間的分支構成這兩個結點之間的路徑。這三棵二叉樹的帶權路徑長度分別為:WPL1=10*2+11*2+3*3+6*3+7*3+9*3=117WPL2=3*1+6*2+7*3+9*4+10*5+11*5=177WPL3=9*1+7*2+6*3+3*4+10*5+11*5=158哈夫曼樹的一個重要特點是:沒有度為1的結點。
2、構造哈夫曼樹的過程:
(1)將給定的n個權值{w1,w2,...,wn}作為n個根結點的權值構造一個具有n棵二叉樹的森林{T1,T2,...,Tn},其中每棵二叉樹只有一個根結點;(2)在森林中選取兩棵根結點權值最小的二叉樹作為左右子樹構造一棵新二叉樹,新二叉樹的根結點權值為這兩棵樹根的權值之和;(3)在森林中,將上面選擇的這兩棵根權值最小的二叉樹從森林中刪除,並將剛剛新構造的二叉樹加入到森林中;(4)重復上面(2)和(3),直到森林中只有一棵二叉樹為止。這棵二叉樹就是哈夫曼樹。 例如: 假設有一組權值{5,29,7,8,14,23,3,11},下面我們將利用這組權值演示構造哈夫曼樹的過程。
它的帶權的路徑長度為:WPL=(23+29)*2+(11+14)*3+(3+5+7+8)*4=2713.判定樹 在很多問題的處理過程中,需要進行大量的條件判斷,這些判斷結構的設計直接影響著 程序的執行效率。例如,編制一個程序,將百分制轉換成五個等級輸出。大家可能認為 這個程序很簡單,並且很快就可以用下列形式編寫出來:if (socre<60) printf("bad");
else if (socre<70) printf("pass");
else if (score<80) printf("general");
else if (score<90) printf("good");
esle printf("very good"); 在實際應用中,往往各個分數段的分布並不是均勻的。下面就是在一次考試中某門課程的各分數段的分布情況:

4.前綴編碼 在電文傳輸中,需要將電文中出現的每個字元進行二進制編碼。在設計編碼時需要遵守兩 個原則:(1)發送方傳輸的二進制編碼,到接收方解碼後必須具有唯一性,即解碼結果與發送方發送的電文完全一樣;(2)發送的二進制編碼盡可能地短。下面我們介紹兩種編碼的方式。
(1)等長編碼 這種編碼方式的特點是每個字元的編碼長度相同(編碼長度就是每個編碼所含的二進制位 數)。假設字元集只含有4個字元A,B,C,D,用二進制兩位表示的編碼分別為00,01,10,11。若現在有一段電文為:ABACCDA,則應發送二進制序列:00010010101100,總長度為14位。當接收方接收到這段電文後,將按兩位一段進行解碼。這種編碼的特點是解碼簡單且具有唯一性,但編碼長度並不是最短的。(2)不等長編碼 在傳送電文時,為了使其二進制位數盡可能地少,可以將每個字元的編碼設計為不等長的,使用頻度較高的字元分配一個相對比較短的編碼,使用頻度較低的字元分配一個比較長的編碼。例如,可以為A,B,C,D四個字元分別分配0,00,1,01,並可將上述電文用二進制序列:000011010發送,其長度只有9個二進制位,但隨之帶來了一個問題,接收方接到這段電文後無法進行解碼,因為無法斷定前面4個0是4個A,1個B、2個A,還是2個B,即解碼不唯一,因此這種編碼方法不可使用。(1)利用字元集中每個字元的使用頻率作為權值構造一個哈夫曼樹;(2)從根結點開始,為到每個葉子結點路徑上的左分支賦予0,右分支賦予1,並從根到葉子方向形成該葉子結點的編碼。假設有一個電文字元集中有8個字元,每個字元的使用頻率分別為{0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11},現以此為例設計哈夫曼編碼。
哈夫曼編碼設計過程為:
(1)為方便計算,將所有字元的頻度乘以100,使其轉換成整型數值集合,得到{5,29,7,8,14,23,3,11};
(2)以此集合中的數值作為葉子結點的權值構造一棵哈夫曼樹,如圖5-27所示;
(3)由此哈夫曼樹生成哈夫曼編碼,如圖5-28所示。
最後得出每個字元的編碼為:比如,發送一段編碼:0000011011010010, 接收方可以准確地通過解碼得到:⑥⑥⑦⑤②⑧。

C. mysql 索引中的USING BTREE 是什麼意思

b-tree 是mysql 索引默認使用的數據結構,
自動建表語句會出現
UNIQUEKEY uq_network_domain USING BTREE (network_id,network_name,network_domain)
手動時不用理會
[CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]
[index_name] [index_type] (index_col_name,...)
[index_option] ...
當然你也可可以寫上
index_type:
USING {BTREE | HASH}
當然你如果不明白什麼是B-Tree花還是google 一下吧

D. 如何寫索引,讓查詢速度快

首先來看看錶是否有索引的命令
show index from 表名;
看到主鍵索引,索引類型是BTREE(二叉樹)
正是因為這個二叉樹演算法,讓查詢速度快很多,二叉樹的原理,就是取最中間的一個數,然後把大於這個數的往右邊排,小於這個數的就向左排,每次減半,然後依次類推,每次減半,形成一個樹狀結構圖
例如上面的例子,我們不使用索引的話,需要查詢11次才把編號為4的數據取出,如果加上索引,我們只需要4次就可以取出。

如大家所知道的,MySQL目前主要有以下幾種索引類型:FULLTEXT,HASH,BTREE,RTREE。
那麼,這幾種索引有什麼功能和性能上的不同呢?
FULLTEXT
即為全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不過目前只有 CHAR、VARCHAR ,TEXT 列上可以創建全文索引。值得一提的是,在數據量較大時候,現將數據放入一個沒有全局索引的表中,然後再用CREATE INDEX創建FULLTEXT索引,要比先為一張表建立FULLTEXT然後再將數據寫入的速度快很多。
全文索引並不是和MyISAM一起誕生的,它的出現是為了解決WHERE name LIKE 「%word%"這類針對文本的模糊查詢效率較低的問題。在沒有全文索引之前,這樣一個查詢語句是要進行遍歷數據表操作的,可見,在數據量較大時是極其的耗時的,如果沒有非同步IO處理,進程將被挾持,很浪費時間,當然這里不對非同步IO作進一步講解,想了解的童鞋,自行谷哥。
全文索引的使用方法並不復雜:
創建ALTER TABLE table ADD INDEX `FULLINDEX` USING FULLTEXT(`cname1`[,cname2…]);
使用SELECT * FROM table WHERE MATCH(cname1[,cname2…]) AGAINST ('word' MODE );
其中, MODE為搜尋方式(IN BOOLEAN MODE ,IN NATURAL LANGUAGE MODE ,IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION / WITH QUERY EXPANSION)。
關於這三種搜尋方式,愚安在這里也不多做交代,簡單地說,就是,布爾模式,允許word里含一些特殊字元用於標記一些具體的要求,如+表示一定要有,-表示一定沒有,*表示通用匹配符,是不是想起了正則,類似吧;自然語言模式,就是簡單的單詞匹配;含表達式的自然語言模式,就是先用自然語言模式處理,對返回的結果,再進行表達式匹配。
對搜索引擎稍微有點了解的同學,肯定知道分詞這個概念,FULLTEXT索引也是按照分詞原理建立索引的。西文中,大部分為字母文字,分詞可以很方便的按照空格進行分割。但很明顯,中文不能按照這種方式進行分詞。那又怎麼辦呢?這個向大家介紹一個Mysql的中文分詞插件Mysqlcft,有了它,就可以對中文進行分詞,想了解的同學請移步Mysqlcft,當然還有其他的分詞插件可以使用。
HASH
Hash這個詞,可以說,自打我們開始碼的那一天起,就開始不停地見到和使用到了。其實,hash就是一種(key=>value)形式的鍵值對,如數學中的函數映射,允許多個key對應相同的value,但不允許一個key對應多個value。正是由於這個特性,hash很適合做索引,為某一列或幾列建立hash索引,就會利用這一列或幾列的值通過一定的演算法計算出一個hash值,對應一行或幾行數據(這里在概念上和函數映射有區別,不要混淆)。在Java語言中,每個類都有自己的hashcode()方法,沒有顯示定義的都繼承自object類,該方法使得每一個對象都是唯一的,在進行對象間equal比較,和序列化傳輸中起到了很重要的作用。hash的生成方法有很多種,足可以保證hash碼的唯一性,例如在MongoDB中,每一個document都有系統為其生成的唯一的objectID(包含時間戳,主機散列值,進程PID,和自增ID)也是一種hash的表現。額,我好像扯遠了-_-!
由於hash索引可以一次定位,不需要像樹形索引那樣逐層查找,因此具有極高的效率。那為什麼還需要其他的樹形索引呢?
在這里愚安就不自己總結了。引用下園子里其他大神的文章:來自 14的路 的MySQL的btree索引和hash索引的區別
(1)Hash 索引僅僅能滿足"=","IN"和"<=>"查詢,不能使用范圍查詢。
由於 Hash 索引比較的是進行 Hash 運算之後的 Hash 值,所以它只能用於等值的過濾,不能用於基於范圍的過濾,因為經過相應的 Hash 演算法處理之後的 Hash 值的大小關系,並不能保證和Hash運算前完全一樣。
(2)Hash 索引無法被用來避免數據的排序操作。
由於 Hash 索引中存放的是經過 Hash 計算之後的 Hash 值,而且Hash值的大小關系並不一定和 Hash 運算前的鍵值完全一樣,所以資料庫無法利用索引的數據來避免任何排序運算;
(3)Hash 索引不能利用部分索引鍵查詢。
對於組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合並後再一起計算 Hash 值,而不是單獨計算 Hash 值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也無法被利用。
(4)Hash 索引在任何時候都不能避免表掃描。
前面已經知道,Hash 索引是將索引鍵通過 Hash 運算之後,將 Hash運算結果的 Hash 值和所對應的行指針信息存放於一個 Hash 表中,由於不同索引鍵存在相同 Hash 值,所以即使取滿足某個 Hash 鍵值的數據的記錄條數,也無法從 Hash 索引中直接完成查詢,還是要通過訪問表中的實際數據進行相應的比較,並得到相應的結果。
(5)Hash 索引遇到大量Hash值相等的情況後性能並不一定就會比B-Tree索引高。
對於選擇性比較低的索引鍵,如果創建 Hash 索引,那麼將會存在大量記錄指針信息存於同一個 Hash 值相關聯。這樣要定位某一條記錄時就會非常麻煩,會浪費多次表數據的訪問,而造成整體性能低下。

愚安我稍作補充,講一下HASH索引的過程,順便解釋下上面的第4,5條:
當我們為某一列或某幾列建立hash索引時(目前就只有MEMORY引擎顯式地支持這種索引),會在硬碟上生成類似如下的文件:
hash值 存儲地址
1db54bc745a1 77#45b5
4bca452157d4 76#4556,77#45cc…

hash值即為通過特定演算法由指定列數據計算出來,磁碟地址即為所在數據行存儲在硬碟上的地址(也有可能是其他存儲地址,其實MEMORY會將hash表導入內存)。
這樣,當我們進行WHERE age = 18 時,會將18通過相同的演算法計算出一個hash值==>在hash表中找到對應的儲存地址==>根據存儲地址取得數據。
所以,每次查詢時都要遍歷hash表,直到找到對應的hash值,如(4),數據量大了之後,hash表也會變得龐大起來,性能下降,遍歷耗時增加,如(5)。
BTREE
BTREE索引就是一種將索引值按一定的演算法,存入一個樹形的數據結構中,相信學過數據結構的童鞋都對當初學習二叉樹這種數據結構的經歷記憶猶新,反正愚安我當時為了軟考可是被這玩意兒好好地折騰了一番,不過那次考試好像沒怎麼考這個。如二叉樹一樣,每次查詢都是從樹的入口root開始,依次遍歷node,獲取leaf。
BTREE在MyISAM里的形式和Innodb稍有不同
在 Innodb里,有兩種形態:一是primary key形態,其leaf node里存放的是數據,而且不僅存放了索引鍵的數據,還存放了其他欄位的數據。二是secondary index,其leaf node和普通的BTREE差不多,只是還存放了指向主鍵的信息.
而在MyISAM里,主鍵和其他的並沒有太大區別。不過和Innodb不太一樣的地方是在MyISAM里,leaf node里存放的不是主鍵的信息,而是指向數據文件里的對應數據行的信息.
RTREE
RTREE在mysql很少使用,僅支持geometry數據類型,支持該類型的存儲引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種。
相對於BTREE,RTREE的優勢在於范圍查找.
各種索引的使用情況
(1)對於BTREE這種Mysql默認的索引類型,具有普遍的適用性
(2)由於FULLTEXT對中文支持不是很好,在沒有插件的情況下,最好不要使用。其實,一些小的博客應用,只需要在數據採集時,為其建立關鍵字列表,通過關鍵字索引,也是一個不錯的方法,至少愚安我是經常這么做的。
(3)對於一些搜索引擎級別的應用來說,FULLTEXT同樣不是一個好的處理方法,Mysql的全文索引建立的文件還是比較大的,而且效率不是很高,即便是使用了中文分詞插件,對中文分詞支持也只是一般。真要碰到這種問題,Apache的Lucene或許是你的選擇。
(4)正是因為hash表在處理較小數據量時具有無可比擬的素的優勢,所以hash索引很適合做緩存(內存資料庫)。如mysql資料庫的內存版本Memsql,使用量很廣泛的緩存工具Mencached,NoSql資料庫redis等,都使用了hash索引這種形式。當然,不想學習這些東西的話Mysql的MEMORY引擎也是可以滿足這種需求的。

閱讀全文

與btree演算法相關的資料

熱點內容
mdr軟體解壓和別人不一樣 瀏覽:884
單片機串列通信有什麼好處 瀏覽:320
游戲開發程序員書籍 瀏覽:843
pdf中圖片修改 瀏覽:269
匯編編譯後 瀏覽:474
php和java整合 瀏覽:829
js中執行php代碼 瀏覽:440
國產單片機廠商 瀏覽:57
蘋果手機怎麼設置不更新app軟體 瀏覽:284
轉行當程序員如何 瀏覽:493
蘋果id怎麼驗證app 瀏覽:864
查看手機命令 瀏覽:953
抖音反編譯地址 瀏覽:226
如何加密軟體oppoa5 瀏覽:233
java從入門到精通明日科技 瀏覽:96
拆解汽車解壓視頻 瀏覽:598
新版百度雲解壓縮 瀏覽:593
android上下拉刷新 瀏覽:880
centos可執行文件反編譯 瀏覽:839
林清玄pdf 瀏覽:271