二叉树总结

本文详细介绍了二叉树的基本概念,包括满二叉树、完全二叉树、堆、二叉排序树和平衡二叉树。接着,阐述了二叉树的创建方法,并提供了各种遍历方式的实现,包括先序、中序、后序和广度优先遍历。此外,还讨论了二叉树中结点个数、叶子结点数量、树的深度以及结点最大距离的计算方法。最后,探讨了如何根据遍历序列重建二叉树以及二叉树的镜像反转操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.基本概念

满二叉树:除最后一层外,每一层上的所有节点都有两个子结点,最后一层都是叶子结点。

完全二叉树:满二叉树最后一层,从右往左删除几个结点。堆是一个完全二叉树。

二叉排序树:左子树的值小于根结点,右子树的值大于根结点,且左右子树都是二叉排序树。

平衡二叉树:左右子树深度差的绝对值小于1。

2.二叉树的创建

二叉树结点的定义:

typedef struct Bitnode
{
	char data;
	struct Bitnode* lchild;
	struct Bitnode* rchild;
}BiTNode,*BiTree;

按先序遍历创建二叉树,'#'表示结点为空

void CreateBiTree(BiTree& root)  
{  
    char ch;  
    cin>>ch;     
    if(ch == '#')   //若输入的是'#',表明二叉树为空,置root为NULL  
        root = NULL;  
    else 
    {              
        root = new  BiTNode;
        root->data = ch;  
	CreateBiTree(root->lchild);  
	CreateBiTree(root->rchild);  
    }  
}

3.二叉树的遍历

    二叉树的遍历分为先序、中序、后序,可以用递归实现。递归的本质是栈结构,也可以用栈来模拟递归实现。

先序遍历递归实现

void PreTraverse(BiTree root)
{
  if(root==NULL)
		return ;
  cout<<root->data<<" ";
  PreTraverse(root ->lchild);
  PreTraverse(root ->rchild);
}

先序遍历非递归实现

void PreTraverse_NoRecursion(BiTree root)
{
	if(root==NULL)
		return ;
	stack<BiTree> s;
    BiTree p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            cout<<p->data<<" ";//先访问根结点
            s.push(p);//访问左子树之前,记得先把根结点进栈保存
            p=p->lchild;//然后才访问左子树
        }
        if(!s.empty())
        {
            p=s.top();//pop根结点
            s.pop();
            p=p->rchild;//访问右子树
        }
    }
}

中序遍历递归实现

void InTraverse(BiTree root) 
{
   if(root==NULL)
		return ;
    InTraverse(root->lchild);
	cout<<root->data<<" ";
    InTraverse(root->rchild);
}

中序遍历非递归实现

void InTraverse_NoRecursion(BiTree root)
{
	if(root==NULL)
		return ;
	stack<BiTree> s;
    BiTree p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            s.push(p);//访问左子树之前,记得先把根结点push进栈
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();//pop根结点(访问完左子树后)
            cout<<p->data<<" ";
            s.pop();
            p=p->rchild;//访问右子树
        }
    }  
}

后序遍历递归实现

void PostTraverse(BiTree root)
{	
	if(root==NULL)
		return;
	PostTraverse(root->lchild);
	PostTraverse(root->rchild);
    cout<<root->data<<" ";
}
4.分层遍历二叉树,从上到下,从左到右。

       跟图的广度优先遍历类似,利用队列实现。

void PrintTree(BiTree root)
{
	if(NULL==root)
		return ;
	queue<BiTree> q;
	BiTree font;
	q.push(root);
	while(!q.empty())
	{
		font=q.front();
		q.pop();
		cout<<font->data<<" ";
		if(font->lchild)//交换顺序,从右往左打印
			q.push(font->lchild);
		if(font->rchild)
			q.push(font->rchild);
	}
}

5.二叉树中的结点个数

    结点个数=左子树结点个数+右子树结点个数 + 1(根结点)   递归实现

int Get_node_num(BiTree root)
{
    if(root==NULL)
        return 0;
     int left = Get_node_num (root->lchild);
     int right = Get_node_num (root->rchild);
     return left+right+1;
}

6.二叉树中叶子结点的个数

int Get_leaf_num(BiTree root)
{
     if(root==NULL)
	return 0;
     if(root->lchild==NULL &&  root->rchild ==NULL)
        return 1;
     int left = Get_leaf_num(root->lchild);
     int right = Get_leaf_num(root->rchild);
     return left+right;
}

7.二叉树的深度

int get_depth(BiTree root)
{
     if(root==NULL)
	return 0;
     int ldepth = get_depth(root->lchild);
     int rdepth = get_depth(root->rchild);
     return ldepth> rdepth ? ldepth+1 : rdepth+1;
}

8.二叉树中结点的最大距离。

    分为两种情况:路径经过根结点的最大距离和没有经过时左右子树的最大距离,三者取其大者。

int Max_distance(BiTree root) 
{
	int distance;
	if(root==NULL)
		return 0;
	else
	{
		distance = get_depth(root->lchild) + get_depth(root->rchild);
                //经过根节点的最大距离等于左子树的深度+右子树的深度
		int ldistance = Max_distance(root->lchild);//左子树的最大深度
		int rdistance = Max_distance(root->rchild);//右子树的最大深度
		distance = (ldistance>distance) ? ldistance : distance;//三者比较取最大值
		distance = (rdistance>distance) ? rdistance : distance;
	}
	return distance; 
}

9.根据二叉树的先序和中序遍历,重建二叉树。

    前序遍历的第一个值为根节点,在根据中序遍历,可以得到序列左右子树,再递归调用,重建子树。

BiTree Rebuild(char* PreOrder,char* InOrder,int len)
{
	if(PreOrder == NULL|| InOrder == NULL || len<=0)
		return NULL;
	BiTree root = new BiTNode;
	root->data = *PreOrder;//前序遍历的第一个值作为根节点
	root->lchild = root->rchild = NULL;

	char* pStart =  InOrder;
	char* pEnd = InOrder;
	int ChildLen = 0;

	while(*PreOrder != *pEnd)//在中序遍历中寻找根节点,划分子树
	{
		ChildLen++;
		if(ChildLen>len)//记录临时长度,防止溢出
			break;
		pEnd++;
	}

	int LeftLen = LeftLen = pEnd - pStart;//左子树长度
        int RightLen = RightLen = len - LeftLen -1;//右子树长度

	if(LeftLen>0)//重建左子树
	{
	    root->lchild = Rebuild(PreOrder+1,InOrder,LeftLen);
	}
	if(RightLen>0)//重建右子树
	{
            root->rchild = Rebuild(PreOrder+LeftLen+1,InOrder+LeftLen+1,RightLen);
	}
	return root;
}

10.二叉树的镜像反转。

    自顶向下,先交换根结点的左右孩子,再递归交换根结点左右子树。也可以自底向上,先交换跟结点的左右子树,在交换根结点的左右孩子结点。

void MirrorTransform(BiTree &root)
{
	if(NULL == root)
	    return;
	BiTree temp;
	temp = root->lchild;
	root->lchild = root->rchild;
	root->rchild = temp;
	if(root->lchild)
	    MirrorTransform(root->lchild);
	if(root->rchild)
	    MirrorTransform(root->rchild);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值