二叉樹的用途之一二叉搜尋樹
在學習資料結構的時候,也曾經學習過二叉樹,以及前序排列、中序排列、後序排列等等,但是一直無緣使用它!
二叉樹可以幹什麼?
排序有快速排序,歸併排序,查詢有二分法,甚至直接遍歷查詢,二叉樹的使用很少。
實際場景使用上,用的最多的是二叉平衡樹,有種特殊的二叉平衡樹就是紅黑樹,Java集合中的TreeSet和TreeMap,C++STL中的set,map以及LInux虛擬記憶體的管理,都是通過紅黑樹去實現的,還有哈弗曼樹編碼方面的應用,以及B-Tree,B+-Tree在檔案系統中的應用。當然二叉查詢樹可以用來查詢和排序。
二叉樹的分類
滿二叉樹:從高到低,除了葉節點外,所以節點左右節點都存在。
完全二叉樹:比滿二叉樹少幾個葉節點,從左向右放子節點。
平衡二叉樹:空樹或者它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹也都是平衡樹。
二叉搜尋樹:空樹或者二叉樹的所有節點比他的左子節點大,比他的右子節點小。
紅黑樹:不僅是具有二叉搜尋樹的屬性,還具有平衡樹的屬性,有序且子樹差不超過1,顏色規則:根節點和特殊節點(即葉節點下面兩個虛無的節點和未填寫的節點)是黑的,紅節點的左右子節點是黑的,最重要的是對於每個節點,從該節點到子孫葉節點的所有路徑包含相同數目的黑節點。
二叉樹在搜尋上的優勢
陣列的搜尋比較方便,可以直接使用下標,但刪除或者插入就比較麻煩了,而連結串列與之相反,刪除和插入都比較簡單,但是查詢很慢,這自然也與這兩種資料結構的儲存方式有關,陣列是取一段相連的空間,而連結串列是每建立一個節點便取一個節點所需的空間,只是使用指標進行連線,空間上並不是連續的。而二叉樹就既有連結串列的好處,又有陣列的優點。
今天就學習一下最簡單的二叉排序樹
1.定義:
二叉排序樹又叫二叉查詢樹或者二叉搜尋樹,它首先是一個二叉樹,而且必須滿足下面的條件:
1)若左子樹不空,則左子樹上所有結點的值均小於它的根節點的值;
2)若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值
3)左、右子樹也分別為二叉排序樹
2.二叉樹的遍歷:
在網上找到的一個遍歷示意圖:
圖1 遍歷示意圖
前序遍歷(根-左-右):ABDGHECKFIJ
中序遍歷(左-根-右):GDHBEAKCIJF
後序便利(左-右-根):GHDEBKJIFCA
結合定義可以知道,二叉搜尋樹的資料大小關係為:G<D<H<B<E<A<K<C<I<J<F,即中序遍歷
小結:從建立好的二叉搜尋樹,我們可以直接使用中序遍歷得到排序。
3.二叉樹的程式碼實現:
有了思路,程式碼實現的方式很多,以下就是很經典的一種實現,多多思考把握吧。
#include <iostream>
using namespace std;
/*BST的結點*/
typedef struct node
{
int key;
struct node *lChild, *rChild;
}Node, *BST;
/*在給定的BST中插入結點,其資料域為element, 使之稱為新的BST*/
bool BSTInsert(BST &p, int element)
{
if(NULL == p) // 空樹
{
p = new Node;
p->key = element;
p->lChild = p->rChild = NULL;
return true;
}
// if(element == p->key) // BST中不能有相等的值,不註釋掉會遮蔽掉相同的樹
// return false;
if(element < p->key) // 遞迴
return BSTInsert(p->lChild, element);
else
return BSTInsert(p->rChild, element);
}
/*先序遍歷*/
void preOrderTraverse(BST T)
{
if(T)
{
cout << T->key << " ";
preOrderTraverse(T->lChild);
preOrderTraverse(T->rChild);
}
}
/*中序遍歷*/
void inOrderTraverse(BST T)
{
if(T)
{
inOrderTraverse(T->lChild);
cout << T->key << " ";
inOrderTraverse(T->rChild);
}
}
/*後序遍歷*/
void postOrderTraverse(BST T)
{
if(T)
{
inOrderTraverse(T->lChild);
inOrderTraverse(T->rChild);
cout << T->key << " ";
}
}
int main()
{
int a[13] = {4, 5, 2, 1, 0, 9, 3, 7, 6, 8,5,4,7};
int n = 13;
BST T;
T = NULL;
int i;
for(i = 0; i < n; i++)
{
BSTInsert(T, a[i]);
}
inOrderTraverse(T);
cout << endl;
return 0;
}