算法导论十二章复习

/*二叉查找树,查找算法里面的一种,折半查找的时间复杂度是O(nlgn)
二叉查找树:可以进行的操作是:插入,删除,查找,最大值,最小值。
对于有n个节点的二叉查找树来说的话,树的高度是O(lgn),那么进行一次的查找的时间复杂度也就是O(lgn)
*/
#include <iostream>
using namespace std;
struct node
{
	int key;//其他卫星数据亦可包含;
	node* left;
	node* right;
	node* p;
	node()
	{
		key=0;
		left=NULL;
		right=NULL;
		p=NULL;
	}
	node(int k):key(k){
		left=NULL;
		right=NULL;
		p=NULL;
	}
	node& operator=(const node n)
	{
		if (this!=&n)
		{
			this->p=n.p;
			this->left=n.left;
			this->right=n.right;
			this->key=n.key;
		}
		return *this;
	}
};
struct bintree
{
	node* root;
	bintree()
	{
		root=NULL;
	}
};

void mid_tree_walk(node* ptr)//中序遍历
{
	if (ptr!=NULL)
	{
		mid_tree_walk(ptr->left);
			cout<<ptr->key<<" ";
		mid_tree_walk(ptr->right);
	}
	cout<<"finished !"<<endl;//遍历二叉树的时间复杂度是O(n);
}

//二叉树的查找:支持最大,最小,前驱和后继的操作,树高度为h,那么操作就是O(h)
node* tree_search(node* ptr,int k)
{
	if(ptr==NULL||k==ptr->key)
	{
		cout<<"search finished !"<<endl;
		return ptr;
	}
	else if(ptr->key<k)
		return tree_search(ptr->right,k);
	else
		return tree_search(ptr->left,k);
}

//或者替换
node* tree_search1(node* ptr,int k)
{
	while (ptr!=NULL||k!=ptr->key)
	{
		if(ptr->key<k)
			ptr=ptr->right;
		else
			ptr=ptr->left;
	}
	return ptr;
}

node* tree_min(node* ptr)//根据二叉树的性质可以获取
{
	while (ptr->left!=NULL)
	{
		ptr=ptr->left;
	}
	return ptr;
}

node* tree_max(node* ptr)
{
	while (ptr->right!=NULL)
	{
		ptr=ptr->right;
	}
	return ptr;
}

/*求前驱和后继:分情况讨论:当是使用中序遍历的情况的话,求后继的时候一般的是某一个键的后继是比该键值大的最小的一个数字,
那么会出现的情况讨论为:当一个键,有右子树,当一个键没有右子树,但是要求该键的时候,前一种情况求后继很简单,中序的情况
下,后继就是遍历完该根,之后右子树的最左的值;后一种情况,当没有右子树的时候,我们需要向上回溯,回溯到没有遍历的那个父或者祖父节点
通过分析二叉搜索树的结构可以分析得到的是:当该节点的父,祖父等节点不是其对应父节点的右子树的时候就是了。
*/
node* successor(node* ptr)//中序遍历后继
{
	node* pptr=ptr->p;
	if(ptr->right!=NULL)
		return tree_min(ptr->right);
	while (pptr!=NULL&&ptr==pptr->right)
	{
		ptr=pptr;
		pptr=pptr->p;
	}
	return pptr;
}

node* presuccessor(node* ptr)//前驱
{
	node* pptr=ptr->p;
	if (ptr->left!=NULL)
	{
		tree_max(ptr->left);
	}
	while (pptr!=NULL&&ptr==pptr->left)
	{
		ptr=pptr;
		pptr=pptr->p;
	}
	return pptr;
	
}

/***********tree_min and tree_max 递归版本***********/
node *tree_max_plus(node* pptr)
{
	if (pptr->right!=NULL)
		return tree_max_plus(pptr->left);
	else
		return pptr;

}

node *tree_min_plus(node* pptr)
{
	if(pptr->left!=NULL)
		return tree_min_plus(pptr->left);
	else 
		return pptr->left;
}


/*****************插入和删除******************************/
void tree_insert(bintree* btr,node* ptr)//插入,从根节点进行插入对应的node,同样插入的时间复杂度是树的高度的那样
{
	node *py=NULL;
	node *px=NULL;
	px=btr->root;
	while (px!=NULL)
	{
		py=px;
		if(ptr->key<px->key)
		{
			px=px->left;
		}else
		{
			px=px->right;
		}
	}
	ptr->p=py;
	if (py==NULL)
		btr->root=ptr;
	else 
		if (ptr->key<py->key)
			py->left=ptr;
		else
			py->right=ptr;
	cout<<ptr->key<<" finishted insert !"<<endl;
}

node* tree_delete(bintree* btr,node* ptr)//删除,同样的时间复杂度上是和高度有关系的。
{
	node *py=NULL;
	node *px=NULL;
	if(ptr->left==NULL||ptr->right==NULL)
		py=ptr;
	else
		py=successor(ptr);
	if (py->left!=NULL)
		px=py->left;
	else
		px=py->right;
	if (px!=NULL)
		px->p=py->p;
	if (py->p==NULL)
		btr->root=px;
	else	
	{
		if (py==(py->p->left))
			py->p->left=px;
		else
			py->p->right=px;
	}
	if (py!=ptr)
		ptr->key=py->key;
	return py;//删除的这个点是什么?
	//首先是判断该ptr的左右的点是不是有,少于2个的情况就直接点删,对于多余1个的就找后继,对于后继进行点删,并把ptr的值用py的代替。时间复杂度还是那样的。
}

node* tree_delete(bintree btr,node* ptr)//删除,同样的时间复杂度上是和高度有关系的。
{
	node *py=NULL;
	node *px=NULL;
	if(ptr->left==NULL||ptr->right==NULL)
		py=ptr;
	else
		py=successor(ptr);
	if (py->left!=NULL)
		px=py->left;
	else
		px=py->right;
	if (px!=NULL)
		px->p=py->p;
	if (py->p==NULL)
		btr.root=px;
	else	
	{
		if (py==(py->p->left))
			py->p->left=px;
		else
			py->p->right=px;
	}
	if (py!=ptr)
		ptr->key=py->key;
	return py;//删除的这个点是什么?
	//首先是判断该ptr的左右的点是不是有,少于2个的情况就直接点删,对于多余1个的就找后继,对于后继进行点删,并把ptr的值用py的代替。时间复杂度还是那样的。
}


int main()
{
	bintree *btr=new bintree();
	node* ptr1=new node(1);
	node* ptr2=new node(2);
	node* ptr3=new node(4);
	node* ptr4=new node(6);
	node* ptr5=new node(9);
	tree_insert(btr,ptr1);
	tree_insert(btr,ptr2);
	tree_insert(btr,ptr3);
	tree_insert(btr,ptr4);
	tree_insert(btr,ptr5);
	cout<<"---------------"<<endl;
	mid_tree_walk(btr->root);
	node *ptr=tree_max(btr->root);
	cout<<"max : "<<ptr->key<<endl;
	ptr=tree_min(btr->root);
	cout<<"min : "<<ptr->key<<endl;
	tree_delete(btr,ptr2);
	cout<<"---------------"<<endl;
	mid_tree_walk(btr->root);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值