導論:首先,沿着二分查找的思路,我們構造一種二叉樹來查找,這種二叉樹的左子樹結點都小於根節點,右子樹節點都大於根節點,這樣一來,所有結點算是都排好序了,接下來就可以查找
基於二叉排序樹的查找
一.二叉排序樹的定義
所謂二叉排序樹是一個什么樣的東西,我們得弄清楚,以下是二叉排序樹的定義:
1.若它的左子樹非空,則左子樹上所有節點的值都小於根節點的值
2.若它的右子樹非空,則右子樹上所有結點的值都大於根節點的值
3.它的左子樹和右子樹也是一顆二叉排序樹
有了定義,很多東西就都會顯而易見了:
1.二叉排序樹並不是一顆完全二叉樹
2.和二叉判定樹的對比:二叉判定樹是一種特殊的二叉排序樹,二叉判定樹多了一個限定條件:左右子樹的節點數目相差最多不能超過1個(小雨或等於1)
3.二叉排序樹又名二叉查找樹
好了,到這里給出二叉排序樹的定義
typedef struct _TreeNode { struct _TreeNode *leftNode; struct _TreeNode *rightNode; TypeData data; }TreeNode,*TreeRoot;
二.二叉排序樹的插入
和堆的建立和維護類似,我們首先想解決的一個問題就是:已經有了一顆二叉排序樹,怎樣做到將一個值插入正確的位置,
給出二叉樹的插入定義
TreeNode* Insert_Tree(TreeRoot &root,TypeData key) { if (!root) { TreeNode *node=new TreeNode; node->data=key; node->leftNode=nullptr; node->rightNode=nullptr; root=node; return root; } else if (root->data==key) { return root; } else if (root->data<key) { return (Insert_Tree(root->rightNode,key)); } else if (root->data>key) { return(Insert_Tree(root->leftNode,key)); } }
這里是用遞歸實現的二叉排序樹的插入,要注意以下幾點:
遞歸開始返回的終結點有兩個:
1.當根節點為null時
2.根節點的data值和key相等,這個時候就不需要插入了
插入完畢返回插入位置的結點
三.二叉排序樹的建立
所謂二叉排序樹的建立,也就是通過向一個空節點不斷地插入結點來建立一顆二叉排序樹,通過遞歸地插入,可得
void Create_Tree(TreeRoot& root) { TypeData key; while (std::cin>>key) { Insert_Tree(root,key); } }
四.通過二叉排序樹進行查找
這里,有兩種方式,遞歸和非遞歸的
首先是遞歸的
TreeNode *find_InTree(TreeRoot root,TypeData key) { if (root) { if (root->data==key) { return root; } else if (root->data>key) { return find_InTree(root->leftNode,key); } else { return find_InTree(root->rightNode,key); } } return nullptr; }
然后是非遞歸的,用while循環代替遞歸達到遞歸的作用
TreeNode *find_InTree2(TreeRoot root,TypeData key) { TreeNode* p=root; while (p) { if (p->data==key) { return p; break; } else if (p->data>key) { p=p->leftNode; } else { p=p->rightNode; } } return nullptr; }
最后,簡單地分析一下查找的時間復雜度吧!
二叉排序樹的插入過程:很明顯,二叉排序樹過程最好情況是O(log2(n)),最差情況是O(n),最差的情況時:二叉樹變為一顆只有左子樹或者只有右子樹的二叉樹,整個插入過程也退化成為順序插入
二叉排序樹的創建過程:很明顯,假設有n個數,建立二叉排序樹就要while循環n次插入過程,也就是說創建過程為O(nlog2(n))~O(n²)之間
二叉排序樹的查找過程:很明顯,基於二叉排序樹的查找過程和二叉排序樹的插入過程類似,時間復雜度也為O(log2(n))到O(n)之間
最后,程序執行過程使這樣的:
排序二叉樹的創建過程;
排序二叉樹的查找過程;
這樣看來,整個過程的時間復雜度為O(nlog2(n)到O(n²))之間,但是實際上表述的時候我們通常忽略創建過程,只考慮二叉樹的查找過程,這樣看來的話,整個過程的時間復雜度為O(log2(n))到O(n)之間