数据结构与算法分析(六)——C++实现二叉查找树

二叉树的基本概念

1.定义
二叉树(binary tree)是一颗树,其中每个节点都不能有多于两个的儿子。

2.实现
每一个节点用一个结构体表示,包含一个关键字和两个指向左儿子和右儿子的指针。

3.遍历方式
中序遍历:左 节点 右
后序遍历:左 右 节点
先序遍历:节点 左 右

4.二叉查找树的概念
一颗二叉树,对于每一个节点X,它的左子树中所有的关键字值都小于X的关键字值,它的右子树中所有的关键字值都大于X的关键字值。

5.二叉查找树的性质
平均深度O(logN)

二叉查找树各种操作的代码实现

用到了很多的递归操作,且所有操作都需要传入操作的节点(即可以对子树进行操作)
1.清空树
算法实现步骤:
1.递归删除左子树
2.递归删除右子树
3.删除该节点,返回一个NULL指针(释放内存后指针依旧指向该段内存,但是内容不确定了)

/**
 *@name Make_empty:递归删除该节点以及该节点下所有的子树
 *@param1 T:指向该节点的指针
 *@ret:将NULL返回给删除的该节点
**/
Search_Tree Binary_Tree::Make_empty(Search_Tree T )
{
	//这里使用了递归删除
	if(T!=NULL)
	{
		Make_empty(T->left);
		Make_empty(T->right);
		delete T;
		T=NULL;
	}
	return T;
}

2.查找最大(最小值)
算法实现步骤:
1.由二叉查找树的结构决定,找到最左边的叶(最小值),找到最右边的叶(最大值)
2.这里也利用递归去找,为最小值为例,直到找到的节点的左儿子为空时,将该节点返回
注:
这里在递归调用Find_Min时需要加return,否则从堆栈pop出来的时候就只有一个ret,可能会出现问题

/**
 *@name Find_Max:找到该节点的子树中最大的那个值
 *@param1 T:传入的树节点 如果要找整根树中最大的值则输入root
 *@ret:指向存最大值的树节点 为子树中最右边的叶
**/
Search_Tree Binary_Tree::Find_Max(Search_Tree T)
{
	if(T==NULL)
		return NULL;

	if(T->right==NULL)
	{
		return T;
	}
	else
	{
		return Find_Max(T->right);
	}
}

/**
 *@name Find_Max:找到该节点的子树中最小的那个值
 *@param1 T:传入的树节点 如果要找整根树中最小的值则输入root
 *@ret:指向存最大值的树节点 为子树中最左边的叶
**/
Search_Tree Binary_Tree::Find_Min(Search_Tree T)
{
	if(T==NULL)
	{
		return NULL;
	}

	if(T->left==NULL)
	{
		return T;
	}
	else
	{
		return Find_Min(T->left);
	}
}

3.查找关键字匹配的节点
算法实现步骤:
1.从某一节点向下,如果查询的关键字大于该节点的关键字,到右子树中递归查找,如果查询的关键字小于该节点的关键字,到左子树中递归查找。
2.如果递归到节点已空,则没有找到;如果找到则返回该节点的地址。
注:
在递归Find_Position前也要加return

/**
 *@name Find_Position:查找关键字所在的树的节点
 *@param1 data:需要匹配的关键字
 *@param2 T:从哪一个节点开始往下找 只会向下查找
 *@ret:指向匹配到关键字的节点的指针 没有找到则返回NULL
**/
Search_Tree Binary_Tree::Find_Position(int data,Search_Tree T)
{
	if(T==NULL)
	{
		return NULL;	
	}

	//如果数据比该节点的关键字小的话,查找去左子树中查找
	if(T->data>data)
	{
		return Find_Position(data,T->left);	
	}
	//如果数据比该节点的关键字大的话,查找去右子树中查找
	else if(T->data<data)
	{
		return Find_Position(data,T->right);
	}
	else
	{
		return T;
	}
}

