查找问题:
- 静态查找与动态查找
- 针对动态查找,数据如何组织?
利用二叉搜索树可以实现高效的动态查找
二叉搜索树操作的特别函数:
- Position Find( ElementType X, BinTree BST ):从二叉搜索树BST 中查找元素X,返回其所在结点的地址;
- Position FindMin( BinTree BST ):从二叉搜索树BST中查找并返回 最小元素所在结点的地址;
- Position FindMax( BinTree BST ) :从二叉搜索树BST中查找并返回 最大元素所在结点的地址。
- BinTree Insert( ElementType X, BinTree BST )
- BinTree Delete( ElementType X, BinTree BST )
查找的效率决定于树的高度
特别值得注意的是插入与删除操作:
插入
找到结点的方法与查找相似,到是要特别注意与查找之间的区别!
BinTree Insert(BinTree BST, int X)
{
if (!BST) {/*若原树为空,生成并返回一个结点的二叉搜索树*/
BST = new struct TreeNode;
BST->data = X;
BST->Left = BST->Right = NULL;
}
else {/*开始找要插入元素的位置*/
if (X < BST->data)
BST->Left = Insert(BST->Left, X); /*递归插入左子树*/
else if (X > BST->data)
BST->Right = Insert(BST->Right, X);/*递归插入右子树*/
/*else X已经存在,什么都不做*/
/*这里与查找不同,存在一个将新插入结点与树接上的过程*/
}
return BST;
}
不是直接return Insert( 。。。,。);
而是BST->。。。= Insert(。。。,。);
删除
考虑三种情况:
1、要删除的是叶结点:直接删除,并再修改其父结点指针---置为NUL
2、要删除的结点只有一个孩子结点: 将其父结点的指针指向要删除结点的孩子结点
3、要删除的结点有左、右两棵子树: 用另一结点替代被删除结点:右子树的最小元素 或者 左子树的最大元素
完整代码:
#include <iostream>
using namespace std;
typedef struct TreeNode* BinTree;
struct TreeNode {
int data;
BinTree Left;
BinTree Right;
};
void CreatBinTree(BinTree& T)
{
int ch;
cin >> ch;
if (ch == -1) T = NULL;
else {
T = new struct TreeNode;
T->data = ch;
CreatBinTree(T->Left);
CreatBinTree(T->Right);
}
return;
}
void PreOrderTraversal(BinTree BT)
{
if (BT)
{
cout << BT->data<<" ";
PreOrderTraversal(BT->Left);
PreOrderTraversal(BT->Right);
}
}
//---------------------------------------------------------------------------------------------------------------------
BinTree Find(int X, BinTree BST)
{
while (BST)
{
if (X == BST->data) return BST;
else if (X > BST->data)
BST = BST->Right;
else BST = BST->Left;
}
return NULL;
}
/*
递归写法:
BinTree Find(int X, BinTree BST)
{
if (!BST) return NULL;
if (X < BST->data)
return Find(X, BST->Left);
else if (X < BST->data)
return Find(X, BST->Right);
else return BST;
}
*/
BinTree FindMin(BinTree BST)
{
if(BST)
while (BST->Left) BST = BST->Left;
return BST;
}
BinTree FindMax(BinTree BST)
{
if (!BST) return NULL; //树空
else if (!BST->Right) return BST; //找到最右子树
else return FindMax(BST->Right); //继续找
}
BinTree Insert(BinTree BST, int X)
{
if (!BST) {/*若原树为空,生成并返回一个结点的二叉搜索树*/
BST = new struct TreeNode;
BST->data = X;
BST->Left = BST->Right = NULL;
}
else {/*开始找要插入元素的位置*/
if (X < BST->data)
BST->Left = Insert(BST->Left, X); /*递归插入左子树*/
else if (X > BST->data)
BST->Right = Insert(BST->Right, X);/*递归插入右子树*/
/*else X已经存在,什么都不做*/
/*这里与查找不同,存在一个将新插入结点与树接上的过程*/
}
return BST;
}
BinTree Delete(int X, BinTree BST)
{
BinTree tmp;
if (!BST) cout << "要删除的元素未找到";
else if (X < BST->data)
BST->Left = Delete(X, BST->Left);
else if (X > BST->data)
BST->Right = Delete(X, BST->Right);
else/*找到了要删除的结点*/
if (BST->Left && BST->Right) {/*被删除的结点有左右两个子树*/
tmp = FindMin(BST->Right);
/*在右子树中找到最小元素填充删除结点*/
BST->data = tmp->data;
BST->Right = Delete(BST->data, BST->Right);
/*在删除结点的右子树中删除最小元素*/
}
else {/*被删除的结点有一个或无子结点*/
tmp = BST;
if (!BST->Left)
BST = BST->Right;
else if (!BST->Right)
BST = BST->Left;
delete tmp;
}
return BST;
}
int main()
{
BinTree t;
/*输入:10 8 7 -1 -1 9 -1 -1 12 -1 -1*/
CreatBinTree(t);
Find(12, t);
Insert(t, 32);
PreOrderTraversal(t);
cout << endl;
Delete(12, t);
PreOrderTraversal(t);
cout << endl;
return 0;
}