二叉树的创建和递归、非递归遍历

  • 复习一下二叉树

二叉树的叶子结点总是比双分支结点多一个。
满二叉树:如果有H层,则总结点个数为2H(次方)-1,每一层有2H-1(次方)个结点。

  • 二叉树的创建

在这里插入图片描述

  • 结点信息

typedef struct node{
int data; // 存放此结点的值
struct node * left; // 指向此结点的左子女
struct node * right; // 指向此结点的右子女
}BTNode;

  • 二叉树的非递归先序遍历

分析:

  • 由于先序遍历的顺序是根、左、右,所以步骤是:先输出根结点的值,然后根结点变为左结点,但是这时如果不保存右结点的值,就会导致右边丢失再也找不回来,所以需要存储。
  • 由于这些结点是先进后出,后进先出,所以用栈来存储。
  • 也需要在栈中存储左子女,因为左子女出去了,就知道现在该它的右子女了。
  • 栈中存储:先存右子女,再存左子女,根提前放入栈中。

算法描述:

  • 创建栈:
    BTNode ** s; // 声明一个栈
    s = (BTNode **) malloc((N+1)*sizeof(BTNode *));// 创建栈
    int top = -1; // 栈顶指针
  • 初始化:
    s[++top] = root; // 根结点入队
  • 实现:
    while(栈不空){
    p = 出栈元素;
    输出此结点的值;
    有右子女,右子女入栈;
    有左子女,左子女入栈;
    }

代码:

# include <stdio.h>
# include <stdlib.h>
# define N 9

//定义结构体:结点信息 
typedef struct node{
	int data;				// 存放此结点的值 
	struct node * left;		// 指向此结点的左子女 
	struct node * right;	// 指向此结点的右子女 
}BTNode; 					// 结构体名为BTNode 

BTNode *  CreatTree(int[],int);
void Forder(BTNode * root);
void InOrder(BTNode * root);
void LastOrder(BTNode * root);
void Forder2(BTNode * root);

int main(void){
	BTNode * root;					// 存放此二叉树的根结点 
	int A[8] = {3,2,5,8,4,7,6,9};	// 这里直接固定了建立二叉树的值  
	root = CreatTree(A, 8);			// 调用创建二叉树的函数 
	printf("\n");
	
	Forder(root);		printf("\n");	// 递归先序遍历二叉树  
	InOrder(root);		printf("\n");	// 递归中序遍历二叉树,可得到升序序列 
	LastOrder(root);	printf("\n");	// 递归后序遍历二叉树 
	
	Forder2(root);		printf("\n");	// 非递归先序遍历二叉树 
	
	return 0;
} 

BTNode *  CreatTree(int A[], int n){
	int i;							// 用于下面的循环变量 
	BTNode * p, * root;						// 当前刚刚创建的结点
	// 创建根结点
	root = (BTNode *) malloc (sizeof(BTNode));
	root->data = A[0];
	root->left = root->right = NULL; 
	
	// 创建其他结点
	for(i = 1; i < n; i++){
		BTNode * cp, * pa; 			//cp,pa用来找刚创建的结点刚放在哪里,pa指向此结点的双亲结点,具体如下
		// 创建新结点 
		p = (BTNode *)malloc(sizeof(BTNode));   
		p->data = A[i];
		p->left = p->right = NULL;
		// 找此结点该放在什么位置
		cp = root;
		while(cp){
			pa = cp; // 每次pa都先保存cp的位置,cp再往下找,直到叶子结点
			if(cp->data > p->data) cp = cp->left;	// 值比根小,向左 
			else	cp = cp->right;					// 反之,向右 
		} 
		if(pa->data > p->data){ // 判断挂在左还是右 
			pa->left = p; 
		}else{
			pa->right = p;
		}	
	} 
	return root;
} 
/*
malloc:
函数原型:void *malloc(unsigned int num_bytes); 
分配长度为num_bytes字节的内存块
作用:当无法知道内存具体的位置时,想要绑定真正的内存空间,就要用到malloc()函数
同时也利用了内存的碎片内存*/

// 递归先序遍历二叉树 (根左右)
void Forder(BTNode * root){
	if(root){
		printf("%5d",root->data);
		Forder(root->left);
		Forder(root->right);
	}
} 
// 递归中序遍历二叉树 (左根右)
void InOrder(BTNode * root){
	if(root){
		InOrder(root->left);
		printf("%5d",root->data);
		InOrder(root->right);
	}
} 
// 递归后序遍历二叉树 (左右根)
void LastOrder(BTNode * root){
	if(root){
		LastOrder(root->left);
		LastOrder(root->right);
		printf("%5d",root->data);
	}
} 

// 非递归先序遍历 
void Forder2(BTNode * root){
	BTNode ** s; 			// 声明一个栈
	int top = -1; 			// 栈顶指针
	BTNode * p;				// 指向当前结点
	// 创建栈
	s = (BTNode **) malloc((N+1)*sizeof(BTNode *));
	// 初始化栈
	s[++top] = root; 		// 根结点入队 
	// 非递归先序遍历
	while(top != -1){ 		// 队不空 
		p = s[top--];		// 从栈顶取出一个结点输出
		printf("%5d",p->data);	//输出结点
		if(p->right)	s[++top] = p->right;	// 如果右节点不为空,入队
		if(p->left) 	s[++top] = p->left;		// 如果左节点不为空,入队 
	} 
	free(s);	// 释放栈,因为malloc分配的空间需要自己释放。 
} 
  • 二叉树的非递归中序遍历

基本思想:根结点先入栈从根结点一直向左走,走的过程入栈,直到左子树为空则访问。然后退栈,查看是否有右指针,若有则以其为根再找最左下结点,否则访问

  • 二叉树的非递归后序遍历

基本思想:把先序的输出放在后面,刚开始初始化时入栈三个,一个是根,一个是根的右,一个是根的左。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值