说明
BST树称作二叉搜索树(Binary Search Tree)或者二叉排序树(Binary Sort Tree),它或者是一颗空 树;或者是具有下列性质的二叉树:
- 若左子树不为空,则左子树上所有节点的值均小于它的根节点的值
- 若右子树不为空,则右子树上所有节点的值均大于它的根节点的值
- 左右子树也分别满足二叉搜索树性质
特点: 每一个节点都满足 左孩子的值(不为空) < 父节点的值 < 右孩子的值(不为空)
非递归方式插入、删除、查询
代码
#include <iostream>
#include <functional>
using namespace std;
// BST树代码实现
template<typename T, typename Compare=less<T>>
class BSTree {
public:
BSTree() : root_(nullptr) {
}
~BSTree() {
}
// 非递归删除操作
void n_remove(const T &val) {
if (root_ == nullptr) {
return;
}
Node* parent = nullptr;
Node* cur = root_;
while (cur != nullptr) {
if (cur->data_ == val) {
break; // 相等。找到待删除节点
} else if (compare_(cur->data_, val)) {
parent = cur;
cur = cur->right_;
} else {
parent = cur;
cur = cur->left_;
}
}
// 没找到待删除节点
if (cur == nullptr) {
return;
}
// 先处理有两个子节点的情况
if (cur->left_ != nullptr && cur->right_ != nullptr) {
Node *pre = cur->left_;
while (pre->right_ != nullptr) {
pre = pre->right_; // 找到左子树中最大的节点(找到前驱)
}
cur->data_ = pre->data_;
cur = pre; // 让cur指向前驱节点
}
// 当节点有一个子节点或者两个子节点的话
// cur指向删除节点,parent指向其父节点
Node* child = cur->left_;
if (child == nullptr) {
child = cur->right_;
}
if (parent == nullptr) { // 表示删除的是根节点
root_ = child;
} else {
// 把待删除节点的孩子(nullptr,或者不空) ,写入其父节点相应的地址域中
if (parent->left_ == cur) {
parent->left_ = child;
} else {
parent->right_ = child;
}
}
// cur指向的是待删除节点
delete cur; // 删除当前节点
};
// 非递归插入操作
void n_insert(const T &val) {
if (root_ == nullptr) { // 树为空, 生成根节点
root_ = new Node(val);
return;
}
// 从根节点往下找,为了找到合适的parent
Node* parent = nullptr;
Node* cur = root_;
while (cur != nullptr) {
if (cur->data_ == val) {
return; // 相等,不插入相同值
} else if (compare_(cur->data_, val)) {
// 插入的值大于节点元素值,往右走
parent = cur;
cur = cur->right_;
} else {
// 插入的值小于节点元素值,往左走
parent = cur;
cur = cur->left_;
}
}
// 把新节点插入到parent节点的孩子上
if (compare_(parent->data_, val)) { // 比较插入的值与parant的大小后进行插入
parent->right_ = new Node(val);
} else {
parent->left_ = new Node(val);
}
}
// 非递归查询操作
bool n_query(const T& val) {
Node* cur = root_;
while (cur != nullptr) {
if (cur->data_ == val) {
return true;
}
else if (compare_(cur->data_, val)) {
cur = cur->right_;
}
else {
cur = cur->left_;
}
}
return false;
}
private:
// 节点定义
struct Node {
Node(T data = T())
: data_(data)
, left_(nullptr)
, right_(nullptr) {
}
T data_; // 节点的数据域
Node* left_; // 左孩子
Node* right_; // 右孩子
};
Node* root_; // 指向BST树的根节点
Compare compare_; // 定义一个函数对象
};
int main() {
int arr[] = {58, 24, 67, 0, 34, 62, 69, 5, 41, 64, 78};
BSTree<int> bst;
for (int v : arr) {
bst.n_insert(v);
}
bst.n_insert(12);
bst.n_remove(12);
// 测试查询
cout << bst.n_query(34) << endl;
cout << bst.n_query(99) << endl;
return 0;
}
测试
我们使用调试方式查看下树的结构
递归前序遍历,中序遍历,后序遍历,层序遍历
#include <iostream>
#include <functional>
using namespace std;
// BST树代码实现
template<typename T, typename Compare=less<T>>
class BSTree {
public:
BSTree() : root_(nullptr) {
}
~BSTree() {
}
// 非递归删除操作
void n_remove(const T &val) {
if (root_ == nullptr) {
return;
}
Node* parent = nullptr;
Node* cur = root_;
while (cur != nullptr) {
if (cur->data_ == val) {
break; // 相等。找到待删除节点
} else if (compare_(cur->data_, val)) {
parent = cur;
cur = cur->right_;
} else {
parent = cur;
cur = cur->left_;
}
}
// 没找到待删除节点
if (cur == nullptr) {
return;
}
// 先处理有两个子节点的情况
if (cur->left_ != nullptr && cur->right_ != nullptr) {
Node *pre = cur->left_;
while (pre->right_ != nullptr) {
pre = pre->right_; // 找到左子树中最大的节点(找到前驱)
}
cur->data_ = pre->data_;
cur = pre; // 让cur指向前驱节点
}
// 当节点有一个子节点或者两个子节点的话
// cur指向删除节点,parent指向其父节点
Node* child = cur->left_;
if (child == nullptr) {
child = cur->right_;
}
if (parent == nullptr) { // 表示删除的是根节点
root_ = child;
} else {
// 把待删除节点的孩子(nullptr,或者不空) ,写入其父节点相应的地址域中
if (parent->left_ == cur) {
parent->left_ = child;
} else {
parent->right_ = child;
}
}
// cur指向的是待删除节点
delete cur; // 删除当前节点
};
// 非递归插入操作
void n_insert(const T &val) {
if (root_ == nullptr) { // 树为空, 生成根节点
root_ = new Node(val);
return;
}
// 从根节点往下找,为了找到合适的parent
Node* parent = nullptr;
Node* cur = root_;
while (cur != nullptr) {
if (cur->data_ == val) {
return; // 相等,不插入相同值
} else if (compare_(cur->data_, val)) {
// 插入的值大于节点元素值,往右走
parent = cur;
cur = cur->right_;
} else {
// 插入的值小于节点元素值,往左走
parent = cur;
cur = cur->left_;
}
}
// 把新节点插入到parent节点的孩子上
if (compare_(parent->data_, val)) { // 比较插入的值与parant的大小后进行插入
parent->right_ = new Node(val);
} else {
parent->left_ = new Node(val);
}
}
// 非递归查询操作
bool n_query(const T& val) {
Node* cur = root_;
while (cur != nullptr) {
if (cur->data_ == val) {
return true;
}
else if (compare_(cur->data_, val)) {
cur = cur->right_;
}
else {
cur = cur->left_;
}
}
return false;
}
// 递归前序遍历
void preOrder() {
cout << "[递归]前序遍历";
preOrder(root_);
cout << endl;
}
// 递归中序遍历
void inOrder() {
cout << "[递归]中序遍历";
inOrder(root_);
cout << endl;
}
// 递归后序遍历
void postOrder() {
cout << "[递归后序遍历]";
postOrder(root_);
cout << endl;
}
// 递归层序遍历
void levelOrder() {
cout << "递归层序遍历";
int h = high(); // 树的层数
for (int i = 0; i < h; i++) {
levelOrder(root_, i);
}
cout << endl;
}
// 递归求二叉树层数
int high() {
return high(root_);
}
// 递归求二叉树节点个数
int number() {
return number(root_);
}
private:
// 节点定义
struct Node {
Node(T data = T())
: data_(data)
, left_(nullptr)
, right_(nullptr) {
}
T data_; // 节点的数据域
Node* left_; // 左孩子
Node* right_; // 右孩子
};
Node* root_; // 指向BST树的根节点
Compare compare_; // 定义一个函数对象
// 递归前序遍历的实现 VLR
void preOrder(Node* node) {
if (node != nullptr) {
cout << node->data_ << " "; // 操作V
preOrder(node->left_); // 访问左孩子L
preOrder(node->right_); // 访问右孩子R
}
}
// 递归中序遍历实现 LVR
void inOrder(Node* node) {
if (node != nullptr) {
inOrder(node->left_); // 访问左孩子L
cout << node->data_ << " "; // 操作V
inOrder(node->right_); // 访问右孩子R
}
}
// 递归后序遍历 LRV
void postOrder(Node* node) {
if (node != nullptr) {
postOrder(node->left_); // 访问左孩子L
postOrder(node->right_); // 访问右孩子R
cout << node->data_ << " "; // 操作V
}
}
// 递归求二叉树层数
int high(Node* node) {
if (node == nullptr) {
return 0;
}
int left = high(node->left_);
int right = high(node->right_);
return left > right ? left + 1 : right + 1;
}
// 递归求二叉树节点个数
int number(Node* node) {
if (node == nullptr) {
return 0;
}
int left = number(node->left_);
int right = number(node->right_);
return left + right + 1;
}
// 递归层序遍历的实现
void levelOrder(Node* node, int i) {
if (node == nullptr) {
return;
}
// 到了要打印的层数了,
if (i == 0) {
cout << node->data_ << " ";
return;
}
levelOrder(node->left_, i - 1);
levelOrder(node->right_, i - 1);
}
};
int main() {
int arr[] = {58, 24, 67, 0, 34, 62, 69, 5, 41, 64, 78};
BSTree<int> bst;
for (int v : arr) {
bst.n_insert(v);
}
bst.n_insert(12);
bst.n_remove(12);
// 测试查询
cout << bst.n_query(34) << endl;
cout << bst.n_query(99) << endl;
// 测试递归遍历
bst.preOrder();
bst.inOrder();
bst.postOrder();
bst.levelOrder();
return 0;
}
测试结果
中序遍历是从小到大排序的。
递归插入,查询,删除
#include <iostream>
#include <functional>
using namespace std;
// BST树代码实现
template<typename T, typename Compare=less<T>>
class BSTree {
public:
BSTree() : root_(nullptr) {
}
~BSTree() {
}
// 递归前序遍历
void preOrder() {
cout << "[递归前序遍历]";
preOrder(root_);
cout << endl;
}
// 递归中序遍历
void inOrder() {
cout << "[递归中序遍历]";
inOrder(root_);
cout << endl;
}
// 递归后序遍历
void postOrder() {
cout << "[递归后序遍历]";
postOrder(root_);
cout << endl;
}
// 递归层序遍历
void levelOrder() {
cout << "[递归层序遍历]";
int h = high(); // 树的层数
for (int i = 0; i < h; i++) {
levelOrder(root_, i);
}
cout << endl;
}
// 递归求二叉树层数
int high() {
return high(root_);
}
// 递归求二叉树节点个数
int number() {
return number(root_);
}
// 递归插入操作
void insert(const T &val) {
root_ = insert(root_, val);
}
// 递归查询操作
bool query(const T& val) {
return nullptr != query(root_, val);
}
// 递归删除操作
void remove(const T& val) {
root_ = remove(root_, val);
}
private:
// 节点定义
struct Node {
Node(T data = T())
: data_(data)
, left_(nullptr)
, right_(nullptr) {
}
T data_; // 节点的数据域
Node* left_; // 左孩子
Node* right_; // 右孩子
};
Node* root_; // 指向BST树的根节点
Compare compare_; // 定义一个函数对象
// 递归前序遍历的实现 VLR
void preOrder(Node* node) {
if (node != nullptr) {
cout << node->data_ << " "; // 操作V
preOrder(node->left_); // 访问左孩子L
preOrder(node->right_); // 访问右孩子R
}
}
// 递归中序遍历实现 LVR
void inOrder(Node* node) {
if (node != nullptr) {
inOrder(node->left_); // 访问左孩子L
cout << node->data_ << " "; // 操作V
inOrder(node->right_); // 访问右孩子R
}
}
// 递归后序遍历 LRV
void postOrder(Node* node) {
if (node != nullptr) {
postOrder(node->left_); // 访问左孩子L
postOrder(node->right_); // 访问右孩子R
cout << node->data_ << " "; // 操作V
}
}
// 递归求二叉树层数
int high(Node* node) {
if (node == nullptr) {
return 0;
}
int left = high(node->left_);
int right = high(node->right_);
return left > right ? left + 1 : right + 1;
}
// 递归求二叉树节点个数
int number(Node* node) {
if (node == nullptr) {
return 0;
}
int left = number(node->left_);
int right = number(node->right_);
return left + right + 1;
}
// 递归层序遍历的实现
void levelOrder(Node* node, int i) {
if (node == nullptr) {
return;
}
// 到了要打印的层数了,
if (i == 0) {
cout << node->data_ << " ";
return;
}
levelOrder(node->left_, i - 1);
levelOrder(node->right_, i - 1);
}
// 递归插入操作
Node* insert(Node* node, const T &val) {
if (node == nullptr) {
// 递归结束,找到插入val的位置,生成新节点并返回其节点地址
return new Node(val);
}
if (node->data_ == val) {
return node;
} else if (compare_(node->data_, val)) {
// 插入的元素比当前节点的值大,往右边进行插入
node->right_ = insert(node->right_, val);
return node;
} else {
node->left_ = insert(node->left_, val);
return node;
}
}
// 递归查询
Node* query(Node* node, const T& val) {
if (node == nullptr) {
return nullptr;
}
if (node->data_ == val) {
return node;
} else if (compare_(node->data_, val)) {
return query(node->right_, val);
} else {
return query(node->left_, val);
}
}
// 递归删除操作
Node* remove(Node* node, const T& val) {
if (node == nullptr) {
return nullptr;
}
if (node->data_ == val) { // 找到待删除节点
// 有两个孩子
if (node->left_ != nullptr && node->right_ != nullptr) {
// 找前驱结点
Node* pre = node->left_;
while (pre->right_ != nullptr) {
pre = pre->right_;
}
node->data_ = pre->data_;
// 通过递归直接删除前驱节点
node->left_ = remove(node->left_, pre->data_);
} else {
if (node->left_ != nullptr) {
Node* left = node->left_;
delete node;
return left;
} else if (node->right_ != nullptr) {
Node* right = node->right_;
delete node;
return right;
} else {
// 删除的是没有孩子的节点, 删除叶子节点
delete node;
return nullptr;
}
}
} else if (compare_(node->data_, val)) {
node->right_ = remove(node->right_, val);
} else {
node->left_ = remove(node->left_, val);
}
return node; // 把当前节点返回给父节点, 更新父节点相应的地址域
}
};
int main() {
int arr[] = {58, 24, 67, 0, 34, 62, 69, 5, 41, 64, 78};
BSTree<int> bst;
// for (int v : arr) {
// bst.n_insert(v);
// }
for (int v : arr) {
bst.insert(v);
}
// // 测试递归遍历
// bst.preOrder();
// bst.inOrder();
// bst.postOrder();
// bst.levelOrder();
// 测试递归查询
// cout << bst.query(58) << endl;
bst.remove(24);
return 0;
}
测试删除结果
非递归前序遍历,中序遍历,后续遍历,层序遍历
#include <iostream>
#include <functional>
#include <stack>
#include <queue>
using namespace std;
// BST树代码实现
template<typename T, typename Compare=less<T>>
class BSTree {
public:
BSTree() : root_(nullptr) {
}
~BSTree() {
}
// 非递归插入操作
void n_insert(const T &val) {
if (root_ == nullptr) { // 树为空, 生成根节点
root_ = new Node(val);
return;
}
// 从根节点往下找,为了找到合适的parent
Node* parent = nullptr;
Node* cur = root_;
while (cur != nullptr) {
if (cur->data_ == val) {
return; // 相等,不插入相同值
} else if (compare_(cur->data_, val)) {
// 插入的值大于节点元素值,往右走
parent = cur;
cur = cur->right_;
} else {
// 插入的值小于节点元素值,往左走
parent = cur;
cur = cur->left_;
}
}
// 把新节点插入到parent节点的孩子上
if (compare_(parent->data_, val)) { // 比较插入的值与parant的大小后进行插入
parent->right_ = new Node(val);
} else {
parent->left_ = new Node(val);
}
}
// 非递归前序遍历, 借助一个栈
void n_preOrder() {
cout << "[非递归前序遍历]";
if (root_ == nullptr) {
return;
}
stack<Node*> s;
s.push(root_);
while (!s.empty()) {
Node* top = s.top();
s.pop();
cout << top->data_ << " "; // V处理了
if (top->right_ != nullptr) {
s.push(top->right_); // 入栈R
}
if (top->left_ != nullptr) {
s.push(top->left_); // 入栈L, 后入栈的先访问
}
}
cout << endl;
}
// 非递归中序遍历
void n_inOrder() {
cout << "[非递归中序遍历]";
if (root_ == nullptr) {
return;
}
stack<Node*> s;
Node* cur = root_;
while (cur != nullptr) {
s.push(cur);
cur = cur->left_;
}
while (!s.empty()) {
Node* top = s.top();
s.pop();
cout << top->data_ << " ";
cur = top->right_;
while (cur != nullptr) {
s.push(cur);
cur = cur->left_;
}
}
cout << endl;
}
// 非递归后续遍历
// 使用两个栈,LRV遍历的方式转为VRL, 最后使用一个栈将VRL转为LRV
void n_postOrder() {
cout << "[非递归后续遍历]";
if (root_ == nullptr) {
return;
}
stack<Node*> s1;
stack<Node*> s2;
s1.push(root_);
while (!s1.empty()) {
Node* top = s1.top();
s1.pop();
s2.push(top); // V
if (top->left_ != nullptr) {
s1.push(top->left_); // L
}
if (top->right_ != nullptr) {
s1.push(top->right_); // R
}
}
// 栈2打印出来即是LRV
while (!s2.empty()) {
cout << s2.top()->data_ << " ";
s2.pop();
}
cout << endl;
}
// 非递归层序遍历
// 使用一个队列queue
void n_levelOrder() {
cout << "[非递归层序遍历]";
if (root_ == nullptr) {
return;
}
queue<Node*> que;
que.push(root_);
while (!que.empty()) {
Node * front = que.front();
que.pop();
cout << front->data_ << " ";
if (front->left_ != nullptr) {
que.push(front->left_);
}
if (front->right_ != nullptr) {
que.push(front->right_);
}
}
cout << endl;
}
private:
// 节点定义
struct Node {
Node(T data = T())
: data_(data)
, left_(nullptr)
, right_(nullptr) {
}
T data_; // 节点的数据域
Node* left_; // 左孩子
Node* right_; // 右孩子
};
Node* root_; // 指向BST树的根节点
Compare compare_; // 定义一个函数对象
};
int main() {
int arr[] = {58, 24, 67, 0, 34, 62, 69, 5, 41, 64, 78};
for (int v : arr) {
bst.n_insert(v);
}
// 测试非递归查询
bst.n_preOrder();
bst.n_inOrder();
bst.n_postOrder();
bst.n_levelOrder();
return 0;
}