一个简单的二叉搜索树(C++实现)
参考:http://www.cnblogs.com/skywang12345/p/3576373.html
这里主要就是自己实现的代码,删除动作有点不一样:
#ifndef __BSTREE_H__
#define __BSTREE_H__
/*
参考:http://www.cnblogs.com/skywang12345/p/3576373.html 这里是介绍二叉查找树 1)若任意结点的左子树不空,则左子树上所有的结点的值均小于它的根结点的值
2)若任意结点的右子树不空,则左子树上所有的结点的值均大于它的根结点的值
3)任意结点的左右子树也分别为二叉查找树
4)没有键值相等的结点(但是这里实现的可以有相同key值的结点)。当键值相同时,插入在右子树中。
*/
#include<iomanip>
#include<iostream>
using namespace std; template <class T>
class BSTNode
{
public:
T key;
BSTNode *left;
BSTNode *right;
BSTNode *parent; BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):key(value), parent(p),left(l), right(r)
{
//cout << "BSTNode() +++ " << endl;
}
}; template <class T>
class BSTree
{
private:
public:
BSTNode <T> *mRoot; public:
BSTree();
~BSTree(); void insert(T key);
void print();
void preOrder();
T maximum();
T minimum();
int remove(T data);
void destory(); private:
void insert(BSTNode<T> *&tree, BSTNode<T> *z);
void print(BSTNode<T> *tree, T key, int direction);
void preOrder(BSTNode<T> *tree) const;
BSTNode<T>* maximum(BSTNode<T> *tree);
BSTNode<T>* minimum(BSTNode<T> *tree);
BSTNode<T>* getNode(T data);
void destory(BSTNode<T> *tree);
}; template <class T>
BSTree<T>::BSTree()
{
mRoot = NULL;
} template <class T>
BSTree<T>::~BSTree()
{ } template <class T>
void BSTree<T>::insert(T key)
{
BSTNode<T> *z = new BSTNode<T>(key, NULL, NULL, NULL);
if(z)
{
insert(mRoot, z);
}
} // 这里的&是引用传递
template <class T>
void BSTree<T>::insert(BSTNode<T> *&tree, BSTNode<T> *pNode)
{
BSTNode<T> *pIndex = NULL;
BSTNode<T> *pTemp = tree; // 先找到插入的位置
while(pTemp != NULL)
{
pIndex = pTemp;
if(pNode->key < pTemp->key)
pTemp = pTemp->left;
else
pTemp = pTemp->right;
} pNode->parent = pIndex;
if(!pIndex)
tree = pNode;
else if(pNode->key < pIndex->key)
pIndex->left = pNode;
else
pIndex->right = pNode; } template <class T>
void BSTree<T>::print()
{
if(mRoot)
{
print(mRoot, mRoot->key, );
}
} /*
key:结点的键值
direction:
-1 - 表示为左孩子
0 - 表示为根节点
1 - 表示为左孩子
*/
template <class T>
void BSTree<T>::print(BSTNode<T> *tree, T key, int direction)
{
if(tree)
{
if(direction == )
cout << setw() << tree->key << " is root" << endl;
else
cout << setw() << tree->key << " is " << setw() << key << "'s " << setw() << (direction==?"right child":"left child") << endl; print(tree->left, tree->key, -);
print(tree->right, tree->key, );
}
} template <class T>
void BSTree<T>::preOrder()
{
cout << "preOrder: ";
preOrder(mRoot);
cout << endl;
} // 这里是遍历。
template <class T>
void BSTree<T>::preOrder(BSTNode<T> *tree) const
{
if(tree)
{
#if 1 // 前置遍历
cout << tree->key << " ";
preOrder(tree->left);
preOrder(tree->right);
#endif #if 0 // 中序遍历
preOrder(tree->left);
cout << tree->key << " ";
preOrder(tree->right);
#endif #if 0 // 后序遍历
preOrder(tree->left);
preOrder(tree->right);
cout << tree->key << " ";
#endif
}
} // 找二叉查找树中的最大值,返回key值最大的那个结点
template <class T>
BSTNode<T> * BSTree<T>::maximum(BSTNode<T> *tree)
{
BSTNode<T> *temp = tree;
if(temp)
{
while(temp->right)
{
temp = temp->right;
} return temp;
}
else
{
return NULL;
}
} // 找二叉查找树中的最小值,返回key值最小的那个结点
template <class T>
BSTNode<T> * BSTree<T>::minimum(BSTNode<T> *tree)
{
BSTNode<T> *temp = tree;
if(temp)
{
while(temp->left)
{
temp = temp->left;
} return temp;
}
else
{
return NULL;
}
} template <class T>
T BSTree<T>::maximum()
{
BSTNode<T> *temp = maximum(mRoot);
if(temp)
{
return temp->key;
} return NULL;
} template <class T>
T BSTree<T>::minimum()
{
BSTNode<T> *temp = minimum(mRoot);
if(temp)
{
return temp->key;
} return NULL;
} // 通过data去获取结点。
template <class T>
BSTNode<T>* BSTree<T>::getNode(T data)
{
BSTNode<T> *temp = mRoot;
if(!temp)
{
return NULL;
} while(temp)
{
if(temp->key == data)
return temp;
else if(temp->key < data)
temp = temp->right;
else
temp = temp->left;
} return NULL;
} // 这个仅仅是用来打印结点的。测试用的
template <class T>
void showNode(BSTNode<T>* node)
{
if(node->parent)
{
cout << " parent: " << node->parent->key << endl;
}
else
{
cout << " parent is NULL" << endl;
} if(node->left)
{
cout << " left: " << node->left->key << endl;
}
else
{
cout << " left is NULL" << endl;
} if(node->right)
{
cout << " right: " << node->right->key << endl;
}
else
{
cout << " right is NULL" << endl;
}
} /*
参考:http://blog.csdn.net/zq17865815296/article/details/52658908
先说一下如何删除二叉树查找树的节点吧。总共有三种情况
1.被删除的节点是叶子节点,这时候只要把这个节点删除,再把指向这个节点的父节点指针置为空就行
2.被删除的节点有左子树,或者有右子树,而且只有其中一个,那么只要把当前删除节点的父节点指向被删除节点的左子树或者右子树就行。
3.被删除的节点既有左子树而且又有右子树,这时候需要把左子树的最右边的节点或者右子树最左边的节点提到被删除节点的位置,为什么要这样呢,
根据二叉查找树的性质,父节点的指针一定比所有左子树的节点值大而且比右子树的节点的值小,为了删除父节点不破坏二叉查找树的平衡性,
应当把左子树最大的节点或者右子树最小的节点放在父节点的位置,这样的话才能维护二叉查找树的平衡性。(我是找的右子树的最小节点)
*/
template <class T>
int BSTree<T>::remove(T data)
{
cout << "remove :" << data << endl;
BSTNode<T>* node = getNode(data);// 这里要找到要删除的结点。
if(node)
{
showNode(node);
if(node->parent == NULL)// 删除根结点
{
// 这里选择的是把左子树接到右子树中key最小的那个结点的左结点上。还有一种是把右子树接到左子树的key最大的那个右结点上
BSTNode<T> *temp = minimum(node->right);
if(temp)
{
temp->left = node->left;
mRoot = node->right;// 要更新根节点
}
delete node;
node = NULL;
return ;
} if((node->right == NULL) && (node->left == NULL)) // 删除叶子结点
{
if(node->parent->left == node)
{
node->parent->left = NULL;
}
else
{
node->parent->right = NULL;
}
}
else if(node->right && node->left) // 删除有两个子节点的
{
BSTNode<T> *temp = minimum(node->right); // 获取后继结点,这个结点一定是没有左子树的。
cout << "have left and right child, mimmum :" << temp->key << endl;
if(temp == temp->parent->left) // 后继结点如果是左结点,就将它的右子树接到它父亲的左子树中。
{
temp->parent->left = temp->right;
}
else // 后继结点如果是右结点,就将它的右子树接到它父亲的右子树中。
{
temp->parent->right = temp->right;
}
node->key = temp->key; // 把后继结点的key保存在要删除的结点中
delete temp; // 其实是删除的后继结点。
temp = NULL;
}
else // 删除只有一个只有一个子结点。
{
if(node->right) // 有右子节点
{
if(node->parent->left == node)
{
node->parent->left = node->right;
}
else
{
node->parent->right = node->right;
}
}
else
{
if(node->parent->left == node)
{
node->parent->left = node->left;
}
else
{
node->parent->right = node->left;
}
}
delete node;
node = NULL;
} }
else
{
return -;
} return ;
} template <class T>
void BSTree<T>::destory(BSTNode<T> *tree)
{
if(tree)
{
if(tree->left)
destory(tree->left);
if(tree->right)
destory(tree->right);
delete tree;
tree = NULL;
}
} template <class T>
void BSTree<T>::destory()
{
destory(mRoot);
} #endif // __BSTREE_H__
下面是测试代码:
#include<iostream>
#include"bstree.h"
using namespace std; /*
可以插入相同的,会插入在右子树中。
*/
void fun()
{
cout << "fun() +++ " << endl;
int i = , len = ;
BSTree<int>* tree = new BSTree<int>;
if(tree->mRoot == NULL)
cout << "fun() mRoot is NULL" << endl;
int arr[] = {, , , , , , , , , };
int count = sizeof(arr)/sizeof(int);
for(int i = ; i<count; i++)
{
tree->insert(arr[i]);
}
tree->insert(); tree->insert();
tree->preOrder();
int maxkey = tree->maximum();
cout << "Max key = " << maxkey << endl;
int minkey = tree->minimum();
cout << "Min key = " << minkey << endl;
tree->remove();
tree->remove(); tree->preOrder();
//tree->print(); tree->destory();
cout << "fun() --- " << endl;
} int main()
{
cout << "hello world" << endl;
fun();
return ;
}
注意:上面只有bstree.h,没有bstree.cpp。
关于为何C++的模板类声明和实现要放在一起可以参考:http://www.cnblogs.com/xcywt/p/8039574.html
一个简单的二叉搜索树(C++实现)的更多相关文章
- LeetCode(98): 验证二叉搜索树
Medium! 题目描述: 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右 ...
- 「面试高频」二叉搜索树&双指针&贪心 算法题指北
本文将覆盖 「字符串处理」 + 「动态规划」 方面的面试算法题,文中我将给出: 面试中的题目 解题的思路 特定问题的技巧和注意事项 考察的知识点及其概念 详细的代码和解析 开始之前,我们先看下会有哪些 ...
- LeetCode初级算法--树02:验证二叉搜索树
LeetCode初级算法--树02:验证二叉搜索树 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...
- LeetCode 第98题--验证二叉搜索树
1. 题目 2.题目分析与思路 3.代码 1. 题目 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数.节点的右子树只包含大于当 ...
- 【LeetCode】验证二叉搜索树
[问题]给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征:节点的左子树只包含小于当前节点的数.节点的右子树只包含大于当前节点的数.所有左子树和右子树自身必须也是二叉搜 ...
- Java实现二叉搜索树的插入、删除
前置知识 二叉树的结构 public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() { } TreeNode( ...
- 剑指Offer面试题:22.二叉搜索树的后序遍历序列
一.题目:二叉搜索树的后序遍历序列 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 例如在下面 ...
- 二叉搜索树(Binary Search Tree)
二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树. 二叉搜索树:一棵二叉树,可以为空:如果不为空,满足以下性质: 非空左子树的所有键值小于其根结点的键值: 非空右 ...
- LeetCode - 验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树. 一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也是二叉搜索树. ...
随机推荐
- 腾讯/阿里/百度 BAT人才体系的职位层级、薪酬、晋升标准
互联网圈有这么一句话:百度的技术,阿里的运营,腾讯的产品.那么代表互联网三座大山的BAT,内部人才体系有什么区别呢?今天老李就带领大家看一看~ ★ 腾讯 ★ 1. 职级 腾讯职级体系分6级,最低1 ...
- xss基础
0x0 定义 总结: (1) 在页面显示 (2) 用户可控 满足以上两点就有可能存在xss 0x1反射型 0x2存储型 0x3 DOM型 与反射型相似 也是从get等参数传参 但 反射 ...
- 【Alpha】第五次Scrum meeting
今日重大事件一览: 姓名 今日完成任务 所耗时间 刘乾 今日没有完成那个Issue..TuT第一次这么努力工作的我没有完成任务...真的是任务太坑啦. 任务完成了 60% Issue链接:https: ...
- LeetCode 167. 两数之和 II - 输入有序数组
题目: 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值index1 和 index2,其中 index1 必须小于 index2. 说明: 返回的 ...
- windows8/10+Ubuntu Kylin(优麒麟)双系统
1.参考资料:http://www.jianshu.com/p/2eebd6ad284d 中第三种U盘启动方式安装完成 2.安装过程: (1)首先将一个盘空出来,做好其中数据的备份.启动win+X磁盘 ...
- C++ Makefile文件编写
对现有的一个C++动态库文件和调用程序,分别编写Makefile文件,从零开始,这里把自己弄明白的一些东西分享给大家. 1.必须明确Linux下,C++的编译器是g++,C语言的是gcc.网上大多数又 ...
- ubuntu18.04配置nvidia docker和远程连接ssh+远程桌面连接(一)
ubuntu18.04配置nvidia docker和远程连接ssh+远程桌面连接(一) 本教程适用于想要在远程服务器上配置docker图形界面用于深度学习的用户. (一)ubuntu18.04配置n ...
- final阶段140字评论
按课堂顺序 1约跑APP ,无论从页面还是从功能来看完整度都很高了.演示也用了能展示的方式.多些趣味性就更赞了. 2礼物挑选小工具,做了能在规定时间内的功能.也算是对礼物固话的一个成本最低的回应. 3 ...
- Exchange2010批量删除邮件
在Exchange2010里若要删除某个用户发出的邮件,可以通过EMC控制台授予管理员“管理完全访问权限”,通过OWA登录到用户邮箱删除.另外,更简便的方法为使用Exchange2010的命令来处理, ...
- WebSocket 时时双向数据,前后端(聊天室)
https://blog.csdn.net/lecepin/article/details/54632749 实例内容 今天主要说一下微信的WebSocket接口以及在小程序中的使用. WebSock ...