数据结构 6.x章:非递归遍历二叉树(自己建栈)(c语言)

void InOrderTraverse(BiTree T)
此处 是一种非递归中序遍历二叉树的方法,利用了栈的数据结构实现。具体步骤如下:

首先定义一个栈S和指针p指向二叉树T的根节点。

然后进行循环遍历,当p不为空时,表示当前节点还有左子树未被访问,将当前节点压入栈中,然后指向其左子树。

当p为空时,表示当前节点的左子树已经遍历完成,从栈中弹出该节点,访问该节点,并将指针p指向其右子树。

遍历过程中,只要栈不为空或p不为空,就需要继续进行循环。

值得注意的是,在每次弹出节点时,需要将弹出元素的指针保存在另一个变量q中,防止丢失节点信息。

这种方法可以避免递归操作占用过多的栈空间,适用于需要遍历大型二叉树的场景。但是,由于需要频繁进行栈操作,因此时间复杂度相对于递归遍历会稍微高一些。

复杂度分析

在最坏情况下,即二叉树为满二叉树时,该算法遍历所有节点,时间复杂度为O(n),其中n为节点数。

在空间复杂度方面,使用了一个栈S作为辅助空间,它的最大容量取决于二叉树的深度,所以空间复杂度为O(h),其中h为二叉树的高度。当二叉树为非常不平衡的情况下,h可能接近于n,此时空间复杂度为O(n);当二叉树为平衡二叉树时,h近似于log(n),此时空间复杂度为O(log n)。

因此,该算法在时间复杂度和空间复杂度方面都具有较好的性能表现,是一种常用的遍历二叉树的方法之一。
在空间复杂度方面,使用了一个栈S作为辅助空间,它的最大容量取决于二叉树的深度,所以空间复杂度为O(h),其中h为二叉树的高度。当二叉树为非常不平衡的情况下,h可能接近于n,此时空间复杂度为O(n);当二叉树为平衡二叉树时,h近似于log(n),此时空间复杂度为O(log n)。

因此,该算法在时间复杂度和空间复杂度方面都具有较好的性能表现,是一种常用的遍历二叉树的方法之一。

代码如下:

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

#define OK 1
#define OVERFLOW -1
#define ERROR 0
#define Status int
#define MAXSIZE 30

//二叉树定义 
typedef struct BiTNode
{
	int data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

//栈定义 
typedef struct stack
{
	BiTree *base;
	BiTree *top;
	int stacksize;
}SqStack, *Stack;

BiTree CreateBiTNode(int data);
void InsertBiTNode(BiTree *T, int data); 
bool isBiTreeEmpty(BiTree T);
bool isStackEmpty(Stack S);
void InOrderTraverse(BiTree T);
Stack InitStack(void);
Status Push(Stack S, BiTree e);
Status Pop(Stack S, BiTree *e);
BiTree GetTop(Stack S);

int main(int argc, char *argv[])
{
	BiTree T = NULL;
	
	//给空树插入节点建立树T 
	InsertBiTNode(&T, 14);
	InsertBiTNode(&T, 45);
	InsertBiTNode(&T, 66);
	InsertBiTNode(&T, 73);
	InsertBiTNode(&T, 89);
	InsertBiTNode(&T, 38);
	InsertBiTNode(&T, 90);
	InsertBiTNode(&T, 0);
	
	//调用函数实现非递归中序遍历(借助栈) 
	printf("非递归中序遍历二叉树T:  "); 
	InOrderTraverse(T);
	return 0;
}

//建立新节点
BiTree CreateBiTNode(int data)
{
	BiTree tempNode = (BiTree)malloc(sizeof(BiTNode));
	if(tempNode == NULL)
	{
		printf("内存不足,分配内存失败,节点 %d 建立失败\n", data);
		return NULL;
	}//of if
	tempNode->data = data;
	tempNode->lchild = NULL;
	tempNode->rchild = NULL;
	return tempNode; 
 }//of CreateBiTNode()

//插入节点
void InsertBiTNode(BiTree *T, int data)
{
	if(*T == NULL)
	{
		*T = CreateBiTNode(data);
		return;
	}//of if
	else if(data < (*T)->data)
	{
		InsertBiTNode(&((*T)->lchild), data);
	}//of else if
	else if(data > (*T)->data)
	{
		InsertBiTNode(&((*T)->rchild), data);
	}//of else if
	else
	{
		printf("%d 已存在,无需再次插入.\n", data);
		return;
	}// of else
}//of InsertBiTNode()

//二叉树判空
bool isBiTreeEmpty(BiTree T) 
{
	if(T == NULL)
	{
		return true;
	}//of if
	return false;
}//of isBiTreeEmpty()
 
//非递归中序遍历 
void InOrderTraverse(BiTree T)
{
	Stack S = InitStack();
	BiTree p = T;
	BiTree q = (BiTree)malloc(sizeof(BiTNode));
	while(p || !isStackEmpty(S))
	{
		if(p)
		{
			Push(S, p);
			p = p->lchild;
		}
		else
		{
			Pop(S, &q);
			printf("%d ", q->data);
			p = q->rchild;
		}
	}
}

//初始化栈
Stack InitStack(void)
{
	Stack S = (Stack)malloc(sizeof(SqStack));
	S->base = (BiTree *)malloc(MAXSIZE*sizeof(BiTree));
	if(S->base == NULL)
	{
		printf("内存不够,栈S分配内存失败.\n");
		exit(OVERFLOW);
	}//of if
	S->top = S->base;
	S->stacksize = MAXSIZE;
	return S;
}//of InitStack()

//入栈
Status Push(Stack S, BiTree e)
{
	if(S->top - S->base == S->stacksize)
	{
		printf("栈S已满,%d 压栈失败", e);
		return ERROR;
	}//of if
	*(S->top)++ = e;
	return OK;
}//of Push()

//出栈
Status Pop(Stack S, BiTree *e) 
{
	if(S->base == S->top)
	{
		printf("栈S为空,无可出栈元素\n");
		return ERROR;		//栈空 
	}//of if
	*e = *--(S->top);
	return OK; 
}//of Pop()

//取栈顶元素
BiTree GetTop(Stack S)
{
	if(S->base != S->top)
	{
		return *(S->top - 1);
	}//of if
 } //of GetTop()

//栈判空
bool isStackEmpty(Stack S)
{
	if(S->base == S->top)
	{
		return true;
	}//of if
	return false;
 } //of isStackEmpty()
 

运行结果:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ever free

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值