二叉树系列:初探二叉树,c语言实现

             端午节假期的最后一天,天气凉爽,我下午该回学校了。原本,我昨天就该写下二叉树的博文,但是由于在二叉树删除这块的功能实现不尽人意,所以我推迟了,希望将其改进后再进行记录。早上趁着清醒,我如愿地改进了二叉树的删除功能,特此记录想法的美好瞬间。

 1、二叉树的基本概念

        二叉树的特点是每个结点至多有二棵子树,并且子树之间有左右之分。
二叉树的其他特性可以参考博文链接,这里按照我自己的方式,具体介绍二叉查找树的查找、插入、 遍历 和删除。

2、二叉查找树的操作

<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

struct tree_node
{

	int key;
	struct tree_node *left;
	struct tree_node *right;
};</span>

       1)查找
步骤:step1:判断root(根地址)是否为空,若不是则顺序执行;
           step2:判断根节点的key值是否等于查找值value,若相等则return NULL,否则选择左子树或者右子树进行查找;
            
代码:
<span style="font-size:14px;">struct tree_node* search(struct tree_node *root, int value)
{

	struct tree_node *p;

	while(root!=NULL)
	{
		p=root;
		if (root->key==value)
		{
			return NULL;
		}
		root=(root->key<value) ? root->right:root->left;
	}

	//not found 
	return p;
}</span>

            2)插入

步骤:step1:判断根节点是否为空,若满足则令新节点为根,否则执行step2;
           step2:在以root为根节点这棵树上进行value的查找,判断返回值。若为空,则说明value已存在不需要插入,return。否则继续执行;
           step3:将返回的 指针 节点的key值与value进行比较,若value>key,则将其连接至指针节点的右子树,反之亦然。

代码:
<span style="font-size:14px;">void insert_Tree(struct tree_node *root, int value)
{
	struct tree_node *s;
	//initialize insert node
	struct tree_node *p=new struct tree_node;
	p->key=value;
	p->left=NULL;
	p->right=NULL;

	if (!root)
	{
		root=p;
		return;
	}
	else
	{
		s=search(root,value);
		if (s==NULL)
		{
			cout<<"do not need to insert"<<endl;
			delete p;
			return;
		}

		if (s->key>value)
		{
			s->left=p;
		}
		else
		{
			s->right=p;
		}

		return;

	}


}</span>


        3)中序遍历
<span style="font-size:14px;">int print_value(int data)
{

	cout<<data<<endl;
	return 1;
}

int print_tree_inorder(struct tree_node *root)
{

	if (root)
	{
		if (print_tree_inorder(root->left))
			if (print_value(root->key))
				if(print_tree_inorder(root->right))
					return 1;
			
		return 0;
			
	}
	else
	{
		return 1;//边界
	}
}</span>

               4)删除
对二叉树删除这部分,其实比较复杂,接下来通过图解来说明删除的几种情况。

                            图1  删除根节点,根节点的右子树的左子树不空



                      图2  删除节点6,节点6的右子树的左子树为空

对于删除的其余情况参加代码。代码如下:
<span style="font-size:14px;">struct tree_node* delete_tree_node(struct tree_node *root, int value)
{
	struct tree_node *c_root;
	struct tree_node *p=root;
	struct tree_node *s,*parent;

	if (NULL==p)
	{
		fprintf(stderr,"the deleting value is %d not found\n",value);
		return NULL;
	}

	if (p->key==value)
	{
		/* only a root, no children  */
		if (!p->left && !p->right)
		{
			root=NULL;
			free(p);
			return NULL;
			
		}
		else if (!p->right)
		{
			root=p->left;
			free(p);
			return root;
		}
		else if (!p->left)
		{
			root=p->right;
			free(p);
			return root;
		}
		else
		{
			/* tree has both children  */
			s=p->right;
			if (!s->left)
			{
				s->left=p->left;
				root=s;
				free(p);
				return root;
			}
			else 
			{
				/* look for the last not empty left node in left subtree   */
				while(s->left)
				{

					parent=s;
					s=s->left;
				}
				parent->left=s->right;
				s->right=p->right;
				s->left=p->left;
				root=s;

				free(p);
				return root;
			}

		}
	}
	else if (p->key<value)
	{
		if((c_root=delete_tree_node(p->right,value))!=NULL )
		{
			root->right=c_root;//将返回后的结点与根结点重新连接
			return root;
		
		}
		else
			return NULL;
	}
	else if (p->key>value)
	{
		if((c_root=delete_tree_node(p->left,value))!=NULL)
		{
			root->left=c_root;
			return root;
		}
		else
			return NULL;
	}

//	return;
}</span>

3、测试主程序及结果

<span style="font-size:14px;">int main()
{
	
	struct tree_node *root,*t_root;
	root=new struct tree_node;
	root->key=8;
	root->left=NULL;
	root->right=NULL;

	insert_Tree(root,6);
	insert_Tree(root,20);
	insert_Tree(root,5);
	insert_Tree(root,7);
	insert_Tree(root,22);
	insert_Tree(root,15);
	insert_Tree(root,17);
	insert_Tree(root,16);
	insert_Tree(root,18);

	print_tree_inorder(root);
	cout<<"\nAfter deleting, the tree is:"<<endl;

	t_root=delete_tree_node(root,8);//delete root node
//	t_root=delete_tree_node(root,6);
	print_tree_inorder(t_root);

	return 0;
}</span>

删除根节点8的实验结果:


删除节点6的实验结果:





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值