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()
运行结果: