二叉查找树实现

// 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值