二叉树的创建和遍历

目录

文章目录

前言

一、树是什么?

二、二叉树是什么?

三、创建二叉树

四、遍历方法

1.先序遍历

1.递归方法

 2.非递归

2.中序遍历

1.递归

2.非递归

 3.后序遍历

1.递归

2.非递归

总结


前言

在数据结构中,树是重要的一个章节,它里面含有着很多的思想,我们在很多的地方也会见到它。尤其是二叉树的知识,让我们有很多的用武之地,在这里,我们就了解一下二叉树的创建还有他的前中后序三种遍历方法,后面我还会写一篇关于他的层序遍历,还有一些计算出度入度的方法。

一、树是什么?

是一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

二、二叉树是什么?

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分 [1]  。

二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点 [1]  。(百度定义)

就类型这种的就是二叉树,通俗的来说二叉树就是树只有左孩子,右孩子。 

三、创建二叉树

Tree *Create_Tree()
{
    //先申明一个空指针
	Tree *root=NULL;
	int data;
	scanf("%d", &data);//通过输入的ch是否为特殊符号来判断该节点是否有孩子节点
    //这里可以用任何的特殊字符,根据自己来定义
	if(data == -1){	//不存在孩子节点
		root=NULL;
	}else{
        //当这个数据需要存储的时候要,我们就需要离开开辟空间
		root = (Tree *)malloc(sizeof(Tree));
        //如果开辟失败,就返回
		if(NULL == root){
			printf("创建失败\n");
			return NULL;
		}	
        //将数据存储到根节点里面
		root->data = data;
		root->l_child = Create_Tree();//存在左孩子节点,递归调用本函数,使得左孩子节点先被赋值
		root->r_child = Create_Tree();//存在右孩子节点,递归调用本函数,使得右孩子节点后被赋值
	}
    //最后将该节点返回
	return root;
}

四、遍历方法

递归方法都是很简单的,所以我们在后面的介绍中,对递归的直接简单的介绍,大量精力再非递归上面。

1.先序遍历

1.递归方法

void first(Tree* tree)
{
    //如果树为空的话,就返回
	if(tree==NULL){
		return ;
	}
    //打印该节点的数据
	printf("%d\n",tree->data);
    //递归调用,打印左孩子的
	first(tree->l_child);
     //递归调用,打印右孩子的
	first(tree->r_child);
	
}

 2.非递归

void Nrefirst(Tree* tree)
{
     //先申明一个栈类型的指针,为了后面的操作
	Tree *stack[MAX],*node;
	int top=0;//初始化栈
    //如果树为空的话,就返回
	if(tree==NULL){
		printf("这个树为空\n");
		return ;
	}else{
		top++;//对索引进行操作,栈第一个位置不存储数据
		stack[top]=tree;//将树存到栈里面
        //如果栈为空,就退出循环
		while(top>0){
            //取出栈顶元素
			node=stack[top];
			top--;//对索引进行操作
			printf("%d\n",node->data);//打印该节点的数据
            //将该节点的右孩子先存到栈里面,再把左孩子存到里面,因为栈是先进后出的
			if(node->r_child!=NULL){
				top++;
				stack[top]=node->r_child;
			}
			if(node->l_child!=NULL){
				top++;
				stack[top]=node->l_child;
			}
		}
	}
}

2.中序遍历

1.递归

代码如下(示例):

void Middle(Tree* tree)
{
	if(tree==NULL){
		return ;
	} 
	Middle(tree->l_child);
	printf("%d\n",tree->data);
	Middle(tree->r_child);
	
}

2.非递归

void Nremiddle(Tree* tree)
{
    //先申明一个栈类型的指针,为了后面的操作
	Tree *stack[MAX],*node;
    //初始化栈为空
	int top=0;
    //如果树为空的话,就返回
	if(tree==NULL){
		printf("这个树为空\n");
		return;
	}
    //用另外的指针来存树
	node=tree;
    //树为空,或者栈为空的时候,我们就返回
	while(node!=NULL||top>0){
        //将树的所有节点都先存到栈里面
		while(node!=NULL){
			top++;//我们栈的第一个空间不存储数据
			stack[top]=node;//将数据存储到栈里面
			node=node->l_child;//一直换到左孩子指针为空
		}
        //取出栈顶元素
		node=stack[top];
		top--;//对索引进行操作
		printf("%d\n",node->data);//打印该数据
		node=node->r_child;//对有孩子进行存储
	}
}

 3.后序遍历

