二叉树的认知

本文介绍了如何使用栈实现二叉树的非递归中序遍历,通过示例代码展示了创建二叉树、遍历和层序遍历的过程,强调了中序遍历需要栈存节点而非数据的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 直接上代码吧,改了好长一段时间,重点在写那个二叉树的非递归遍历,就写了一个中序的(太麻烦了),层序遍历需要队列,中序遍历竟然需要栈,属实蚌埠住了。

中序非递归遍历:

void inorder(BiTNode *t)//中序遍历的非递归算法
{
	BiTNode *temp = t;
	
	while(temp != NULL||S.top != 0)
	{
		while(temp != NULL)//先把左孩子入栈,所有左孩子入栈结束
		{
			Push(temp);
			temp = temp->lchild;
		}
		if(S.top != 0)//左孩子入栈结束,取栈顶,输出栈顶元素,遍历右孩子
		{
			temp = Pop();
			
			printf("%c",temp->data);
			temp = temp->rchild;
		}
	}
	printf("\n");
}

    当时写不对原因是因为自己直接把以前的栈拿来用了,加上层序遍历都是直接存数据,我也没怎么想,后面发现中序遍历不能只存数据,这样的话回不去,原来竟然需要直接存结点,害.......         服了啊!

对了,我创建树的代码长这样:

int CreatBiTree(BiTree &T, char* ch, int &i)//创建二叉树
{
	
	if(ch[i] == '#') 
	{
		T = NULL;
	}
	else
	{
		if(!(T = (BiTNode *)malloc(sizeof(BiTNode))))
		exit(OVERFLOW);
		T->data = ch[i];
		i++;
		CreatBiTree(T->lchild, ch, i);
		i++;
		CreatBiTree(T->rchild, ch, i);
	}
	return 0;
}

这个的意思是只要没检查到#,就一直存左节点,遇到#存右结点,我的例子为ac#de##b##f##

如图:

丑图见谅;

 

总代码:

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

#define MAXTSIZE 100
#define MAXSIZE 100
#define isMyFaith main
#define TRUE 1
#define TURE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef char TElemType;

typedef char SElemType;

typedef int QElemType;
typedef int Status;
typedef int Kurumi;

typedef struct BiNode{
	TElemType data;
	struct BiNode *lchild, *rchild;
}BiTNode, *BiTree;

typedef struct stack 
{
	BiTNode *elements[100];
	int top;
}SqStack;


SqStack S;

typedef struct QNode {  
    BiTree az;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
    QueuePtr front; 
    QueuePtr rear; 
} LinkQueue; //链队

Status InitQueue(LinkQueue &Q) {  //链队初始化
    Q.front = Q.rear = new QNode; 
    Q.front->next = NULL;
    return OK;
}

Status EnQueue(LinkQueue &Q,  BiTree &e) {  //入队
    QueuePtr p;
    p = new QNode; 
    p->az = e;
	 
    p->next = NULL;
    Q.rear->next = p;
    Q.rear = p;

    return OK;
}

Status DeQueue(LinkQueue &Q, BiTree &e) {  //出队
    QueuePtr p;
    if (Q.front == Q.rear)
        return ERROR; 
    p = Q.front->next; 
    e = p->az; 
    
    Q.front->next= p->next;

    if (Q.rear == p)
        
	Q.rear = Q.front;
    delete p;
    return OK;
}

