唐老师数据结构专题八3

关于二叉树的创建:

这里有个问题,就是二叉树,就不能想1中讲的那样,建立两个链表,一个孩子链表,一个组织链表,因为二叉树的孩子是分左右的,这个顺序不能搞混,所以就直接是在每个二叉树的结点中设置两个指针,分别指向左右孩子,这样就可以了,但是又有一个问题随之而来,那就是如何定位??这个问题唐老师给了一个很形象的解决办法,“指路”就是说,当你到了陌生的地方,别人给你指路,然后你会按照指的路去一步一步走,同样的,在想二叉树里插入元素的时候,自己可以设定一个路标,然后按照路标的指示一直走下去即可。


然后是二叉树的插入, 这个函数还要有一个特殊的参数,就是当你插入某个结点元素n后,该树可能是插在某个结点m的后面,而m的后面原先也有元素,当你插入后,原先的那些元素树时放在你插入的元素n的做树后面,还是右树后面呢,这个就需要这个特殊的参数了。


然后是二叉树的遍历:分为前序遍历,中序遍历,后序遍历还有层次遍历。


现在先展示一下插入函数,如何通过用指示来寻找这个函数的:

//左边的孩子 
#define Child_L 0
//右边的孩子 
#define Child_R 1
//这个是指向树的根节点的头
//包含着指向二叉树的根的指针,和该二叉树的结点数目
typedef struct _tag_BTreeList BTreeList;
struct _tag_BTreeList
{
	BTreeNode* root;
	int count;
};

插入元素函数如下:

//这里node是数据元素  pos则是路标,按照路标就可以找到 count则是计数
//这里可能有人会问,都有指标了为什么还用count呢  比如pos=0x00 你的意思是插在根节点的左边
//如果没有count 你怎么判断你这个pos已经移动完了呢  所以有必要加个count 
//flag则是将插入结点后面的元素插在该元素的左边还是右边
int Tree_Insert(BTree* tree, BTreeNode* node, BTPos pos, int count, int flag)
{
	BTreeList* btree = (BTreeList*)tree;
	int ret = (btree != NULL) && (node != NULL);
	
	
	if( ret )
	{
		int i = 0;
		int p = -1;
		//设置一个保存孩子的结点 
		BTreeNode* current = btree->root;
		BTreeNode* parents = NULL;
		
		//先将新结点的两个孩子指针初始化 
		node->left = NULL;
		node->right = NULL;
		
	//此循环为了找到相应的孩子节点	
		while( (count>0) && (current != NULL) )
		{
			p = pos&1;
			pos = pos>>1;
			//保存父亲结点 
			parents = current;
			if( p == Child_L )
			{
				current = current->left;
			}
			else if( p = Child_R )
			{
				current = current->right;
			}
			count--;
		}
		
		if( parents != NULL ) 
		{
			if( p == Child_L )
			{
				parents->left = node;
			}
			else if( p == Child_R )
			{
				parents->right = node;
			}
		}
		//如果两个都不是  那么插入的应该是树的根 
		else
		{
			btree->root = node;
		}
		//将插入结点后面的元素  连接到新的节点处 
		if( flag == Child_L )
		{
			node->left = current;
		}
		else if( flag == Child_R )
		{
			node->right = current;
		}
		
		btree->count++;
	}
	
	return ret;
}

删除函数:(这里主要注意的是count没删除一个元素的时候,可能count减小的值并不是1  因为删除的元素后面可能还会有元素)

BTreeNode* Tree_Delete(BTree* tree, BTPos pos, int count)
{
	BTreeList* btree = (BTreeList*)tree;
	BTreeNode* ret = NULL;
	
	if(btree != NULL)
	{
		int i = 0;
		int p = -1;

	//设置一个保存孩子的结点 
		BTreeNode* current = btree->root;
		BTreeNode* parents = NULL;
				
	//此循环为了找到相应的孩子节点	
	//这里不要忘了加上  current != NULL 很容易弄丢
		while( (count>0) && (current != NULL) )
		{
			p = pos&1;
			pos = pos>>1;
			//保存父亲结点 
			parents = current;
			if( p == Child_L )
			{
				current = current->left;
			}
			else if( p = Child_R )
			{
				current = current->right;
			}
			count--;
		}
		
		if(parents != NULL)		
		{
			if( p == Child_L )
			{
				parents->left = NULL;
			}
			else if( p == Child_R )
			{
				parents->right = NULL;
			}
		}
		//删除的的根节点
		else
		{
			btree->root = NULL;
		} 
		
	//这里不要忘了count减小的值不是1  因为删除的元素他的后面可能还会有元素
		btree->count = btree->count - recursive_count(current);
		
		ret = current;
	}
	
	return ret;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值