二分搜索树

Posted tom-shushu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分搜索树相关的知识,希望对你有一定的参考价值。

1.二分搜索树特点:
每个节点的键值大于左孩子; 每个节点的键值小于右孩子;以左右孩子为根的子树仍为二分搜索树 ;不是完全二叉树
2.优势:
高效,不仅可以查找数据;还可以高效的插入,删除数据-动态维护数据
3.二分搜索树的局限性:
  1.二分搜索树的排列不同,对应的时间复杂度不同:最差可以退化为链表的形式O(n)
  2.改造二叉树(防止其变成链表):平衡二叉树(如:红黑树,2-3树,AVLL 树,Splay树)
  3.其他树形问题(递归):
    归并排序
    快速排序
    搜索问题(搜索树,8皇后)
    数独…
4.其他树:
KD树,区间树,哈夫曼树…
5.时间复杂度:

  查找元素 插入元素 删除元素
普通数组 O(n) O(n) O(n)
顺序数组 O(logn) O(n) O(n)
二分搜索树 O(logn) O(logn) O(logn)

遍历:时间复杂度O(n)
删除:时间复杂度O(logn)
二分搜索树实现代码:

  1 #include <iostream>
  2 #include <queue>
  3 #include <cassert>
  4 using namespace std;
  5 
  6 template<typename Key ,typename Value>
  7 class BST{
  8 private:
  9         struct Node{
 10             Key key;
 11             Value  value;
 12             Node *left;
 13             Node *right;
 14             Node(Key key,Value value){
 15                 this->key = key;
 16                 this->value = value;
 17                 this->left = this->right = NULL;
 18             }
 19             Node(Node *node){
 20                 this->key = node->key;
 21                 this->value = node->value;
 22                 this->left = node->left;
 23                 this->right = node->right; 
 24             }
 25         };
 26     Node *root;
 27     int count;
 28 public:
 29         BST(){
 30             root = NULL;
 31             count = 0;
 32         }
 33         ~BST(){
 34             destroy(root); 
 35         }
 36         int size(){
 37             return count;
 38         }
 39         bool isEmpty(){
 40             return count == 0;
 41         }
 42         void insert(Key key,Value value){
 43             root =  insert(root,key,value) ;
 44         }
 45         bool contain(Key key){
 46             return contain(root,key);
 47         } 
 48         Value* search(Key key){
 49             return search(root,key);
 50         }
 51         //前序遍历
 52         void preOrder(){
 53             preOrder(root);
 54         } 
 55         //中序遍历
 56         void inOrder(){
 57             inOrder(root);
 58         } 
 59         //后序遍历
 60         void postOrder(){
 61             postOrder(root);
 62         } 
 63         //层序遍历
 64         void levelOrder(){
 65             queue<Node*> q;
 66             q.push(root);
 67             while( !q.empty()){
 68                 Node *node = q.front();
 69                 q.pop();
 70                 cout<<node->key<<endl;
 71                 if(node->left)
 72                     q.push(node->left);
 73                 if(node->right)
 74                     q.push(node->right);
 75             }
 76         } 
 77         
 78         //寻找最小的键值 
 79         Key minimum(){
 80             assert(count != 0);
 81             Node* minNode =  minimum(root);
 82             return minNode->key;
 83         }
 84         //寻找最大的键值 
 85         Key maximum(){
 86             assert(count != 0);
 87             Node* maxNode =  maximum(root);
 88             return maxNode->key;
 89         }  
 90         
 91         //从二叉树中删除最小值所在的节点
 92         void removeMin(){
 93             if (root)
 94             root = removeMin( root );
 95         }
 96         //从二叉树中删除最大值所在的节点
 97         void removeMax(){
 98             if (root)
 99             root = removeMax( root );
100         }  
101         //从二叉树中删除键值为key 的节点
102         void remove(Key key){
103         root =    remove(root,key);
104         } 
105          
106         private:
107             //向以node为根的二叉搜索树中,插入节点(key,value) 
108             //返回插入新节点的二叉搜索树的根 
109             Node* insert(Node *node,Key key,Value value){    
110                 if(node == NULL){
111                     count ++;
112                     return new Node(key,value);
113                 }
114                 if(key==node->key)
115                     node->value = value;
116                 else if (key < node->key)
117                     node->left = insert(node->left,key,value);
118                 else
119                     node->right = insert(node->right,key,value);
120                     return node;
121             }
122             //查看以node为根的二叉搜索树中是否包含键值为key的节点 
123             bool contain(Node* node , Key key){
124                 if(key==node->key)
125                 return true;
126                 else if(key<node->key) 
127                     return contain(node->left,key);
128                 else 
129                     return contain(node->right,key);
130             }            
131             Value* search(Node* node,Key key){
132                 if(node ==NULL)
133                 return NULL;
134                 if(key == node->key)
135                     return &(node->value);
136                 else if(key < node->value)
137                     return search(node->left,key);
138                 else
139                     return search(node->right,key);
140             }
141             //对以node为根的二叉搜索树进行前序遍历 
142             void preOrder(Node* node){
143                 if(node != NULL)
144                 cout<<node->key<<endl;
145                 preOrder(node->left);
146                 preOrder(node->right);
147             }
148             //对以node为根的二叉搜索树进行中序遍历
149             void inOrder(Node* node){
150                 if(node != NULL){
151                     inOrder(node->left);
152                     cout<<node->key<<endl;
153                     inOrder(node->right);
154                 }
155             }
156             //对以node为根的二叉搜索树进行后序遍历
157             void postOrder(Node* node){
158                 if(node != NULL){
159                     postOrder(node->left);
160                     postOrder(node->right);
161                     cout<<node->key<<endl;
162                 }
163             }
164             //释放内存 
165             void destroy(Node* node){
166                 if(node != NULL){
167                     destroy(node->left);
168                     destroy(node->right);
169                     delete node;
170                     count --;
171                 }
172             }
173             //在以node为根的二叉搜索树中,返回最小键值的节点 
174             Node* minimum(Node* node){
175                 if(node->left == NULL)
176                 return node;
177             return minimum(node->left); 
178             }
179             
180             //在以node为根的二叉搜索树中,返回最大键值的节点 
181             Node* maximum(Node* node){
182                 if(node->right == NULL)
183                 return node;
184             return maximum(node->right); 
185             }
186             //删除掉以node为根的二分搜索树中的最小节点 
187             //返回删除节点后的二分搜索树 
188             Node* removeMin(Node* node){
189                 if(node->left  == NULL){
190                     Node* rightNode  = node->right;
191                     delete node;
192                     return rightNode;
193                 } 
194                 node->left =  removeMin(node->left);
195                 return node;
196             }
197             //删除掉以node为根的二分搜索树中的最大节点 
198             //返回删除节点后的二分搜索树 
199             Node* removeMax(Node* node){
200                 if(node->right  == NULL){
201                     Node* leftNode  = node->left;
202                     delete node;
203                     return leftNode;
204                 } 
205                 node->right =  removeMax(node->right);
206                 return node;
207             }
208             //删除掉以node为根的二分搜索树中键值为key的节点 
209             //返回删除节点后的二分搜索树 
210             Node* remove(Node* node,Key key){
211                 if(node == NULL)
212                 return NULL;
213                 if(key < node->key){
214                     node->left = remove(node->left,key);
215                     return node;
216                 }
217                 else if (key > node->key){
218                     node->right = remove(node->right,key);
219                     return node;
220                 }
221                 else{  //key = node->key
222                         if(node->left ==NULL){
223                             Node *rightNode = node->right;
224                             delete node;
225                             count --;
226                             return rightNode;
227                         }
228                         
229                         if(node->right ==NULL){
230                             Node *leftNode = node->left;
231                             delete node;
232                             count --;
233                             return leftNode;
234                         }
235                         
236                         //:node的左右孩子都不为空
237                         Node *successor = new Node(minimum(node->right));
238                         count ++;
239                         successor->right = removeMin(node->right);
240                         successor->left = node->left;
241                         delete node;
242                         count --;
243                         return successor;
244                 }
245             }
246 }; 
247 int main(int argc, char** argv) {
248     return 0;
249 }

测试省略

















以上是关于二分搜索树的主要内容,如果未能解决你的问题,请参考以下文章

二分搜索树介绍&PHP 定义节点

实现二分搜索树

二分搜索树(Binary Search Tree)

二分搜索树

敲黑板!数据结构精讲之二分搜索树

学习数据结构笔记(11) --- [二分搜索树(BinarySearchtTree)]