C语言-二叉树的基本操作(test)

  1. 创建二叉树节点(递归)
  2. 先序遍历(递归)
  3. 中序遍历(递归)
  4. 后序遍历(递归)
  5. 复制二叉树(先序递归)
  6. 求二叉树的深度(递归)
  7. 求二叉树的节点数(递归)
  • 注意:遍历中的“访问”是一抽象操作,可以指代任何操作,本文仅以“打印、输出”作为“访问”操作!

注:树及二叉树的算法大多都是利用递归的思路去求解,因为树结构本身就是逐级发散,在算法中以一个跟节点和它的左右孩子组成一个单元,通过递归一层一层的访问一个单元的子目录,从而找到二叉树的所有节点。

需要注意的细节:

  1. creat中的输入顺序是按前序遍历的顺序输入
  2. 输入格式:在二叉树中区分左右两个分支节点,也就是一个根结点(root)的左,右孩子可以相互独立,可以只有左孩子,也可以只有右孩子,所以在输入的过程中遇到空节点需要用“#”来代替,如下图二叉树:
    在这里插入图片描述
  • 注意:若输入时想用空格或者回车键隔开每个输入变量,则需在scanf后(代码第20行处)加入一个getchar();来抵消回车或空格键。
  1. 先序遍历:先访问根,DLR(根,左,右),输出跟节点的内容,递归查找当前左孩子的“根系”,递归查找当前右孩子的“根系”。
  2. 中序遍历:中间访问根,LDR(左,根,右),先递归查找当前左孩子的“根系”,输出当前根节点内容,递归查找当前右孩子的“根系”
  3. 后序遍历:后续访问根,LDR(左,右,根),先查递归查找当前左孩子的“根系”,再递归查找当前右孩子的“根系”,最后输出根节点内容。
  4. 层序遍历:根据逐层的次序从上往下,逐层输出,需要借助队列来实现(此处不演示)
  5. 先序遍历,中序遍历,后序遍历,也可以不使用递归算法,因为递归算法本身就是一层一层的放进系统的堆栈中,然后由栈顶向栈底处理,那么能用递归实现的也一定可以用堆栈来实现。
  6. 在建立二叉树的过程中,我们不难发现,我们需要浪费一大部分的空指针,这些虚节点和空指针没有任何的指向,我们在建立n个结点的二叉树中共有2n个指针域,足足有n+1个空指针域,造成巨大的浪费。那么我们怎么样才能避免这种浪费呢?或者是说如何能利用上这些空指针?——线索化二叉树

完整代码:

#include <stdio.h>
#include <stdlib.h>

typedef char dataType;

typedef struct BiNode
{
	dataType elem; //根节点的元素值 
	struct BiNode *lchild; //根节点的左孩子 
	struct BiNode *rchild; //根节点的右孩子 
}BiTree;

BiTree *creat() //创建二叉树,以先序方式填入 
 
{
	dataType value;
	BiTree *t;
	
	scanf("%c",&value);	//为节点读入字符  
	/*getchar();如果输入字符用空格或回车隔开的话,则需要用getchar()抵消空格或回车*/
	if(value=='#')   //如果读入字符为 # 则建立虚节点 
	{
		t=NULL;
	}
	else
	{
		t=(BiTree *)malloc(sizeof(BiTree));
		t->elem=value;
		t->lchild=creat(); //递归调用,处理根节点的左孩子 
		t->rchild=creat(); //递归调用,处理根节点的右孩子 
	}
	
	return t;
}

void preorder(BiTree *t) //先序遍历 
{
	if(t) //判断t不为空 
	{
	    printf("%c ",t->elem);
	    preorder(t->lchild);
	    preorder(t->rchild);
	}

}

void inorder(BiTree *t) //中序遍历 
{
	if(t) //判断t不为空 
	{
	    inorder(t->lchild);
	    printf ("%c ",t->elem);
	    inorder(t->rchild);
	}
	
}

void postorder(BiTree *t) //后续遍历 
{
	if(t) //判断t不为空 
	{
	    postorder(t->lchild);
	    postorder(t->rchild);
	    printf("%c ",t->elem);
	}
	
}

BiTree *copy(BiTree *t) //复制顺序与前序遍历一致
{
	BiTree *New;
	
	if(t==NULL)
	{
		New=NULL;
		return;
	}
	
	New=(BiTree *)malloc(sizeof(BiTree));
	New->elem=t->elem; //复制根节点 
	New->lchild=copy(t->lchild); //递归复制左孩子 
	New->rchild=copy(t->rchild); //递归复制右孩子 
	
     return New;
}

int Depth(BiTree *t) //
{
	int n,m;
	
	if(t==NULL)
	{
		return 0;
	}
	n=Depth(t->lchild); //递归查找左孩子的深度 
	m=Depth(t->rchild); //递归查找右孩子的深度 
	if(n>m)
	{
		return(n+1);
	} 
	
	else 
	
	    return(m+1);	

}

int CountNode(BiTree *t)
{
	int n,m;
	
	if(t==NULL)
	{
		return 0;
	}
	n=CountNode(t->lchild);
	m=CountNode(t->rchild);
	return(n+m+1);
}


int main() 
{
	BiTree *root,*NewTree;
	int depth,Node;
	
	printf("Input:");
	root=creat();
	
//---------------Tree的遍历------------------- 
    printf("\n");
	printf("Tree:\n");
    
	printf("Preorder:");
	preorder(root);
	printf("\n");
	
	printf("inorder:");
	inorder(root); 
	printf("\n");
	
	printf("Postorder:");
	postorder(root); 
	printf("\n"); 
	
//-----Tree复制到NewTree后,NewTree的遍历------
	printf("\n");
	printf("Copy Tree to NewTree:\n");
	printf("NewTree:");
	NewTree=copy(root);
	
	printf("Preorder:");
	preorder(NewTree);
	printf("\n");
	
	printf("inorder:");
	inorder(NewTree); 
	printf("\n");
	
	printf("Postorder:");
	postorder(NewTree); 
	printf("\n"); 
	
//---------计算Tree的深度-----------
    printf("\n"); 
	depth=Depth(NewTree);
	printf("Calculate 'Tree' Depth: %d\n",depth);
	
//---------计算Tree的节点数-----------
	printf("\n"); 
	Node=CountNode(root);
	printf("Calculate 'Tree' NoDE: %d\n",Node);
	
	return 0;
}

输出结果:

错误示例:

在这里插入图片描述
此处大可不必这么去判断t是否为空,如果按此处执行,则当每次递归执行到虚节点处,则会判定树为空,如下图。

在这里插入图片描述


参考:

  1. 数据结构(C语言版,严蔚敏,吴伟民)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Attract1206

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值