算法导论第十二章——二叉查找树的C++代码实现

 

二叉排序树(Binary Sort Tree)又称二叉查找树。 它或者是一棵空树;或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉排序树;

二叉排序树的查找
  步骤:若根结点的关键字值等于查找的关键字,成功。
  否则,若小于根结点的关键字值,递归查左子树。
  若大于根结点的关键字值,递归查右子树。
  若子树为空,查找不成功。
  平均情况分析(在成功查找两种的情况下)
 

二叉排序树的插入和删除

  与次优二叉树相对,二叉排序树是一种动态树表。其特点是:树的结构通常不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的节点时再进行插入。新插入的结点一定是一个新添加的叶子节点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。

插入算法

  首先执行查找算法,找出被插结点的父亲结点。
  判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子节点插入。
  若二叉树为空。则首先单独生成根结点。然后该节点指向要插入的节点。
 
具体代码如下,该代码实现了树的插入、删除、搜索,中序遍历,前序遍历,后序遍历,获取左孩子,获取右孩子,获取父母节点,获取树的高度,获取节点按照中序遍历的前序节点以及后继节点。
BinTreeNode.h实现了树的节点的相关操作:
#include<iostream>
using namespace std;
class BinTree;
class BinTreeNode
{
private:
	friend BinTree;
	int key;
	BinTreeNode* left;
	BinTreeNode* right;
public:
	BinTreeNode():key(-1),left(NULL),right(NULL){}
	BinTreeNode(BinTreeNode* node):key(node->key),left(node->left),right(node->right)
	{}
	BinTreeNode(int num):left(NULL),right(NULL),key(num){}
	~BinTreeNode()
	{}
	int Getkey()
	{
		return key;
	}
	BinTreeNode* GetLeft()
	{
		return this->left;
	}
	BinTreeNode* Getright()
	{
		return this->right;
	}
	void Inorder()
	{
		if(this!=NULL)
		{
			this->left->Inorder();
			cout<<this->key<<" ";
			this->right->Inorder();
		}
	}
	void Preorder()
	{
		if(this!=NULL)
		{
			cout<<this->key<<" ";
			this->left->Preorder();
			this->right->Preorder();
		}
	}
	void Postorder()
	{
		if(this!=NULL)
		{
			this->left->Postorder();
			this->right->Postorder();
			cout<<this->key<<" ";
		}
	}
	void MakeEmpty()
	{
		if(this!=NULL)
		{
			this->left->MakeEmpty();
			this->right->MakeEmpty();
			delete this;
		}
	}
	int GetHeight()
	{
		int L,R;
		if(this==NULL)
		{
			return 0;
		}
		L=this->left->GetHeight();
		R=this->right->GetHeight();
		return 1+(L>R? L:R);
	}

};