4.插入节点
由于二叉查找树的结构,插入永远会在叶上,故方便很多
算法实现步骤:
1.根据新插入的节点的关键字大小,在给定节点的左子树递归插入或右子树递归插入
2.直到递归到空节点,new一个节点,然后return该地址
3.最后返回插入完成了的给定节点的地址

/**
 *@name Insert:在树的合适位置插入关键字为data的节点
 *@param1 data:插入的数据
 *@param2 T:在该节点的子树中插入数据
**/
Search_Tree Binary_Tree::Insert(int data,Search_Tree T)
{
	//递归到空节点 这时建立一个新节点
	if(T==NULL)
	{
		T=new Tree_node;
		T->data=data;
		T->left=T->right=NULL;
		return T;
	}

	//插入的数据小于此时节点的数据,往左插(别忘了赋值给子左节点,指针形参改变不了传入的参数,即虽然T->left新建了一个节点,但此时只有形参指向它)
	if(T->data>data)
	{
		T->left=Insert(data,T->left);
	}
	//插入的数据大于此时节点的数据,往右插
	else if(T->data<data)
	{
		T->right=Insert(data,T->right);
	}
	//如果插入的数据等于此时节点的数据,直接返回该节点
	else
	{
		cout<<"can't insert the same data"<<endl;
	}
	return T;
}

5.删除某一关键字对应的节点
算法实现步骤:
1.关键字小于给点节点关键字去左子树删,关键字大于给点节点关键字去右子树删。
2.如果关键字等于当前节点了分三种情况删:
(1)当前节点为叶,直接delete,返回NULL;
(2)当前节点只挂一侧有子树,则先用定义中间指针变量temp指向该节点,然后delete当前节点,然后返回其右子树;
(3)当前节点两侧都有子树,则取出右子树中的min节点,将此关键字赋给当前节点,然后递归删除min节点;
3.如果找到空节点了还没找到就报错。

/**
 *@name Delete:删除关节字为data的元素
 *@param1 data:关键字
 *@param2 T:从该节点以下的树中删除
**/
Search_Tree Binary_Tree::Delete(int data,Search_Tree T)
{
	Search_Tree temp;

	if(T==NULL)
		cout<<"error:without element to delete"<<endl;
	else if(T->data<data)
		T->right=Delete(data,T->right);
	else if(T->data>data)
		T->left=Delete(data,T->left);
	else
	{
		//此时data等于T->data
		temp=T;
		if((T->left==NULL)&&(T->right==NULL))	//此时的节点为叶 
		{
			delete T;
			T=NULL;
		}
		else
		{
			if(T->left==NULL)				//此时的左儿子为空,只有右子树
			{
				T=T->right;						//将T指向右儿子节点
				delete temp;					//释放该节点的内存
				temp=NULL;
			}
			else if(T->right==NULL)	//此时的右儿子为空,只有左子树
			{
				T=T->left;						//将T指向左儿子节点
				delete temp;					//释放该节点的内存
				temp=NULL;
			}
			else														//此时既存在左子树又存在右子树
			{
				temp=Find_Min(T->right);			//找到右子树中最小的节点
				T->data=temp->data;					//将该节点的元素赋给当前节点
				T->right=Delete(temp->data,T->right);	//对右子树进行一次删除操作
			}
		}
	}
	return T;
}

对递归和指针理解的还不够,搞在一起就开始糊涂了。。。
注:
为什么这里的形参指针不能改变传入的指针的值?
解:
1.改变形参指针指向的内容对传入的指针毫无影响,因为调用完后就消失了
2.这里由于递归带来的混淆,我一直以为形参指针和传入的指针指向的一直是同一块内存,这里举最简单的一个例子,传入的指针指向NULL,形参做出判断,新建了一块内存并指向它,而传入的指针依旧是NULL。

发布了99 篇原创文章 · 获赞 29 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44586750/article/details/103241835