二叉搜索树定义
具有特殊性质的二叉树,即:每一个双亲节点都比左孩子大、比右孩子小(这个不一定,具体看实现方式,本文是这样实现的),则每一次中序遍历都是有序的。
每一个节点的类型
template<class T>
struct BStreeNode {
BStreeNode() :right(nullptr),left(nullptr),data(T()){}
BStreeNode<T>* right;
BStreeNode<T>* left;
T data;
};
构造函数:在这里只需要构造一个空的节点就可以,当作根来使用
typedef BStreeNode<T> Node;
BStree():root(nullptr){}
二叉树的插入操作:首先如果树是空的那么直接插入都根的位置即可,如果树不空,则先查找插入节点的位置,这里根据二叉搜索树的特点进行查找,找到插入位置时插入数据即可。
void Insert(const T& x) {
if (root == nullptr)
{
root = new Node;
root->data = x;
}
//找插入位置的双亲节点
Node* cur = root;
Node* parent=nullptr;
while (cur) {
parent = cur;
if (cur->data > x) cur = cur->left;
else if (cur->data < x) cur = cur->right;
else
return;
}
//插入节点
cur = new Node;
cur->data = x;
if (parent->data < x) parent->right = cur;
else if (parent->data > x) parent->left = cur;
else
return;
}
查找操作:根据二叉搜索树的性质进行查找。
bool Find_tree(const T& data) {
if (root) {
Node* cur = root;//记录节点
while (cur)
{
if (data == cur->data) return true;
else if (data > cur->data) cur = cur->right;
else if (data < cur->data) cur = cur->left;
}
return false;
}
}
删除操作:这可以说是二叉搜索树的核心操作了,首先查找删除位置,中跟上述的查找是一样的,但是删除时不一样的位置有不一样的删除方法。
void Erase_tree(const T& data) {
//查找节点
Node* cur = root;
Node* parent = nullptr;
while (cur) {
if (data == cur->data) break;
else if (data > cur->data) { parent = cur; cur = cur->right; }
else if (data < cur->data) { parent = cur; cur = cur->left; }
}
if (cur == nullptr) return;//另一个作用可以判断是否为空树
//删除节点
if (nullptr == cur->left&&cur->right!=nullptr)
{
if (parent == nullptr)
root = cur->right;
if (cur->right != nullptr&&parent->left==cur) parent->left = cur->right;
if (cur->right != nullptr&&parent->right==cur) parent->right = cur->right;
}
if (nullptr == cur->right&&cur->left!=nullptr)
{
if (parent == nullptr) root = cur->left;
root = cur->right;
if (cur->left != nullptr && parent->left == cur) parent->left = cur->left;
if (cur->left != nullptr && parent->right == cur) parent->right = cur->left;
}
if (cur->left != nullptr && cur->right != nullptr) {
Node* DelNode = cur->right;
parent = cur;
while(DelNode->left) {//找右子树中最左边的节点
parent = DelNode;
DelNode = DelNode->left;
}
cur->data = DelNode->data;
//删除替代节点
//记录删除的右节点
if (parent->left == DelNode) parent->left = DelNode->right;
else parent->right = DelNode->right;
cur = DelNode;
}
delete cur;
cur = nullptr;
}
二叉树的回收:不能像回收链表一样直接回收根节点,二叉树回收要一个节点一个节点去删除,并且删除过程不能丢失节点,因此本文使用后序遍历回收节点。
void Destory(Node*& proot) {
if (proot) {
Destory(proot->left);
Destory(proot->right);
delete proot;
proot = nullptr;
}
}
二叉树的层序遍历:借助队列进行实现。
void Level_Oreder() {//层序遍历
if (root == nullptr) return;
//借助queue容器
queue<Node*> q;
q.push(root);
while (!q.empty()) {
Node* cur = q.front();
cout << cur->data<<" ";
q.pop();
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
}
以上是较为重要的函数,其中三种递归遍历方式付在源代码中。
#include<queue>
#include<iostream>
using namespace std;
template<class T>
struct BStreeNode {
BStreeNode() :right(nullptr),left(nullptr),data(T()){}
BStreeNode<T>* right;
BStreeNode<T>* left;
T data;
};
template<class T>
class BStree {
public:
typedef BStreeNode<T> Node;
BStree():root(nullptr){}
void Insert(const T& x=T()) {
if (root == nullptr)
{
root = new Node;
root->data = x;
}
//找插入位置的双亲节点
Node* cur = root;
Node* parent=nullptr;
while (cur) {
parent = cur;
if (cur->data > x) cur = cur->left;
else if (cur->data < x) cur = cur->right;
else
return;
}
//插入节点
cur = new Node;
cur->data = x;
if (parent->data < x) parent->right = cur;
else if (parent->data > x) parent->left = cur;
else
return;
}
~BStree()
{
Destory(root);
}
void Show_tree() {
Show(root);
}
bool Find_tree(const T& data) {
if (root) {
Node* cur = root;//记录节点
while (cur)
{
if (data == cur->data) return true;
else if (data > cur->data) cur = cur->right;
else if (data < cur->data) cur = cur->left;
}
return false;
}
}
void Erase_tree(const T& data) {
//查找节点
Node* cur = root;
Node* parent = nullptr;
while (cur) {
if (data == cur->data) break;
else if (data > cur->data) { parent = cur; cur = cur->right; }
else if (data < cur->data) { parent = cur; cur = cur->left; }
}
if (cur == nullptr) return;//另一个作用可以判断是否为空树
//删除节点
if (nullptr == cur->left&&cur->right!=nullptr)
{
if (parent == nullptr)
root = cur->right;
if (cur->right != nullptr&&parent->left==cur) parent->left = cur->right;
if (cur->right != nullptr&&parent->right==cur) parent->right = cur->right;
}
if (nullptr == cur->right&&cur->left!=nullptr)
{
if (parent == nullptr) root = cur->left;
root = cur->right;
if (cur->left != nullptr && parent->left == cur) parent->left = cur->left;
if (cur->left != nullptr && parent->right == cur) parent->right = cur->left;
}
if (cur->left != nullptr && cur->right != nullptr) {
Node* DelNode = cur->right;
parent = cur;
while(DelNode->left) {//找右子树中最左边的节点
parent = DelNode;
DelNode = DelNode->left;
}
cur->data = DelNode->data;
//删除替代节点
//记录删除的右节点
if (parent->left == DelNode) parent->left = DelNode->right;
else parent->right = DelNode->right;
cur = DelNode;
}
delete cur;
cur = nullptr;
}
void Level_Oreder() {//层序遍历
if (root == nullptr) return;
//借助queue容器
queue<Node*> q;
q.push(root);
while (!q.empty()) {
Node* cur = q.front();
cout << cur->data<<" ";
q.pop();
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
}
private:
Node* root;//根节点
private:
void Show(Node* root) {
if (root) {
Show(root->left);
cout << root->data << " ";
Show(root->right);
}
}
void Destory(Node*& proot) {
if (proot) {
Destory(proot->left);
Destory(proot->right);
delete proot;
proot = nullptr;
}
}
};