C语言实现二叉树的非递归中序遍历
创建一个栈
注意,这个栈的目的时用来保存结点地址的
。因为我们在出栈时,还需判断结点的右节点的情况,如果只是保存结点的值,是无法实现中序遍历的。
现在我们来创建一个栈。首先定义一个栈的结构,不过之前还需定义一个节点结构
节点定义
typedef struct BinaryTreeNode{
int data;
struct BinaryTreeNode *lchild, *rchild;//左右孩子指针
}BinaryTreeNode, *pBinaryTreeNode;
栈结构定义
typedef struct {
pBinaryTreeNode *stack;//栈的指针,由于入栈的是节点地址,所以必须为二级指针
int top;//标识栈顶位置
int stacksize;//标识栈的容量
}MyStack;
栈的操作函数
- 栈的初始化函数。
初始化栈结构的数据成员:确认栈的大小,申请一块栈空间。
void initstack(MyStack *_s,int _stacksize)
{
//1.初始化栈内部变量
_s->stacksize = _stacksize; //确认栈的大小
_s->top = -1; //初始栈顶位置为-1
//2.申请内存空间
_s->stack = (pBinaryTreeNode*)malloc(sizeof(pBinaryTreeNode)*(_s->stacksize));
}
- 栈的Empty函数
判断栈是否为空,为空返回1。为空的条件是栈结构中的数据成员top<0
。
int StackEmpty(MyStack *_s)
{
if (_s->top < 0) return 1;
return 0;
}
- 栈的Push函数
传入树节点的地址。注意栈满了是当栈顶top达到栈的大小stacksize。由于top从0开始,所以是top= stacksize-1为栈满
。
void StackPush(MyStack *_s, pBinaryTreeNode _pdata)
{
if (_s->top == _s->stacksize - 1)
//栈满了
exit(1);
else{
_s->stack[++(_s->top)] = _pdata;
}
}
- 栈的Pop函数
删除栈顶数据。
void StackPop(MyStack *_s)
{
if (StackEmpty(_s) == 1)
//栈为空
exit(1);
else{
_s->top--;
}
}
- 栈的Top函数
返回栈顶数据。
pBinaryTreeNode StackTop(MyStack *_s)
{
if (StackEmpty(_s) == 1)
//栈为空
exit(1);
else{
return _s->stack[_s->top];
}
}
怎样实现非递归中序遍历
从中序遍历的顺序可以看出,先打印的一定是最左节点。所第一步是找到最左节点
,找到之后可以立马打印数据。第二步是判断已打印数据的右节点,为空则继续出栈;不空则重复第一步的操作
。依次循环这两步,直到栈为空。
int inorder(pBinaryTreeNode root){
MyStack s;
initstack(&s, 10);
pBinaryTreeNode current = root;
if (current == nullptr) return 0;
while (current || !StackEmpty(&s)){
if (current){
StackPush(&s, current);
current = current->lchild;
}
else{
current = StackTop(&s);
StackPop(&s);
printf("%d",current->data);//打印数据
current = current->rchild;
}
}
return 1;
}
完整代码和测试结果
完整代码:
#include<stdio.h>
#include<stdlib.h>
//二叉树节点定义
typedef struct BinaryTreeNode{
int data;
struct BinaryTreeNode *lchild, *rchild;//左右孩子指针
}BinaryTreeNode, *pBinaryTreeNode;
//定义栈
typedef struct {
pBinaryTreeNode *stack;
int top;
int stacksize;
}MyStack;
//初始化栈
void initstack(MyStack *_s,int _stacksize)
{
//1.初始化栈内部变量
_s->stacksize = _stacksize;
_s->top = -1;
//2.申请内存空间
_s->stack = (pBinaryTreeNode*)malloc(sizeof(pBinaryTreeNode)*(_s->stacksize));
}
//判断栈是否为空
int StackEmpty(MyStack *_s)
{
if (_s->top < 0) return 1;
return 0;
}
//栈的push操作
void StackPush(MyStack *_s, pBinaryTreeNode _pdata)
{
if (_s->top == _s->stacksize - 1)
//栈满了
exit(1);
else{
_s->stack[++(_s->top)] = _pdata;
}
}
//栈的top操作:返回栈顶指针
pBinaryTreeNode StackTop(MyStack *_s)
{
if (StackEmpty(_s) == 1)
//栈为空
exit(1);
else{
return _s->stack[_s->top];
}
}
//栈的pop操作:删除栈顶数据
void StackPop(MyStack *_s)
{
if (StackEmpty(_s) == 1)
//栈为空
exit(1);
else{
//free(_s->stack[_s->top]);//释放内存
_s->top--;
}
}
//中序遍历
int inorder(pBinaryTreeNode root){
MyStack s;
initstack(&s, 10);
pBinaryTreeNode current = root;
if (current == nullptr) return 0;
while (current || !StackEmpty(&s)){
if (current){
StackPush(&s, current);
current = current->lchild;
}
else{
current = StackTop(&s);
StackPop(&s);
printf("%d",current->data);//打印数据
current = current->rchild;
}
}
return 1;
}
//创建二叉树
pBinaryTreeNode CreatBinaryTree(){
pBinaryTreeNode node;
int _data;
scanf("%d", &_data);
//确认递归的结束的条件
if (_data < 0)//由于是用户输入节点,当用户输入9999时,递归结束
return nullptr;
node = (pBinaryTreeNode)malloc(sizeof(BinaryTreeNode));
node->data = _data;
node->lchild = CreatBinaryTree();//生成左子树
node->rchild = CreatBinaryTree();//生成右子树
return node;
}
int main(){
printf("请按照先序遍历输入二叉树:\n");
//方法一:动态的创建一课树
pBinaryTreeNode rootDyn = nullptr;
rootDyn = CreatBinaryTree();
printf("二叉树创建成功!\n");
printf("\n中序非递归遍历:\n");
inorder(rootDyn);
system("pause");
return 0;
}
打印结果:
注意输入二叉树时,每个数据之间有空格,<0表示空节点。节点的输入是按照树的前序遍历顺序
。上面输入的二叉树如下图所示。
有关如何递归法动态创建一颗二叉树,可参考:递归创建二叉树(C版)。
本人水平有限,欢迎各位朋友批评指正。