二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。
其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:
①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
③左、右子树本身又各是一棵二叉排序树。
输入序列决定了二叉排序树的形态。
二叉排序树的中序序列是一个有序序列。所以对于一个任意的关键字序列构造一棵二叉排序树,其实质是对此关键字序列进行排序,使其变为有序序列。"排序树"的名称也由此而来。通常将
这种排序称为树排序(Tree Sort),可以证明这种排序的平均执行时间亦为O(nlgn)。
对相同的输入实例,树排序的执行时间约为堆排序的2至3倍。因此在一般情况下,
构造二叉排序树的目的并非为了排序,而是用它来加速查找,这是因为在一个有序的集合上查找通常比在无序集合上查找更快。
因此,人们又常常将二叉排序树称为二叉查找树。
#include <iostream>
#include <stdio.h>
#include<stack>
#include<string>
using namespace std;
typedef struct Node
{
char data;
struct Node *left;
struct Node *right;
}*pNode;
void pre_show(Node *pRoot)//递归前序遍历二叉树
{
if(pRoot)
{
std::cout<<pRoot->data<<" ";
pre_show(pRoot->left);
pre_show(pRoot->right);
}
}
void mid_show(Node *pRoot)//中序遍历二叉树
{
if(pRoot)
{
mid_show(pRoot->left);
std::cout<<pRoot->data<<" ";
mid_show(pRoot->right);
}
}
void back_show(Node *pRoot)//后序遍历二叉树
{
if(pRoot)
{
back_show(pRoot->left);
back_show(pRoot->right);
std::cout<<pRoot->data<<" ";
}
}
void create_sort_tree(pNode& pRoot, char val)
{
if(NULL == pRoot)
{
pRoot = new Node;
pRoot->left = NULL;
pRoot->right = NULL;
pRoot->data = val;
}
else
{
if(pRoot->data == val)
return ;
if(pRoot->data < val)
create_sort_tree(pRoot->right,val);
else if(pRoot->data > val)
create_sort_tree(pRoot->left,val);
}
}
void create_sort_tree_ex(pNode& pRoot, char val)
{
pNode tmp = pRoot;
pNode cur_node = NULL;
while(tmp)
{
if(tmp->data == val)//如果节点已经存在,则直接退出
return ;
cur_node = tmp;//保存当前节点
tmp = tmp->data > val ? tmp->left : tmp->right;//获取下一个节点
}
pNode nNode = new Node;
nNode->left = NULL;
nNode->right = NULL;
nNode->data = val;
if(NULL == pRoot)
pRoot = nNode;
else if(val < cur_node->data)
cur_node->left = nNode;
else
cur_node->right = nNode;
}
//删除二叉排序树的节点
/*删除*p结点的三种情况
(1)fdNode是叶子(即它的孩子数为0)
无须连接*p的子树,只需将fdNode的双亲 parent 中指向 fdNode 的指针域置空即可
(2)fdNode只有一个孩子 left
需要将做孩子直接链接到fdNode的parent节点即可,但是需要判断fdNode是parent的左节点还是右节点
注:fd只有一个孩子(right)的情况也是如此,连接孩子到parent的时候,需要判断fdNode是parent的左节点还是右节点
(3)fdNode左右节点都存在
根据排序二叉树的特点可以知道,fdNode右子树中序遍历的第一个节点便是fdNode的后继节点,此节点(del_left)的左子树必为空。
如此这样,交换fdNode和del_left的节点数值,再删掉del_left节点即可。如果del_left的右子树不为空,又把问题转化为(2)中的问题了
,否则变为(1)中的问题
*/
bool del_node(pNode& pRoot, char val)
{
if(NULL == pRoot)
return false;
pNode tmp = pRoot;
pNode fdNode = NULL;
pNode pre = NULL;
while(tmp)
{
if(tmp->data == val)
{
fdNode = tmp;
break;
}
pre = tmp;
tmp = tmp->data > val ? tmp->left : tmp->right;//获取下一个节点
}
if(fdNode)
{
//查找到的节点为叶子节点
if(fdNode->left == NULL && fdNode->right == NULL)
{
if(pre)//要删除的节点存在父节点
{
bool is_left = (pre->left == fdNode);
if(is_left)
pre->left = NULL;
else
pre->right = NULL;
}
else
pRoot = NULL;
delete fdNode;
fdNode = NULL;
}
//被查找到的节点只存在右节点
else if(fdNode->left == NULL && fdNode->right != NULL)
{
if(pre)
{
bool is_left = (pre->left == fdNode);
if(is_left)
pre->left = fdNode->right;
else
pre->right = fdNode->right;
}
else
{
pRoot = fdNode->right;
fdNode->right = NULL;
}
delete fdNode;
fdNode = NULL;
}
//被查找到的节点只存在左节点
else if(fdNode->left != NULL && fdNode->right == NULL)
{
if(pre)
{
bool is_left = (pre->left == fdNode);
if(is_left)
pre->left = fdNode->left;
else
pre->right = fdNode->left;
}
else
{
pRoot = fdNode->left;
fdNode->left = NULL;
}
delete fdNode;
fdNode = NULL;
}
//被查找到的节点左右节点均存在
else if(fdNode->left && fdNode->right)
{
//找到fdNode的右子树
pNode dy_node = fdNode->right;
pNode dy_pre = fdNode;
//查找到fdNode的中序遍历的后继结点
while(dy_node)
{
if(dy_node->left == NULL)
break;
dy_pre = dy_node;//保存dy_node的前驱结点
dy_node = dy_node->left;
}
//交换要删除节点(fdNode)的节点值和它的右子树的中序遍历的第一个节点的数值
char tmp_val = dy_node->data;
dy_node->data = fdNode->data;
fdNode->data = tmp_val;
//判断查找到的节点是否存在右子树
if(dy_node->right)
{
if(dy_pre == fdNode)
dy_pre->right = dy_node->right;
else
dy_pre->left = dy_node->right;
}
else
{
//判断前驱结点是否为要删除掉的节点
if(dy_pre == fdNode)
dy_pre->right = NULL;
else
dy_pre->left = NULL;
}
//交换数据后,删除节点
delete dy_node;
dy_node = NULL;
}
return true;
}
else
return false;
}
int main()
{
Node *pRoot = NULL;
std::string data = "eqwep1p312keqweqe";
for(int index = 0x00; index < data.size(); index++)
create_sort_tree_ex(pRoot, data.at(index));
std::cout<<"proot ======"<<pRoot->data<<std::endl;
mid_show(pRoot);
std::cout<<std::endl;
std::string del_str = "abc@eqwep1p312keqweqe";
for(int index = 0x00; index < del_str.size(); index++)
{
char tmp = del_str.at(index);
if(del_node(pRoot, tmp))
std::cout<<"del ----"<<tmp<<"====ok"<<std::endl;
else
std::cout<<"del ----"<<tmp<<"====###failed."<<std::endl;
mid_show(pRoot);
std::cout<<"###=============="<<hex<<pRoot<<"==============================="<<std::endl;
}
return 0;
}