Status QueueEmpty(LinkQueue &Q)
{
	if(Q.front == Q.rear)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

int CreatBiTree(BiTree &T, char* ch, int &i)//创建二叉树
{
	
	if(ch[i] == '#') 
	{
		T = NULL;
	}
	else
	{
		if(!(T = (BiTNode *)malloc(sizeof(BiTNode))))
		exit(OVERFLOW);
		T->data = ch[i];
		i++;
		CreatBiTree(T->lchild, ch, i);
		i++;
		CreatBiTree(T->rchild, ch, i);
	}
	return 0;
}

void setnull()//初始化栈
{
	S.top =0;
}
 
void Push(BiTNode *temp)//入栈操作
{
	S.elements[S.top++] = temp;
}
 
BiTNode *Pop()//取栈顶并出栈顶
{
	return S.elements[--S.top];
}
 
int StackEmpty()//判断空栈
{
	return S.top == 0;
}


void visit(BiTree T)
{
	printf("%c",T->data); 
	
}
Status PreOrderTraverse(BiTree T)
{

	if(T == NULL)  return OK;
	else{
		visit(T);
		PreOrderTraverse(T->lchild);
		PreOrderTraverse(T->rchild);
	}
	return OK;
	
}//先序遍历

Status InOrderTraverse(BiTree T)
{
	if(T == NULL)  return OK;
	else{
		InOrderTraverse(T->lchild);
		visit(T);
		InOrderTraverse(T->rchild);
	}
 } //中序递归遍历

Status PostOrderTraverse(BiTree T)
{
	if(T == NULL)  return OK;
	else{
		PostOrderTraverse(T->lchild);
		PostOrderTraverse(T->rchild);
		visit(T);
	}
 } //后序遍历 
 
void LevelOrder(BiTree b)
{
	BiTree p;
	LinkQueue Q;
	InitQueue(Q); //初始化队列 
	

	EnQueue(Q,b); //根节点指针进入队列 
	while(QueueEmpty(Q)){ //队列不为空,则循环 
		DeQueue(Q, p); //出队结点p; 
		printf("%c", p->data); //访问p 
		if(p->lchild!=NULL) EnQueue(Q,p->lchild);
		//有左节点时将其进队 
		if(p->rchild!=NULL) EnQueue(Q,p->rchild);
		//有右节点时将其进队 
	}
	
	
} //层序遍历 


void inorder(BiTNode *t)//中序遍历的非递归算法
{
	BiTNode *temp = t;
	
	while(temp != NULL||S.top != 0)
	{
		while(temp != NULL)//先把左孩子入栈,所有左孩子入栈结束
		{
			Push(temp);
			temp = temp->lchild;
		}
		if(S.top != 0)//左孩子入栈结束,取栈顶,输出栈顶元素,遍历右孩子
		{
			temp = Pop();
			
			printf("%c",temp->data);
			temp = temp->rchild;
		}
	}
	printf("\n");
}

int Copy(BiTree T, BiTree &NewT){    //复制二叉树 
	if(T == NULL)
	{
		NewT = NULL; return 0;
		
	}
	else{
		NewT = new BiTNode;   NewT->data = T->data;
		Copy(T->lchild, NewT->rchild);
		Copy(T->rchild, NewT->rchild);
	}
} 

int Depth(BiTree T){    //计算树的深度 
	int m = 0, n = 0;
	if(T == NULL) return 0;
	else{
		m = Depth(T->lchild);
		n = Depth(T->rchild);
		if(m > n) return m+1;
		else return n+1;
	}
}

int NodeCount(BiTree T){   //根节点 
	if(T == NULL)
	return 0;
	else 
		return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
} 

int LeafCount(BiTree T){   //叶子结点 
 	if(T == NULL)
		return 0;
	if(T->rchild == NULL && T->lchild == NULL)
	return 1;
	else
	return LeafCount(T->lchild) + LeafCount(T->rchild); 
}

Kurumi isMyFaith()
{
	BiTree T;
	char* tempString = "ac#de##b##f##";
	int a = 0;
	CreatBiTree(T, tempString, a);

	printf("Pre: ");
	PreOrderTraverse(T);
	printf("\nIn:  ");
	InOrderTraverse(T);
	printf("\nPost:  ");
	PostOrderTraverse(T);
	printf("\nLevel:  ");
	LevelOrder(T);
	printf("\nIn2:  ");
	inorder(T);
	return 0;
}

运算结果:

前序遍历Pre: acdebf
中序遍历In:  cedbaf
后序遍历Post:  ebdcfa
层序遍历Level:  acfdeb
中序非递归遍历In2:  cedbaf

完毕!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值