1.递归

void last(Tree* tree)
{
	if(tree==NULL){
		return;
	} 
	last(tree->l_child);
	last(tree->r_child);
	printf("%d\n",tree->data);
	
}

2.非递归

void Nrelast(Tree* tree)
{
    //初始化栈,定义一个虚拟指针r,利用node把树存进去
	Tree *stack[MAX],*node=tree,*r=NULL;
	int top=0;//初始化栈为空
     //如果树为空的话,就返回
	if(tree==NULL){
		printf("这个树为空\n");
		return;
	}
    //树为空,或者栈为空的时候,我们就退出循环
	while(node||top>0){
        //先把左边的节点全部存到栈里面
		while(node){
			stack[top]=node;
			top++;//对索引操作
			node=node->l_child; 
		}
        //因为之前的加一,所以这里我们需要减1
		node=stack[top-1];
        //此节点没有右孩子或者右孩子已经访问过
		if(NULL==node->r_child||node->r_child==r){
			printf("%d\n",node->data);
			top--;
			r=node;//记录最近访问过的节点
			node=NULL;//节点访问过的节点
		}else{
			node=node->r_child;//右孩子存在则指向右孩子,重复上面操作
		}
	}
}

总结

二叉树是一个重要的数据结构,所以我们要认真了解,在整个过程中,我们要人认识到,栈的作用,所以我们对栈的索引,要仔细的引用,思考到每一步的操作。接下来就分享所有的代码。

#include<stdio.h>
#include<stdlib.h>
#define MAX 10
typedef struct node{
	int data;
	struct node *l_child;
	struct node *r_child;
}Tree;
void Middle(Tree* tree);//中序遍历 
void Nremiddle(Tree* tree);//非递归 非递归中序遍历 
void first(Tree* tree);//先序遍历 
void Nrefirst(Tree* tree);//非递归 前序遍历 
void last(Tree* tree);//后序遍历 
void Nrelast(Tree* tree);//非递归 后序遍历 
Tree *Create_Tree();//创建二叉树 
int main()
{
	Tree*tree;
	tree=Create_Tree();
	printf("中序遍历\n");
	Middle(tree);
	printf("先序遍历\n");
	first(tree);
	printf("后序遍历\n");
	last(tree);
	printf("非递归中序遍历\n");
	Nremiddle(tree);
	printf("非递归先序遍历\n");
	Nrefirst(tree);
	printf("非递归后序遍历\n");
	Nrelast(tree);
}

