二叉搜索树的简易实现

Posted jeavenwong

tags:

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

二叉查找树或者是一棵空二叉树;或者是具有下列性质的二叉树:

(1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

(2)若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。 (3)根结点的左右子树分别也是二叉查找树。

二叉查找树可以用来组织一组数据,并且实现在这组数据上的快速检索。

 

二叉查找树或者是一棵空二叉树;或者是具有下列性质的二叉树:

(1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

(2)若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。

(3)根结点的左右子树分别也是二叉查找树。

二叉查找树可以用来组织一组数据,并且实现在这组数据上的快速检索。

 

向二叉查找树中插入新结点必须保证插入新结点后,二叉树仍然满足二叉查找树的定义。

如何在二叉查找树中插入新结点?

(1)若二叉查找树为空,则新结点应作为二叉查找树的根结点。

(2)将新结点的值和根结点的值比较,如果相等返回。(此时要插入的结点在树中已存在)

(3)如果新结点的值小于根结点的值,则转二叉查找树的左子树继续插入操作。

(4)如果新结点的值大于根结点的值,则转二叉查找树的右子树继续插入操作。

 

从二叉查找树上删除结点应保证结点删除后得到的二叉树仍然是二叉查找树。

如何从二叉查找树中删除结点?

(1)如果要删除的结点是叶子结点,直接删除并更新父结点指针。

(2)如果要删除的结点只有一棵非空子树,则令该非空子树代替被删除的结点作为被删除结点父结点的相应子树。

(3)如果要删除的结点的两棵子树均非空,问题比较复杂,此时用要删除结点的中序前趋替换要删除的结点,再运用(1)和(2)中的方法删除处在原来位置上的要删除结点的中序前趋。而前驱结点是左子树的右下角的那个结点。

 

下面是用C++实现的二叉搜索树?

  1 template <typename Entry>
  2 class binary_tree
  3 {
  4     protected:
  5         //定义树结点,方便访问,不封装,全部开放
  6         class binary_node
  7         {
  8             public:
  9                 Entry data; //数据域
 10                 binary_node* lchild; //指向左子树的指针域
 11                 binary_node* rchild; //指向右子树的指针域
 12                 binary_node(){} //无参数构造函数
 13                 binary_node(const Entry& x):data(x),rchild(null),lchild(null){} //带参数构造函数
 14         };
 15         
 16         binary_node* root; //指向根结点的指针
 17     
 18     public:
 19         binary_tree();
 20         binary_tree(const binary_tree& bt);
 21         virtual ~binary_tree();
 22         bool empty() const;
 23         int size() const;
 24         int height() const;
 25         void clear();
 26         void preorder(binary_node*root,void(*visit)(Entry&));
 27         void inorder(binary_node*root,void(*visit)(Entry&));
 28         void postorder(binary_node*root,void(*visit)(Entry&));
 29         void level_traversal(binary_node*root,void(*visit)(Entry&))
 30         int insert(const Entry&);
 31         int remove(const Entry&);
 32         binary_tree& operator=(const binary_tree& bt);
 33         
 34 };
 35 
 36 //二叉查找树,普通二叉树的基础上写
 37 template <typename Entry>
 38 class search_tree: public binary_tree
 39 {
 40     public:
 41         int tree_search(Entry&) const;
 42         int insert(const Entry&);
 43         int remove(const Entry&);
 44         
 45 };
 46 
 47 
 48 //按值查找结点
 49 template <typename Entry>
 50 search_tree<Entry>::binary_node<Entry>* search_for_node(binary_node* root,const Entry& target)
 51 {
 52     while(root->data != target && root != NULL)
 53         if(root->data < target) root = root->rchild;
 54         else root = root->lchild;
 55     return root;
 56 }
 57 
 58 //查找,并且将找到的data放入传入变量中
 59 template <typename Entry>
 60 int search_tree<Entry>::tree_search(const Entry& target) const
 61 {
 62     int result = 1;
 63     binary_node* found = search_for_node(target);
 64     if(found == NULL) result = 0;
 65     else target = found->data;
 66     return result;
 67 }
 68 
 69 
 70 //查找并且插入
 71 template <typename Entry>
 72 int search_tree<Entry>::search_and_insert(binary_node* root,const Entry& new_data)
 73 {
 74     if(root == NULL)
 75     {
 76         root = new binary_node(new_data); 
 77         return 1;
 78     }
 79     else if(new_data < root->data)
 80         return search_and_insert(root->lchild,new_data);
 81     else if(new_data > root->data)
 82         return search_and_insert(root->rchild,new_data);
 83     else return 0;
 84 }
 85 
 86 //插入操作
 87 template <typename Entry>
 88 int search_tree<Entry>::insert(const Entry& new_data)
 89 {
 90     return search_and_insert(root,new_data);
 91 }
 92 
 93 
 94 //删除结点操作
 95 template <typename Entry>
 96 int search_tree<Entry>::remove_node(binary_node* node)
 97 {
 98     if(root == NULL) return 0;
 99     if(node->rchild == NULL) node = node->lchild;
100     else if(node->lchild == NULL) node = node->rchild;
101     else
102     {
103         binary_node* parent = NULL;
104         binary_node* son = node->lchild;
105 /*找到要删除结点的左子树的最右下角的结点,即为待删除结点的中序前驱结点*/
106         while(temp->rchild != NULL)
107         {
108             parent = son;
109             son = son->rchild;
110         }
111         //parent是前驱结点的父节点,待删除结点的前驱结点为子节点son。
112         node->data = son->data; //将前驱结点放到待删除结点的位置
113         if(son->lchild != NULL)  //删除前驱结点
114         {
115             son->data = son->lchild->data;
116             delete son-lchild;
117         }
118         
119     }
120     return 1;
121     
122 }
123 
124 //查找并且删除
125 template <typename Entry>
126 int search_tree <Entry>::search_and_destroy(binary_node* root,const Entry& target)
127 {
128     if(root == NULL || root->data == target)
129         return remove_node(root);
130     else if(root->data < target)
131         search_and_destroy(root->rchild,target);
132     else search_and_destroy(root->lchild,target);
133 }
134 
135 
136 //删除操作
137 template <typename Entry>
138 int search_tree<Entry>::remove(const Entry& target)
139 {
140     return search_and_destroy(root,target);
141 } 

 

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

LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段

二叉搜索树的概念 及 功能代码实现

高阶数据结构 | 二叉搜索树(Binary Search Tree)

二叉搜索树

二叉搜索树的理解以及AVL树的模拟实现

二叉搜索树的理解以及AVL树的模拟实现