zoukankan      html  css  js  c++  java
  • 二分搜索树

    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 }

    测试省略

  • 相关阅读:
    响应式开发
    webstrom配置
    CSS水平垂直居中
    CSS3里的 转换与过渡动效
    CSS布局
    CSS定宽居中的实现方案
    Flex布局篇2
    编辑器中快速生成代码——emmet输入法
    display:flex实践加感悟
    websocket connet.js
  • 原文地址:https://www.cnblogs.com/Tom-shushu/p/10067794.html
Copyright © 2011-2022 走看看