BinTree.h实现了树的相关操作:
#include"BinTreeNode.h"
class BinTree
{
private:
	BinTreeNode* root;
public:
	BinTree():root(NULL){}
//	BinTree(BinTreeNode* node):root(node){}
	~BinTree()
	{
		MakeEmpty();
	}
	void MakeEmpty()
	{
		BinTreeNode *p=root;
		p->MakeEmpty();
	}
	int Getkey(BinTreeNode* node)
	{
		return node->Getkey();
	}
	BinTreeNode* Getroot()
	{
		return root;
	}
	int GetHeight()
	{
		return root->GetHeight();
	}
	void Inorder()
	{
		return root->Inorder();
	}
	void Preorder()
	{
		return root->Preorder();
	}
	void Posetorder()
	{
		return root->Postorder();
	}
	void Insert(int num)
	{
		BinTreeNode* node=new BinTreeNode(num);
		BinTreeNode* p=root,*q;
		if(root==NULL)
		{
			root=node;
			return ;
		}
		while(p)
		{
			if(p->key==num)
			{
				cout<<num<<"  has exist!"<<endl;
				return ;
			}
			else if(p->key>num)
			{
				q=p;
				p=p->left;
			}
			else
			{
				q=p;
				p=p->right;
			}
		}
		if(q->key>num)
			q->left=node;
		else
			q->right=node;
	}
	BinTreeNode* Search(int num)
	{
		BinTreeNode* p=root;
		while(p)
		{
			if(p->key==num)
			{
				return p;
			}
			else if(p->key>num)
			{
				p=p->left;
			}
			else 
			{
				p=p->right;
			}
		}
		cout<<"there is no "<<num<<" in this tree!"<<endl;
		return NULL;
	}
	//获取以node节点为根节点的树的最小元素,并返回该最小值
	int Minnum(BinTreeNode*node)
	{
		BinTreeNode*p=node;
		while(p->left!=NULL)
		{
			p=p->left;
		}
		return p->key;
	}
	//获取以node节点为根节点的树的最da元素,并返回该最da值
	int Maxnum(BinTreeNode*node)
	{
		BinTreeNode*p=node;
		while(p->right!=NULL)
		{
			p=p->right;
		}
		return p->key;
	}
	//获取以node节点为根节点的树的最小元素,并返回该节点
	BinTreeNode* MinNum(BinTreeNode*node)
	{
		BinTreeNode*p=node;
		while(p->left!=NULL)
		{
			p=p->left;
		}
		return p;
	}
	//获取以node节点为根节点的树的最大元素
	BinTreeNode* MaxNum(BinTreeNode*node)
	{
		BinTreeNode*p=node;
		while(p->right!=NULL)
		{
			p=p->right;
		}
		return p;
	}
	//获取Node节点的父母节点,如果是根节点返回NULL
	BinTreeNode* GetParent(BinTreeNode*node)
	{
		if(node==root)
		{
			return NULL;
		}
		BinTreeNode*p=root,*q=p;
		while(p)
		{
			if(p->key==node->key)
			{
				return q;
			}
			else if(p->key>node->key)
			{
				q=p;
				p=p->left;
			}
			else
			{
				q=p;
				p=p->right;
			}
		}
	}
	//中序遍历的后续
	BinTreeNode*InorderSuccessor(BinTreeNode*node)
	{
		if(node->right!=NULL)
		{
			return MinNum(node->right);
		}
		else
		{
			BinTreeNode*p=GetParent(node);
			while(p&&node==p->right)
			{
				node=p;
				p=GetParent(node);
			}
			return p;
		}
	}
	//中序遍历的前趋
	BinTreeNode*InordePredecessor(BinTreeNode*node)
	{
		if(node->left!=NULL)
		{
			return MaxNum(node->left);
		}
		else
		{
			BinTreeNode*p=GetParent(node);
			while(p&&node==p->left)
			{
				node=p;
				p=GetParent(node);
			}
			return p;
		}	
	}
	bool Delete(int num)
	{
		BinTreeNode*p,*q,*t;
		//寻找key值为num的节点p
		p=Search(num);
		if(p==NULL)
		{
			return 0;
		}
		//如果p节点没有孩子节点,则直接去掉
		if(p->left==NULL&&p->right==NULL)
		{
			q=GetParent(p);
			if(p==q->left)
			{
				q->left=NULL;
			}
			else
			{
				q->right=NULL;
			}
			delete p;
			return 1;
		}
		//如果只有右节点,则将右节点作为p的父母的孩子
		else if(p->left==NULL)
		{
			q=GetParent(p);
			if(p==q->left)
			{
				q->left=p->right;
			}
			else
			{
				q->right=p->right;
			}
			delete p;
			return 1;
		}
		//如果只有左节点,则将左节点作为p的父母的孩子
		else if(p->right==NULL)
		{
			q=GetParent(p);
			if(p==q->left)
			{
				q->left=p->left;
			}
			else
			{
				q->right=p->left;
			}
			delete p;
			return 1;
		}
		//如果左右节点都具有,则找到p的后继,用p的后继来取代p
		else
		{
			//找到p的后继,
			q=InorderSuccessor(p);
			//获取q的父母
			t=GetParent(q);
			//q的父母左孩子指向q的右孩子,这样q就删除了。
			//因为q为p的后继所以最多有一个右孩子,而且q肯定为父母的左孩子,如果为父母的右孩子
			//那么q就不可能成为p的后继
			t->left=q->right;
			//获取p的父母,是p的父母指向q,且q的左右孩子分别为p的左右孩子
			t=GetParent(p);
			if(t->left==p)
			{
				t->left=q;
			}
			else
			{
				t->right=q;
			}
			q->left=p->left;
			q->right=p->right;
			delete p;
			return 1;
		}
	}
};

mian.cpp对上述操作进行了详细的测试
#include"BinTree.h"
int main()
{
	int a[12]={15,5,3,12,10,13,6,7,16,20,18,23};
	int i;
	BinTree tree;
	for(i=0;i<12;i++)
	{
		tree.Insert(a[i]);
	}
	tree.Inorder();
	cout<<endl;
	tree.Preorder();
	cout<<endl;
	tree.Posetorder();
	cout<<endl;
	cout<<"the heigth of the tree is :"<<tree.GetHeight()<<endl;
	tree.Insert(13);
	tree.Insert(100);
	tree.Inorder();
	cout<<endl;
	tree.Search(45);

	if(tree.Delete(5))
	{
		cout<<"delete "<<5<<" successful!"<<endl;
	}
	tree.Inorder();
	cout<<endl;
	cout<<"the min num of the tree is :"<<tree.Minnum(tree.Getroot())<<endl;
	cout<<"the max num of the tree is :"<<tree.Maxnum(tree.Getroot())<<endl;
	cout<<"the successor of element 7 is :"<<tree.InorderSuccessor(tree.Search(7))->Getkey()<<endl;
	cout<<"the Predecessor of element 7 is :"<<tree.InordePredecessor(tree.Search(7))->Getkey()<<endl;
	cout<<"the successor of element 13 is :"<<tree.InorderSuccessor(tree.Search(13))->Getkey()<<endl;
	return 0;
}

 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值