zoukankan      html  css  js  c++  java
  • 二叉查找树

    1.二叉查找树又称为二叉搜索树。二叉查找树和普通的二叉树在结构上一样,它要么是一棵空树,要么是这样的一棵二叉树:对任意结点,如果左子树不为空,则左子树上所有结点的权值都小于该结点的权值;如果右子树不为空,则右子树上所有结点的权值都大于该结点的权值;任意结点的左子树和右子树都是一棵二叉查找树;一般而言, 二叉查找树上结点的权值都是唯一的。

    • 在二叉排序树上,对于任意结点,如果有左子树和右子树,那么其左子树上结点的权值都小于右子树上结点的权值。
    • 如果中序遍历二叉排序树,会得到一个从小到大的序列。
    • 二叉排序树的插入和查找效率相对较高,最坏情况下时间复杂度为 O(n),期望的时间复杂度为 O(logn),其中 n 为树上结点总个数。

    刚才我们提到了二叉排序树最坏情况下时间复杂度为 O(n),这是为什么呢?最坏情况下,二叉排序树会退化成链表,从根结点往左依次递减,或者从根结点往右依次递增。那有什么方法可以解决这个问题呢?在二叉排序树的基础上可以加些优化,可以让其成为 AVL 树,红黑树,SBT,Splay 等等,这些高级的树结构解决了上面的问题,插入和查找的效率均为 O(logn)。

    2.二叉排序树的性质

    3.二叉查找树的构造,插入,查找,删除

      1 #include<iostream>
      2 using namespace std;
      3 class Node {
      4 public:
      5     int data;
      6     Node *lchild, *rchild, *father;
      7     Node(int _data, Node *_father = NULL) {
      8         data = _data;
      9         lchild = NULL;
     10         rchild = NULL;
     11         father = _father;
     12     }
     13     ~Node() {
     14         if (lchild != NULL) {
     15             delete lchild;
     16         }
     17         if (rchild != NULL) {
     18             delete rchild;
     19         }
     20     }
     21     void insert(int value) {               //二叉查找树的插入(递归)
     22         if (value == data) {
     23             return;
     24         } else if (value > data) {
     25             if (rchild == NULL) {
     26                 rchild = new Node(value, this);
     27             } else {
     28                 rchild->insert(value);
     29             }
     30         } else {
     31             if (lchild == NULL) {
     32                 lchild = new Node(value, this);
     33             } else {
     34                 lchild->insert(value);
     35             }
     36         }
     37     }
     38     Node* search(int value) {           //二叉查找树的查找(递归)
     39         if (data == value) {
     40             return this;
     41         } else if (value > data) {
     42             if (rchild == NULL) {
     43                 return NULL;
     44             } else {
     45                 return rchild->search(value);
     46             }
     47         } else {
     48             if (lchild == NULL) {
     49                 return NULL;
     50             } else {
     51                 return lchild->search(value);
     52             }
     53         }
     54     }
     55     Node* predecessor() {              //找节点的前驱(左孩子节点孩子不为空)
     56         Node *temp = lchild;
     57         while (temp != NULL && temp->rchild != NULL) {
     58             temp = temp->rchild;
     59         }
     60         return temp;
     61     }
     62     Node* successor() {                //找节点的后继(右孩子节点不为空)
     63         Node *temp = rchild;
     64         while (temp != NULL && temp->lchild != NULL) {
     65             temp = temp->lchild;
     66         }
     67         return temp;
     68     }
     69     void remove_node(Node *delete_node) {   //删除度为1或0的节点
     70         Node *temp = NULL;
     71         if (delete_node->lchild != NULL) {
     72             temp = delete_node->lchild;
     73             temp->father = delete_node->father;
     74             delete_node->lchild = NULL;
     75         }
     76         if (delete_node->rchild != NULL) {
     77             temp = delete_node->rchild;
     78             temp->father = delete_node->father;
     79             delete_node->rchild = NULL;
     80         }
     81         if (delete_node->father->lchild == delete_node) {
     82             delete_node->father->lchild = temp;
     83         } else {
     84             delete_node->father->rchild = temp;
     85         }
     86         delete delete_node;
     87     }
     88     bool delete_tree(int value){     //二叉查找树的删除
     89         Node *delete_node,*current_node;
     90         current_node=search(value);
     91         if(current_node==NULL){
     92             return false;
     93         }
     94         if(current_node->lchild!=NULL){
     95             delete_node=current_node->predecessor();
     96         }
     97         else if(current_node->rchild!=NULL){
     98             delete_node=current_node->successor();
     99         }
    100         else{
    101             delete_node=current_node;
    102         }
    103         current_node->data=delete_node->data;//先替换,再转化为度为0的情况
    104         remove_node(delete_node);
    105         return true;
    106     }
    107 };
    108 class BinaryTree {
    109 private:
    110     Node *root;
    111 public:
    112     BinaryTree() {
    113         root = NULL;
    114     }
    115     ~BinaryTree() {
    116         if (root != NULL) {
    117             delete root;
    118         }
    119     }
    120     void insert(int value) {
    121         if (root == NULL) {
    122             root = new Node(value);
    123         } else {
    124             root->insert(value);
    125         }
    126     }
    127     bool find(int value) {
    128         if (root->search(value) == NULL) {
    129             return false;
    130         } else {
    131            return true;
    132         }
    133     }
    134     bool delete_tree(int value){
    135         return root->delete_tree(value);
    136     }
    137 };
    138 int main() {
    139     BinaryTree binarytree;
    140     int arr[10] = { 8, 9, 10, 3, 2, 1, 6, 4, 7, 5 };
    141     for (int i = 0; i < 10; i++) {
    142         binarytree.insert(arr[i]);
    143     }
    144     int value;
    145     cin >> value;
    146     if (binarytree.find(value)) {
    147         cout << "search success!" << endl;
    148     } else {
    149         cout << "search failed!" << endl;
    150     }
    151     cin>>value;
    152     if(binarytree.delete_tree(value)){
    153         cout<<"delete success!"<<endl;
    154     }
    155     else{
    156         cout<<"delete failed!"<<endl;
    157     }
    158     return 0;
    159 }
  • 相关阅读:
    将"089,0760,009"变为 89,760,9
    单向循环链表
    双链表复习
    【C语言】scanf()输入浮点型数据
    【C语言】一元二次方程(求实根和虚根)
    输入一个三位正整数,输出百位数,十位数,个位数
    输入身份证号,输出出生日期
    比较四个数的大小
    比较三个数的大小
    比较两个数的大小
  • 原文地址:https://www.cnblogs.com/Reindeer/p/5691363.html
Copyright © 2011-2022 走看看