// BinarySearch.cpp : 定义控制台应用程序的入口点。
//
#include "iostream"
#include "BinarySearch.h"
using namespace std;
extern int oridada[];
//创建二叉查找树
int arrayIndex = 0;
void CBinaryTree::CreateBinaryTree(CBinaryNode* &T,int data)
{
if(data == -1)
{
T = NULL;
arrayIndex ++;
return;
}
else
{
T = new CBinaryNode();
T->data = data;
arrayIndex ++;
CreateBinaryTree(T->left,oridada[arrayIndex]);
CreateBinaryTree(T->right,oridada[arrayIndex]);
}
}
//中序遍历
void CBinaryTree::InOrderTreeWork(CBinaryNode* &T)
{
if(T == NULL)
return;
InOrderTreeWork(T->left);
cout<<T->data<<endl;
InOrderTreeWork(T->right);
}
CBinaryNode* CBinaryTree::TreeSearch(CBinaryNode* &T,int k)
{
if(T == NULL)
return T;
if(T->data == k)
return T;
if(k < T->data)
return TreeSearch(T->left,k);
if(k > T->data)
return TreeSearch(T->right,k);
}
CBinaryNode* CBinaryTree::TreeMinimum(CBinaryNode* &T)
{
// if(T->left == NULL)
// return T;
CBinaryNode *node = T;
//TreeMinimum(T->left);
while(node->left != NULL)
{
node = node->left;
}
return node;
}
CBinaryNode* CBinaryTree::TreeMaximum(CBinaryNode* &T)
{
// if(T->right == NULL)
// return T;
//TreeMaximum(T->right);//递归方式
//也可以用下面的方式
CBinaryNode *node = T;
while(node->right != NULL)
{
node = node->right;
}
return T;
}
//后继
CBinaryNode* CBinaryTree::TreeSuccessor(CBinaryNode* &root, CBinaryNode* &T)
{
if(T->right != NULL)//情况1、存在右子节点,在右子节点中找最小值
return TreeMinimum(T->right);
//情况2、不存在右子节点,需要将父节点查找出来,然后从当前节点开始往后倒退
//一直退到其父节点的父节点为左节点处
CBinaryNode *p = TreeParent(root,T);此处可以在CBinaryNode增加一个父结构
while ((p != NULL)&&(T == p->right))
{
T = p;
p = TreeParent(root,p);//此处可以在CBinaryNode增加一个父结构
}
return p;
}
//前驱 情况与后继的类似,但是是反向操作的
CBinaryNode* CBinaryTree::TreePrecursor(CBinaryNode* &root,CBinaryNode* &T)
{
if(T->left != NULL)
return TreeMaximum(T->left);
CBinaryNode *p = TreeParent(root,T);//此处可以在CBinaryNode增加一个父结构
while((p != NULL)&&(T == p->left))
{
T = p;
p = TreeParent(root,p);//此处可以在CBinaryNode增加一个父结构
}
}
//父结构,可在CBinaryNode中增加一个父类结构而省去查找这一步骤
CBinaryNode* CBinaryTree::TreeParent(CBinaryNode* &root,CBinaryNode* &desNode)
{
//前序遍历的方式
CBinaryNode *parent = root;
if(parent->left == desNode)
return parent;
if(parent->right == desNode)
return parent;
if((parent->left !=NULL)&&(desNode->data < parent->left->data))
{
return TreeParent(parent->left,desNode);
}
else if((parent->right !=NULL)&&(desNode->data > parent->right->data))
{
return TreeParent(parent->right,desNode);
}
}
void CBinaryTree::TreeInsert(CBinaryNode* &root,int k)
{
if(root == NULL)
return;
CBinaryNode *nnode = new CBinaryNode();
nnode->data = k;
nnode->left = NULL;
nnode->right = NULL;
CBinaryNode *temp = root;
CBinaryNode *p = root;
while(temp)
{
p = temp;
if(k < temp->data)
temp = temp->left;
else
temp = temp->right;
}
if(k > p->data)
p->right = nnode;
else
p->left = nnode;
}
//删除节点的过程
//1.找出需要删除的节点,此处需要判断要删除的节点是单子节点还是双子节点,
//若是双子节点,则删除的节点转移到其后继节点上,而此时后继节点是最多只有一个右子节点的
//2.取出将要删除的节点的子节点,注意:在此时,需要删除的节点是没有左子的(最多只有一个右子节点)
//3.取出需要删除的节点的父,此时要注意,需要删除节点有可能是根节点的情况,此时父将为NULL
//4.父为NULL,则直接接上子;不为NULL,则判断是要删除的是父的左/右子节点,将需要删除的子接上至
//需要删除的父的对应位置
//5.如果需要删除的是节点是有两个子节点的情况,则将后继节点的信息复制值准备删除的节点
//6.删除需要删除的节点(可能是后继节点)
void CBinaryTree::TreeDelete(CBinaryNode* &root,int k)
{
CBinaryNode *pareDelNode = TreeSearch(root,k);//准备删除的节点指针
CBinaryNode *needTodelNode = NULL;//需要删除的节点指针
if((pareDelNode->left == NULL)||(pareDelNode->right == NULL))
needTodelNode = pareDelNode;//在只有一个节点或者没有节点时,需要删除的等于pareDelNode
else//有两节节点 等于其中序遍历的后继,这种情况下的后继是只有右子节点的
needTodelNode = TreeSuccessor(root,pareDelNode);
CBinaryNode *child = NULL;//需要删除的节点有三种情况
if(needTodelNode->left != NULL)
{
child = needTodelNode->left;//需要删除的节点存在左子节点
needTodelNode->left = NULL;//注意
}
else//此时不再判断是否有右子节点
{
child = needTodelNode->right;//注意,此处child可能为空,也可能为需要删除的右子节点
needTodelNode->right = NULL;//注意
}
CBinaryNode *pp = TreeParent(root,needTodelNode);//需要删除的父节点
if(pp == NULL)//若删除的是根节点,则将子接上
pp = child;
else
{
if(needTodelNode->data < pp->data)//判断需要删除的是其父的左还是右节点,将相应的子节点接上
pp->left = child;
else if(needTodelNode->data > pp->data)
pp->right = child;
}
if(needTodelNode->data != k)//如果需要删除的是节点是有两个子节点的情况,则将后继节点的信息复制值准备删除的节点
pareDelNode->data = needTodelNode->data;
delete needTodelNode;//删除实际过程中需要删除的节点
}
二叉查找树所有的操作时间复杂度均为O(lg n)
#ifndef BINARYSEARCH_H
#define BINARYSEARCH_H
#include "stdio.h"
class CBinaryNode
{
public:
CBinaryNode():data(0),left(NULL),right(NULL){}
public:
int data;
CBinaryNode *left,*right;
};
class CBinaryTree
{
public:
void CreateBinaryTree(CBinaryNode* &T,int data);
void InOrderTreeWork(CBinaryNode* &T);
CBinaryNode* TreeSearch(CBinaryNode* &T,int k);
CBinaryNode* TreeMinimum(CBinaryNode* &T);
CBinaryNode* TreeMaximum(CBinaryNode* &T);
CBinaryNode* TreeSuccessor(CBinaryNode* &root,CBinaryNode* &T);
CBinaryNode* TreePrecursor(CBinaryNode* &root,CBinaryNode* &T);
CBinaryNode* TreeParent(CBinaryNode* &root,CBinaryNode* &desNode);
void TreeInsert(CBinaryNode* &root,int k);
void TreeDelete(CBinaryNode* &root,int k);
public:
CBinaryNode *Tr;
public:
CBinaryTree()
{
Tr = NULL;
}
};
#endif