二叉树的创建、三种递归遍历方式、利用栈的非递归中序遍历的代码实现

本文详细介绍了C语言中的二叉树结构,包括二叉树节点定义、栈的结构及其功能,以及递归和非递归遍历二叉树的方法,重点展示了先序遍历和中序遍历的实现,以及栈在非递归遍历中的应用。
摘要由CSDN通过智能技术生成

1、全部代码编程方式 , 直接上代码

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

#define MAXSIZE 100

//二叉树 
typedef struct BiTNode{
	int data;
	struct BiTNode *lchild;
	struct BiTNode *rchild;
	
}BiTNode, *BiTree; //定义的时候有写typedef,就可以直接使用这两个变量名定义 

//栈 
typedef struct stack{
	BiTNode data[MAXSIZE];
	int top; //初始指向-1 指针停留在栈顶元素上 0是栈底元素 99是栈顶元素  
}SqStack;


/*====================================================下面是栈的功能=================================================*/ 

/**
	初始化栈 
*/
void initStack(SqStack *s){
	s->top = -1;
}

//栈是否为空 
int isEmpty(SqStack s){
	if(s.top <= -1) return 1;
	return 0;
}

//栈是否已满 
int isFull(SqStack s){
	if(s.top >= 99) return 1;
	return 0;
}

/**
	入栈 
*/
int push(SqStack *s,BiTree e){
	if(isFull(*s)) return 0;
	
	s->data[++(s->top)] = *e;	
	return 1; 
	
}

/**
	出栈 
*/
int pop(SqStack *s,BiTNode *e){
	if(isEmpty(*s)) return 0;
	
	*e = s->data[s->top--];
	return 1;
}

/**
	从上到下打印栈元素
	每5个一换行 
*/
void printStack(SqStack s){
	int n = s.top; //n为当前头指针 向下遍历 
	int count = 0; //计数器 
	for(; n >= 0 ; n--){
		BiTNode t = s.data[n]; //获取栈顶指针的树节点的data值 
		printf("%d\t",t.data);
		if(++count % 5 == 0) printf("\n");
	}
} 
/*===================================================栈的功能在这结束=================================================*


/*====================================================下面是树的功能 ================================================*/ 

/**
	创建结点 
*/
BiTNode* createNode(int data){
	BiTNode* newNode = (BiTNode*)malloc(sizeof(BiTNode));
	newNode->data = data;
	newNode->lchild = NULL;
	newNode->rchild = NULL;
	
	return newNode;
}

/**
	插入结点 
	(其实这样创建出来的是一颗二叉搜索树) 
*/
BiTNode* insertNode(BiTree root , int data){
	if(root == NULL) return createNode(data); //树为空 直接创建根节点
	
	//树不为空
	if(data < root->data){
		//插入的值小于当前结点值 递归往左子树放
		root->lchild = insertNode(root->lchild,data); //记得r->l '=' 否则不会挂到树上 
	}else{
		//否则递归插入右子树
		root->rchild = insertNode(root->rchild,data); 
	}
	return root;
}

/*
	访问结点 
*/
void visit(BiTree tree){
	printf("%d ",tree->data);
}

/**
	递归: 先序遍历 
*/
void preTraversal(BiTree tree){
	if(tree == NULL) return;
	visit(tree); //放在这里是前序 
	preTraversal(tree->lchild);
	//放在这里是中序 
	preTraversal(tree->rchild);
	//放在这里是后序 
	return;
}

/**
	********************** 
	**非递归遍历: 使用栈**
	**       中序       ** 
	**********************
*/
void inTraByStack(BiTree tree){
	//建立一个遍历指针 
	//结点弹出栈后依靠它指向弹出的元素 从而实现回到上一层的效果 
	BiTree p = tree; 
	SqStack s;
	initStack(&s);
	
	while(p || !isEmpty(s)){
		if(p){
			visit(q);
			push(&s,p); //注意是结点压入栈 
			p = p->lchild; //向左孩子
		}else{
			BiTree q; //王道书上写的应该有点问题 这里需要一个额外变量来接收 不然会出问题 
			pop(&s,q); //栈顶元素弹出之后 p就指向这个元素了 
			visit(q);
			p = q->rchild; //q是弹出的栈顶元素,那么此时就相当于反倒上一层的父节点了,让p等于父节点的右子树 再重新开始遍历 
			 
		}
		
	}
	
}

/*============================================树的功能在这里结束===========================================*/ 


int main(){
	BiTree root = createNode(5);
	
	insertNode(root,2);
	insertNode(root,4);
	insertNode(root,7);
	insertNode(root,8);
	insertNode(root,1);
	insertNode(root,3);
	/*
				5
	          /   \
	         2     7
	        / \     \
	       1   4     8
	       	  /
	         3
	*/

//	preTraversal(root);
//printf(" ::%d ",root->data); 	
	inTraByStack(root); 
	

	
//测试栈 
//	SqStack s;
//	initStack(&s);
//	
//	int i = 0;
//	
//	while(!isFull(s)){
//		push(&s,i++);
//	}
//	printStack(s);
//	
//	int e;
//	while(!isEmpty(s)){
//		pop(&s,&e);
//		printf("%d\t",e);
//	}
		
	
	return 0;	
} 
1.1 递归遍历代码部分

/**
	递归: 先序遍历 
*/
void preTraversal(BiTree tree){
	if(tree == NULL) return;
	visit(tree); //放在这里是前序 
	preTraversal(tree->lchild);
	//放在这里是中序 
	preTraversal(tree->rchild);
	//放在这里是后序 
	return;
}
1.2 中序非递归遍历(非递归的三种遍历方式写法不像递归变化那么简单 后续更新)
/**
	********************** 
	**非递归遍历: 使用栈**
	**       中序       ** 
	**********************
*/
void inTraByStack(BiTree tree){
	//建立一个遍历指针 
	//结点弹出栈后依靠它指向弹出的元素 从而实现回到上一层的效果 
	BiTree p = tree; 
	SqStack s;
	initStack(&s);
	
	while(p || !isEmpty(s)){
		if(p){
			visit(q);
			push(&s,p); //注意是结点压入栈 
			p = p->lchild; //向左孩子
		}else{
			BiTree q; //王道书上写的应该有点问题 这里需要一个额外变量来接收 不然会出问题 
			pop(&s,q); //栈顶元素弹出之后 p就指向这个元素了 
			visit(q);
			p = q->rchild; //q是弹出的栈顶元素,那么此时就相当于反倒上一层的父节点了,让p等于父节点的右子树 再重新开始遍历 
			 
		}
		
	}
	
}


2.力扣递归写法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void inorder(struct TreeNode* root,int ans[], int *index){
    if(root){
        inorder(root -> left,ans,index);
        ans[(*index)++] = root -> val;
        inorder(root -> right,ans,index);
    }
}

int* inorderTraversal(struct TreeNode* root, int* returnSize){
    int index = 0 ;

    if(root){
        static int ans[100] = {-1}; //或者是静态分配数组
        // int *ans = malloc(sizeof(int) * 101); //或者是动态分配内存
        int index = 0;
        inorder(root,ans,&index);
        *returnSize = index;
        return ans;
    }
    else{
        *returnSize = 0;
        return NULL;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值