难点:二叉查找树的删除
二叉查找树
概念:
二叉查找树:要么为空树,若二叉查找树不为空,则需要满足以下性质:
(1)左子树上所有的节点值均小于或等于其根结点的值。
(2)右子树上所有的节点值均大于或等于其根结点的值。
(3)左右子树也一定分别为二叉查找树。
特点:
(1)将数据分为左右子树两部分,加快了查找的速度。
(2)中序遍历的结果为有序的。
优点:
(1)查找的时间复杂度为O(logN)。
(2)一般情况下,插入和删除的时间复杂度为O(logN)。
缺点:
(1)二叉排序树的构建和数据的输入顺序有极大的关系,如果输入为有序,二叉排序树将退化为线性结构,导致查找的时间复杂度降为O(N)。
举例:
数据序列:5,8,3,2,4,1,6,7,9
这样在查找是就将数据分为两部分进行查找,时间复杂度为O(logN)。
数据序列:1,2,3,4,5
如果数据本身有序,那么二叉排序树将退化为线性结构。
二叉查找树C++实现
二叉查找树的操作有:创建、添加、删除、销毁等基本操作,其他操作都比较简单,只有删除比较复杂。
二叉查找树的删除:
(1)待删除的节点为叶子节点时:将父节点对应的子节点的指针置空。
(2)待删除的节点只有左子树/右子树时:将父节点对应子节点的指针置为待删除节点的子节点。
(3)待删除的节点既有左子树又有右子树时:将左子树中最右节点\右子树最左节点和待删除节点交换,之后删除待删除节点。
BinarySearchTree.h文件:
#ifndef Binary_Search_Tree
#define Binary_Search_Tree
#include <iostream>
using namespace std;
//树的节点的类型
typedef int DataType;
//数据的节点
struct TreeNode
{
DataType data;
struct TreeNode* left;
struct TreeNode* right;
};
//二叉排序树的数据结构
class BinarySearchTree
{
public:
BinarySearchTree();
~BinarySearchTree();
TreeNode* createBSTree(DataType* dataList,int length);//创建二叉排序树
void inorderTraversal(TreeNode* node);//二叉排序树的中序遍历
void addTreeNode(DataType data);//给树添加新的节点
void delTreeNode(DataType data);//删除树中的节点
TreeNode* findTreeNode(DataType data);//查询
void desTree(TreeNode* node);//销毁树
TreeNode* getTreeRoot();
private:
TreeNode* treeRoot;//树根
};
typedef BinarySearchTree BST;
#endif
//BinarySearchTree.cpp
#include "BinarySearchTree.h"
BST::BinarySearchTree()
{
treeRoot = NULL;
}
BST::~BinarySearchTree()
{
desTree(treeRoot);
}
TreeNode* BST::createBSTree(DataType* dataList,int length)
{
treeRoot = new TreeNode();
treeRoot->data = dataList[0];
treeRoot->left = NULL;
treeRoot->right = NULL;
for (int i = 1; i < length; ++i)
{
addTreeNode(dataList[i]);
}
return treeRoot;
}
void BST::addTreeNode(DataType data)
{
TreeNode* newNode = new TreeNode();
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
TreeNode* node = treeRoot;
while (1)
{
//如果新结点的值大于根结点的值,则在右子树。
if (newNode->data >= node->data)
{
//若右子树为空,这直接插入
if (node->right == NULL)
{
node->right = newNode;
break;
}
//不为空,则继续判断。
else
{
node = node->right;
}
}
//否则在左子树上。
else
{
if (node->left == NULL)
{
node->left = newNode;
break;
}
else
{
node = node->left;
}
}
}
}
void BST::inorderTraversal(TreeNode* node)
{
if (node != NULL)
{
inorderTraversal(node->left);
cout << node->data << ",";
inorderTraversal(node->right);
}
}
void BST::desTree(TreeNode* node)
{
if (node != NULL)
{
desTree(node->left);
desTree(node->right);
delete [] node;
node = NULL;
}
}
TreeNode* BST::findTreeNode(DataType data)
{
TreeNode* node = treeRoot;
while (node)
{
if (node->data == data)
{
return node;
}
else if (node->data < data)
{
node = node->right;
}
else
{
node = node->left;
}
}
return node;
}
void BST::delTreeNode(DataType data)
{
TreeNode* node = treeRoot;//待删除节点的值
TreeNode* parNode = NULL;//待删除节点的父节点
while (node)
{
if (node->data == data)
{
//(1)叶子结点
if (node->left == NULL && node->right == NULL)
{
//根结点
if (parNode == NULL)
{
treeRoot = NULL;
}
else
{
(node == parNode->left) ? parNode->left = NULL : parNode->right = NULL;
}
delete[] node;
node = NULL;
}
//(2)只有左/右子树
else if (node->left == NULL || node->right == NULL)
{
//根节点
if (parNode == NULL)
{
(node->left == NULL) ? treeRoot = node->right : treeRoot = node->left;
}
else
{
if (parNode->left == node)
{
(node->left == NULL) ? parNode->left = node->right : parNode->left = node->left;
}
else
{
(node->right == NULL) ? parNode->right = node->right : parNode->right = node->left;
}
}
delete[] node;
node = NULL;
}
//(3)既有左子树,又有右子树
else
{
//寻找左子树的最右节点作为替换节点
TreeNode* replaceNode = node->left;
while (replaceNode->right)
{
replaceNode = replaceNode->right;
}
//保存替换节点的值
DataType tempData = replaceNode->data;
//删除replaceNode节点
delTreeNode(tempData);
replaceNode = NULL;
//替换值域
node->data = tempData;
}
break;
}
else
{
parNode = node;
if (data < node->data)
{
node = node->left;
}
else
{
node = node->right;
}
}
}
}
TreeNode* BST::getTreeRoot()
{
return treeRoot;
}
Main.cpp
#include "BinarySearchTree.h"
int main()
{
BST bsTree;
DataType dataArr[] = { 5, 8, 3, 2, 4, 1, 6, 7, 9 };
TreeNode* treeNode = bsTree.createBSTree(dataArr, sizeof(dataArr) / sizeof(dataArr[0]));
//bsTree.addTreeNode(10);
//bsTree.addTreeNode(9);
//bsTree.addTreeNode(11);
bsTree.delTreeNode(5);
bsTree.inorderTraversal(bsTree.getTreeRoot());
cout << endl;
bsTree.delTreeNode(3);
bsTree.inorderTraversal(bsTree.getTreeRoot());
cout << endl;
bsTree.delTreeNode(8);
bsTree.inorderTraversal(bsTree.getTreeRoot());
cout << endl;
return 0;
}
以上代码如存在错误,请及时留言,谢谢。
数据结构可视化网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html