#include <iostream>
using namespace std;
template<class T>
class Node
{
public:
T m_Value;
Node* left;
Node* right;
public:
Node() : m_Value(T()), left(nullptr), right(nullptr) {};
Node(const T& value) :m_Value(value), left(nullptr), right(nullptr) {};
};
//插入节点
template<class T>
void insertHelper(Node<T>* node, const T& value)
{
Node<T>* newNode = new Node<T>(value);
//根节点为空,新节点即为根节点
if (node == nullptr)
{
node = newNode;
return;
}
if (value < node->m_Value)
{
insertHelper(node->left, value);
}
else if (value > node->m_Value)
{
insertHelper(node->right, value);
}
else
{
cout << "节点已存在。" << endl;
return;
}
}
//搜索节点
template<class T>
void searchNode(Node<T>* node, const T& value)
{
if (node == nullptr)
{
cout << "未找到。" << endl;
return;
}
if (value < node->m_Value)
{
searchNode(node->left, value);
}
else if (value > node->m_Value)
{
searchNode(node->right, value);
}
else
{
cout << "find it:" << node->m_Value << endl;
}
}
//删除节点
template<class T>
void deleteNode(Node<T>* tree, const T& value)
{
if (tree == nullptr)
{
cout << "未找到要删除的节点。" << endl;
return;
}
//定义三个节点,待删节点,待删节点的父节点,根节点的临时节点
//要定义一个根节点的临时节点是因为我们可能会对根节点进行操作,这样会改变结构
//当别人要进行操作的时候会发现树已经变了
Node<T>* node = NULL, * parent = NULL, * temp = tree;//这里的temp其实就是根节点
while (temp != nullptr)
{
if (temp->m_Value == value)
{
node = temp;
break;
}
//当前节点为父节点,向其子节点查找
parent = temp;
if (value < temp->m_Value)
{
temp = temp->left;
}
else
{
temp = temp->right;
}
}
//现在node就是找到的那个节点,但可能没找到,初始定义没变 为空
if (node == nullptr)
{
cout << "not find." << endl;
return;
}
//找到不为空的node节点了。分三种情况
//1. 该节点为叶子节点,即没有左右子节点,这个时候直接删掉
if (node->left == nullptr && node->right == nullptr)
{
if (parent == nullptr) //这种情况就是只有一个根节点
{
delete node;
cout << "删除成功。" << endl;
return;
}
if (parent->left == node)
{
parent->left = nullptr;
}
else
{
parent->right = nullptr;
}
delete node;
cout << "删除成功。" << endl;
return;
}
//2.该节点只有左子节点
//这是需要定义一个待删节点的子节点
Node<T>* subNode = NULL;
if (node->right == NULL)
{
subNode = node->left;
if (parent != NULL)
{
if (parent->left == node)
{
parent->left = subNode;
}
else
{
parent->right = subNode;
}
delete node;
cout << "删除成功。" << endl;
return;
}
else //父节点为空,也就是说要删除的是根节点
{
delete node;
tree = subNode;
cout << "删除成功。" << endl;
return;
}
}
//3. 该节点只有右子节点
else if (node->left == NULL)
{
subNode = node->right;
if (parent != NULL)
{
if (parent->left == node)
{
parent->left = subNode;
}
else
{
parent->right = subNode;
}
}
delete node;
cout << "删除成功。" << endl;
return;
}
//4.该节点左右子节点都有
if (node->left != nullptr && node->right != nullptr)
{
//查找前驱节点,以及前驱结点的父节点
Node<int>* replacer = node, * rpcParent = parent;
//temp用不到了,在这里拿来查找前驱节点用
temp = node->left;
while (temp != nullptr)
{
rpcParent = replacer;
replacer = temp;
temp = temp->right;
}
//循环后,此时replacer是待删除节点node的前驱
//rpcParent是前驱的父节点,temp为空不需要了
//删除操作
T value = replacer->m_Value;
deleteNode(rpcParent, replacer->m_Value);
node->m_Value = value;
//cout << "删除成功。" << endl;
return;
}
}
//前序遍历
template<class T>
void preOrderTravel(Node<T>* node)
{
if (node != NULL)
{
cout << node->m_Value << " ";
preOrderTravel(node->left);
preOrderTravel(node->right);
}
}
//中序遍历
template<class T>
void inOrderTravel(Node<T>* node)
{
if (node != NULL)
{
inOrderTravel(node->left);
cout << node->m_Value << " ";
inOrderTravel(node->right);
}
}
//后序遍历
template<class T>
void postOrderTravel(Node<T>* node)
{
if (node != NULL)
{
postOrderTravel(node->left);
postOrderTravel(node->right);
cout << node->m_Value << " ";
}
}
void test01()
{
//BinaryTree<int> tree;
//定义一个根节点也就是一棵树
Node<int>* root = new Node<int>(10);
Node<int>* node5 = new Node<int>(5);
Node<int>* node16 = new Node<int>(16);
Node<int>* node2 = new Node<int>(2);
Node<int>* node7 = new Node<int>(7);
Node<int>* node1 = new Node<int>(1);
Node<int>* node4 = new Node<int>(4);
Node<int>* node6 = new Node<int>(6);
Node<int>* node9 = new Node<int>(9);
root->left = node5; root->right = node16;
node5->left = node2; node5->right = node7;
node2->left = node1; node2->right = node4;
node7->left = node6; node7->right = node9;
//树的实际结构
// 10
// 5 16
// 2 7
// 1 4 6 9
cout << "前序遍历:" << endl;
preOrderTravel(root);
cout << endl;
cout << "中序遍历:" << endl;
inOrderTravel(root);
cout << endl;
cout << "后序遍历:" << endl;
postOrderTravel(root);
cout << endl;
//searchNode(root, 2);
deleteNode(root, 5);
cout << "删除节点5之后的中序遍历:" << endl;
inOrderTravel(root);
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
结合教材和视频课整理的,删除部分可以简化很多,主要还是看自己的逻辑思路