void Middle(Tree* tree)
{
	if(tree==NULL){
		return ;
	} 
	Middle(tree->l_child);
	printf("%d\n",tree->data);
	Middle(tree->r_child);
	
}
void first(Tree* tree)
{
    //如果树为空的话,就返回
	if(tree==NULL){
		return ;
	}
    //打印该节点的数据
	printf("%d\n",tree->data);
    //递归调用,打印左孩子的
	first(tree->l_child);
     //递归调用,打印右孩子的
	first(tree->r_child);
	
}
void last(Tree* tree)
{
	if(tree==NULL){
		return;
	} 
	last(tree->l_child);
	last(tree->r_child);
	printf("%d\n",tree->data);
	
}
Tree *Create_Tree()
{
    //先申明一个空指针
	Tree *root=NULL;
	int data;
	scanf("%d", &data);//通过输入的ch是否为特殊符号来判断该节点是否有孩子节点
    //这里可以用任何的特殊字符,根据自己来定义
	if(data == -1){	//不存在孩子节点
		root=NULL;
	}else{
        //当这个数据需要存储的时候要,我们就需要离开开辟空间
		root = (Tree *)malloc(sizeof(Tree));
        //如果开辟失败,就返回
		if(NULL == root){
			printf("创建失败\n");
			return NULL;
		}	
        //将数据存储到根节点里面
		root->data = data;
		root->l_child = Create_Tree();//存在左孩子节点,递归调用本函数,使得左孩子节点先被赋值
		root->r_child = Create_Tree();//存在右孩子节点,递归调用本函数,使得右孩子节点后被赋值
	}
    //最后将该节点返回
	return root;
}
void Nremiddle(Tree* tree)
{
    //先申明一个栈类型的指针,为了后面的操作
	Tree *stack[MAX],*node;
    //初始化栈为空
	int top=0;
    //如果树为空的话,就返回
	if(tree==NULL){
		printf("这个树为空\n");
		return;
	}
    //用另外的指针来存树
	node=tree;
    //树为空,或者栈为空的时候,我们就返回
	while(node!=NULL||top>0){
        //将树的所有节点都先存到栈里面
		while(node!=NULL){
			top++;//我们栈的第一个空间不存储数据
			stack[top]=node;//将数据存储到栈里面
			node=node->l_child;//一直换到左孩子指针为空
		}
        //取出栈顶元素
		node=stack[top];
		top--;//对索引进行操作
		printf("%d\n",node->data);//打印该数据
		node=node->r_child;//对有孩子进行存储
	}
}
void Nrefirst(Tree* tree)
{
     //先申明一个栈类型的指针,为了后面的操作
	Tree *stack[MAX],*node;
	int top=0;//初始化栈
    //如果树为空的话,就返回
	if(tree==NULL){
		printf("这个树为空\n");
		return ;
	}else{
		top++;//对索引进行操作,栈第一个位置不存储数据
		stack[top]=tree;//将树存到栈里面
        //如果栈为空,就退出循环
		while(top>0){
            //取出栈顶元素
			node=stack[top];
			top--;//对索引进行操作
			printf("%d\n",node->data);//打印该节点的数据
            //将该节点的右孩子先存到栈里面,再把左孩子存到里面,因为栈是先进后出的
			if(node->r_child!=NULL){
				top++;
				stack[top]=node->r_child;
			}
			if(node->l_child!=NULL){
				top++;
				stack[top]=node->l_child;
			}
		}
	}
}
void Nrelast(Tree* tree)
{
    //初始化栈,定义一个虚拟指针r,利用node把树存进去
	Tree *stack[MAX],*node=tree,*r=NULL;
	int top=0;//初始化栈为空
     //如果树为空的话,就返回
	if(tree==NULL){
		printf("这个树为空\n");
		return;
	}
    //树为空,或者栈为空的时候,我们就退出循环
	while(node||top>0){
        //先把左边的节点全部存到栈里面
		while(node){
			stack[top]=node;
			top++;//对索引操作
			node=node->l_child; 
		}
        //因为之前的加一,所以这里我们需要减1
		node=stack[top-1];
        //此节点没有右孩子或者右孩子已经访问过
		if(NULL==node->r_child||node->r_child==r){
			printf("%d\n",node->data);
			top--;
			r=node;//记录最近访问过的节点
			node=NULL;//节点访问过的节点
		}else{
			node=node->r_child;//右孩子存在则指向右孩子,重复上面操作
		}
	}
}

  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树是一种常用的数据结构,它由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。创建二叉树的方法有多种,最常用的是递归和非递归方法。 递归创建二叉树的过程如下:首先定义一个二叉树节点的结构,包含节点值、左孩子和右孩子三个属性。然后利用递归函数,根据给定的数列或输入,依次创建节点并建立它们之间的关系。具体步骤如下:若输入为空,则返回空节点;否则,创建一个新节点作为当前节点,将当前节点的值设为输入的第一个值,将输入的余下部分分为左右两个部分,第一个部分为左子树的输入,第二个部分为右子树的输入。然后递归调用该函数,分别构建左右子树,并将返回的左右子树作为当前节点的左右孩子。 二叉树遍历有三种方式:前序遍历、中序遍历和后序遍历。前序遍历先访问根节点,然后遍历左子树,最后遍历右子树;中序遍历遍历左子树,然后访问根节点,最后遍历右子树;后序遍历遍历左子树,然后遍历右子树,最后访问根节点。对于每个节点,遍历方法是一样的,先访问当前节点后,再递归地遍历左右子树。 在编程竞赛平台pta上,可以使用C++或其他编程语言来实现二叉树创建遍历。注意在创建二叉树时,需要读入并解析输入,构建二叉树并返回根节点。而在遍历二叉树时,可以定义一个递归函数,在访问每个节点时,先输出节点值,然后递归地遍历左右子树。可以根据具体问题的要求,选择不同的遍历方式来实现对二叉树节点的访问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值