VS2015可直接运行
//因为二叉查找树的平均深度为O(logN),所以一般不用担心栈空间被用尽
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
//二叉树查找结构(有序):
//*SearchTree根节点用来表示整个二叉查找树
//*Position用来表示某一个结点
typedef struct TreeNode
{
int Element;
TreeNode* Left;
TreeNode* Right;
}*SearchTree, *Position;
SearchTree makeEmpty(SearchTree T);//讲树置为空树
Position find(int x, SearchTree T);
Position findMin(SearchTree T);
Position findMax(SearchTree T);
SearchTree insert(int x, SearchTree T);
SearchTree deleteTreeEle(int x, SearchTree T);
SearchTree creatSearchTree(int* arr, int len);
void preOrderTraverse(SearchTree T);
void inOrderTraverse(SearchTree T);
/*
创建一颗空树
使用递归的方式由下到上将树中的每一个点释放空间,
返回NULL。可以初始化一个单节点,这里使用递归更遵循树的定义。
*/
SearchTree makeEmpty(SearchTree T)
{
if (T != NULL)
{
if (T->Left != NULL)
makeEmpty(T);//一直在对T操作,无需return!
if (T->Right != NULL)
makeEmpty(T);
}
return NULL;
}
//利用查找树的特点
/*
二叉查找树的find操作
使用递归的方式查找元素x,若树T为空,则返回NULL,
若元素x比当前元素小,则递归向该元素节点的左子树查找,
若元素x比当前元素大,则递归向该元素节点的右子树查找,
最后返回查找到的元素x位置。
*/
Position find(int x, SearchTree T)
{
if (T == NULL)
return T;
else
{
if (x == T->Element)
return T;
else if (x < T->Element)
return find(x, T->Left);
else
return find(x, T->Right);
}
}
/*
二叉查找树的find_min操作
因为二叉排序树是有序的,所以只需要递归的查找左子树,
如果树为空,返回NULL,如果树根不为空,根的左子树为空,返回根T,
否则递归的在根的左子树中查找,返回递归到最后的根元素。
*/
//只需看三个节点,父和左右儿子,其他的遍历
Position findMin(SearchTree T)
{
if (T == NULL)
return NULL;
if (T->Left == NULL)
return T;
else
return findMin(T);
}
/*
二叉查找树的find_max操作,
使用非递归的方式进行查找。
*/
Position findMax(SearchTree T)
{
if (NULL != T)
{
while (NULL != T->Right)
T = T->Right;
}
return T;
}
/*
插入元素到二叉查找树中
返回为根节点,因为如果树根为空的话需要插入创建一个节点并返回,
可以把插入想象为find操作,发现不做或做些更新,否则插入路径上最后一点。
*/
SearchTree insert(int x, SearchTree T)
{
if (T == NULL)//若树为空树,需要分配节点空间并初始化,递归基准
{
T = new TreeNode;
T->Element = x;
T->Left = NULL, T->Right = NULL;
}
else
{
if (x < T->Element)//若插入元素x比当前节点小,则递归的在其左子树查找
T->Left = insert(x, T->Left);//最后一点
else if (x > T->Element)
T->Right = insert(x, T->Right);
}
return T;
}
/*
二叉查找树的删除例程,查找到元素x的节点
若要删除节点是一片树叶,则立即删除,若要删除节点有一个儿子可以在其父节点调整指针删除,
若要删除有两个二个儿子,则用其右子树最小的节点代替该节点并将右子树删除。
*/
SearchTree deleteTreeEle(int x, SearchTree T)
{
if (T == NULL)
{
cout << "空树不能删除,退出程序" << endl;
exit(-1);
}
else if (x < T->Element)
{ //若该树不为空且当前节点元素比元素x大
//则递归到该节点的左子树中进行删除
T->Left = deleteTreeEle(x, T->Left);
}
else if (x > T->Element)
{
T->Right = deleteTreeEle(x, T->Right);
}
else if (T->Left && T->Right)//暗含了x == T->Element
{ //若找到要删除的节点且该节点有两个孩子
//则将该节点右子树元素值最小的节点赋值给该节点
//同时将右子树最小的节点删除释放空间
Position rightMin = findMin(T->Right);
T->Element = rightMin->Element;
T->Right = deleteTreeEle(T->Element, T->Right);
}
else//暗含了x == T->Element
{ //若找到要删除的节点且该节点有一个个孩子或者没有孩子
//则移动该节点指针到左右节点相当于父节点指向了该节点,释放该节点空间
SearchTree tempCell = T;
if (T->Left == NULL)
T = T->Right;
else if (T->Right == NULL)
T = T->Left;
delete tempCell;
}
return T;
}
SearchTree creatSearchTree(int * arr, int len)
{
SearchTree T = nullptr;//0x00000000,这个地址不存内容
for (int i = 0; i < len; i++)
{
cout << *(arr + i) << " ";
T = insert(*(arr + i), T);
}
return T;
}
//中序遍历:左根右
void inOrderTraverse(SearchTree T)
{
if (T != NULL)
{
inOrderTraverse(T->Left);
cout << T->Element << " ";
inOrderTraverse(T->Right);
}
}
//先序遍历:根左右
void preOrderTraverse(SearchTree T)
{
if (T != NULL)
{
cout << T->Element << "";
preOrderTraverse(T->Left);
preOrderTraverse(T->Right);
}
}
//使用数组初始化构造一棵树,利用中序遍历和先序遍历验证是否是二叉排序树
int main()
{
int num = 0;
cout << "输入查找树结点个的数:";
cin >> num;
int *arr = new int[num*sizeof(int)];
for (int i = 0; i < num; i++)
{
arr[i] = (rand()%(num*2));//随机生成0-num*2之间的数字
}
SearchTree T = creatSearchTree(arr, num);
cout << "中序遍历该二叉排序树的结果:" << endl;
inOrderTraverse(T);
int key = 0;
cout << "输入要查找的整数:";
cin >> key;
Position p = find(key, T);
if (p)
cout << "查找成功" << endl;
else
cout << "查找失败" << endl;
cout << "输入要插入的整数:";
cin >> key;
T = insert(key, T);
if (T)
{
cout << "插入成功,插入后的中序遍历结果:";
inOrderTraverse(T);
cout << endl;
}
else
cout << "插入失败,该二叉排序树中不存在整数" << key << endl;
cout << "输入要删除的整数:";
cin >> key;
T = deleteTreeEle(key, T);
if (T)
{
cout << "删除成功,删除后的中序遍历结果:";
inOrderTraverse(T);
cout << endl;
}
else
cout << "删除失败,该二叉排序树中不存在整数" << key << endl;
system("pause");
return 0;
}