基于我的另一篇文章《算法与数据结构基础4:C++二叉树实现及遍历方法大全》 ,二叉树的结构用的这篇文章里的。
二查找叉树的删除可以细分为三种情况:
1 被删除的是叶子节点,直接删除;
2 被删除只有一个子节点,指针下移;
3 有两个子节点,为了不破坏树的结构,需要找出一个节点来替换当前节点。
根据二叉树的特点,当前节点大于所有左子树,小于所有右子树,
可以用左子树中最大的节点,或者右子树最小的节点来替换当前节点,然后删除替换节点。
// BSTree.h
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
// binary search tree,中文翻译为二叉搜索树、二叉查找树或者二叉排序树。简称为BST
class BSTree
{
struct Node{
Node(int x = 0):data(x), lchild(NULL), rchild(NULL){}
struct Node* lchild;
struct Node* rchild;
int data;
};
public:
// **************************************************************************
// 类的四大函数:构造函数、拷贝构造函数、重载赋值运算符、析构函数
// **************************************************************************
BSTree();
~BSTree();
// **************************************************************************
// 增删改查
// **************************************************************************
void Insert(int x);
void Remove(int x);
// 返回二叉树的个数
unsigned short Size();
unsigned short Deep();
unsigned short Leaf();
bool IsEmpty();
// 遍历
void PreorderTraversal(); // 先序遍历
void InorderTraversal(); // 中序遍历
void PostorderTraversal(); // 后序遍历
void DepthFirstSearch(); // 深度优先遍历
void BreadthFirstSearch(); // 广度优先遍历
private:
void Remove(int x, Node** pNode);
// 递归计算二叉树个数
unsigned short CountSize(Node* n);
unsigned short CountDeep(Node* n);
unsigned short CountLeaf(Node* n);
// 递归遍历
void PreorderTraversal(Node* n);
void InorderTraversal(Node* n);
void PostorderTraversal(Node* n);
void DepthFirstSearch(Node* n);
void BreadthFirstSearch(Node* n);
void Free(Node* node);
private:
Node* m_root;
};
// **************************************************************************
// 私有方法
// **************************************************************************
/*
//1 请问下面这份代码有什么问题?
void BSTree::Remove(int x, Node* node)
{
if (!node) {
return;
}
if (x < node->data) {
Remove(x, node->lchild);
}
else if (x > node->data){
Remove(x, node->rchild);
}
else if (node->lchild && node->rchild) {
Node* min = node->rchild;
while(min->lchild){
min = min->lchild;
}
node->data = min->data;
Remove(node->data, node->rchild);
}
else{
Node* tmp = node;
if(node->lchild){
node = node->lchild;
}
else if (node->rchild){
node = node->rchild;
}
else{
node = NULL;
}
delete tmp;
tmp = NULL;
}
}
node是一个局部变量,对node的操作除delete之外都不会生效
// 2 再问,下面的代码有什么问题?
void BSTree::Remove(int x, Node** pNode)
{
if (!pNode || !(*pNode)) {
return;
}
Node* node = *pNode;
if (x < node->data) {
Remove(x, node->lchild);
}
else if (x > node->data){
Remove(x, node->rchild);
}
else if (node->lchild && node->rchild) {
Node* min = node->rchild;
while(min->lchild){
min = min->lchild;
}
node->data = min->data;
Remove(node->data, node->rchild);
}
else{
Node* tmp = node;
if(node->lchild){
node = node->lchild;
}
else if (node->rchild){
node = node->rchild;
}
else{
node = NULL;
}
delete tmp;
tmp = NULL;
}
}
同样的问题,虽然这里传递的参数是指针,但是Node* node = *pNode;发生了拷贝。
*/
void BSTree::Remove(int x, Node** pNode)
{
if (!pNode || !(*pNode)) {
return;
}
if (x < (*pNode)->data) {
Remove(x, &((*pNode)->lchild));
}
else if (x > (*pNode)->data){
Remove(x, &((*pNode)->rchild));
}
else if ((*pNode)->lchild && (*pNode)->rchild) {
Node* min = (*pNode)->rchild;
while(min->lchild){
min = min->lchild;
}
(*pNode)->data = min->data;
Remove((*pNode)->data, &((*pNode)->rchild));
}
else{
Node* tmp = *pNode;
if((*pNode)->lchild){
(*pNode) = (*pNode)->lchild;
}
else if ((*pNode)->rchild){
*pNode = (*pNode)->rchild;
}
else{
*pNode = NULL;
}
delete tmp;
tmp = NULL;
}
}
unsigned short BSTree::CountSize(Node* n)
{
if(!n){
return 0;
}
return CountSize(n->lchild) + CountSize(n->rchild) + 1;
}
unsigned short BSTree::CountDeep(Node* n)
{
if (!n) {
return 0;
}
int ldeep = CountDeep(n->lchild);
int rdeep = CountDeep(n->rchild);
return ( ldeep > rdeep ) ? (ldeep + 1) : (rdeep + 1);
}
unsigned short BSTree::CountLeaf(Node* n)
{
if (!n){
return 0;
}
if (!n->lchild&& !n->rchild){
return 1;
}
return CountLeaf(n->lchild) + CountLeaf(n->rchild);
}
void BSTree::PreorderTraversal(Node* n)
{
if (n) {
cout << n->data << ",";
PreorderTraversal(n->lchild);
PreorderTraversal(n->rchild);
}
}
void BSTree::InorderTraversal(Node* n)
{
if (n) {
InorderTraversal(n->lchild);
cout << n->data << ",";
InorderTraversal(n->rchild);
}
}
void BSTree::PostorderTraversal(Node* n)
{
if (n) {
PostorderTraversal(n->lchild);
PostorderTraversal(n->rchild);
cout << n->data << ",";
}
}
void BSTree::DepthFirstSearch(Node* root)
{
stack<Node *> nodeStack;
nodeStack.push(root);
Node* node = NULL;
while(!nodeStack.empty()){
node = nodeStack.top();
cout << node->data << ",";
nodeStack.pop();
if (node->rchild) {
nodeStack.push(node->rchild);
}
if (node->lchild) {
nodeStack.push(node->lchild);
}
}
}
void BSTree::BreadthFirstSearch(Node* root)
{
queue<Node *> nodeQueue;
nodeQueue.push(root);
Node* node = NULL;
while(!nodeQueue.empty()){
node = nodeQueue.front();
nodeQueue.pop();
cout << node->data << ",";
if (node->lchild) {
nodeQueue.push(node->lchild);
}
if (node->rchild) {
nodeQueue.push(node->rchild);
}
}
}
void BSTree::Free(Node* n)
{
if (n) {
Free(n->lchild);
Free(n->rchild);
delete n;
n = NULL;
}
}
// **************************************************************************
// 类的四大函数:构造函数、拷贝构造函数、重载赋值运算符、析构函数
// **************************************************************************
BSTree::BSTree()
{
m_root = NULL;
}
BSTree::~BSTree()
{
Free(m_root);
}
// **************************************************************************
// 增删改查
// **************************************************************************
void BSTree::Insert(int x)
{
Node* tmp = new Node(x);
if (!m_root){
m_root = tmp;
}
else{
Node* pre = m_root;
Node* cur = m_root;
while (cur){
pre = cur;
cur = (x < cur->data) ? (cur->lchild) : (cur->rchild);
}
(x < pre->data) ? (pre->lchild = tmp) : (pre->rchild = tmp);
}
}
void BSTree::Remove(int x)
{
if (!m_root){
return;
}
Remove(x, &m_root);
}
unsigned short BSTree::Size()
{
return CountSize(m_root);
}
unsigned short BSTree::Deep()
{
return CountDeep(m_root);
}
unsigned short BSTree::Leaf()
{
return CountLeaf(m_root);
}
bool BSTree::IsEmpty()
{
return m_root == NULL;
}
void BSTree::PreorderTraversal()
{
PreorderTraversal(m_root);
cout << endl;
}
void BSTree::InorderTraversal()
{
InorderTraversal(m_root);
cout << endl;
}
void BSTree::PostorderTraversal()
{
PostorderTraversal(m_root);
cout << endl;
}
void BSTree::DepthFirstSearch()
{
DepthFirstSearch(m_root);
cout << endl;
}
void BSTree::BreadthFirstSearch()
{
BreadthFirstSearch(m_root);
cout << endl;
}
// main.cpp
// test for BSTree
#include "BSTree.h"
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
BSTree tree;
int arr[6] = {5, 4, 8, 1, 7, 10};
for (int i = 0; i < 6; ++i){
tree.Insert(arr[i]);
}
tree.PreorderTraversal();
tree.InorderTraversal();
tree.PostorderTraversal();
tree.DepthFirstSearch();
tree.BreadthFirstSearch();
tree.Remove(4);
tree.PreorderTraversal();
tree.Remove(1);
tree.PreorderTraversal();
tree.Remove(10);
tree.PreorderTraversal();
cout << "size:" << tree.Size() << endl;
cout << "deep:" << tree.Deep() << endl;
cout << "leaf:" << tree.Leaf() << endl;
system("pause");
return 0;
}
// 树的结构
// 运行结果截图