二叉排序树整理

来源:互联网 发布:普通程序员 知乎 编辑:程序博客网 时间:2024/06/07 09:50

二叉排序树(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;elsecur_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;}elsepRoot = 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;elsepre->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;elsepre->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;elsedy_pre->left  = dy_node->right;}else{//判断前驱结点是否为要删除掉的节点if(dy_pre == fdNode)dy_pre->right = NULL;elsedy_pre->left = NULL;}//交换数据后,删除节点delete dy_node;dy_node = NULL;}return true;}elsereturn 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;elsestd::cout<<"del ----"<<tmp<<"====###failed."<<std::endl;mid_show(pRoot);std::cout<<"###=============="<<hex<<pRoot<<"==============================="<<std::endl;}return 0;}



原创粉丝点击