//DFS_without_Recursion
void preOderNonRec(BTNode* p_root)
{
if(p_root != NULL)
{
//1)创建并初始化 实现“深度”遍历顺序所需的栈————————————
BTNode* Stack[MAX_SIZE];//栈的线性存储
int stack_top = -1;//初始化栈顶指针
//——————————————————————————————————————————————
//2)深度遍历——————————————————————————————————————
//2.0)要完成图的遍历,需要一个指针来指向图的顶点
BTNode* p_Gnode = NULL;
//2.1)将第一个结点入栈—————————————————————
stack_top ++;//栈顶指针移至栈底
Stack[stack_top] = p_root;//访问结点入栈
//2.0)~2.1)为遍历准备阶段——————————————————
//2.2)深度优先遍历实现(算法核心):访问栈顶-> 入栈右子-> 入栈左子(一定要最后入栈左子,这样循环下次访问栈顶为左子)————
while(stack_top != -1)//栈不为空,循环访问
{
//2.2.1 先执行print操作⇔访问根节点—————————
p_Gnode = Stack[stack_top];
Visit(p_Gnode);
//—————————————————————————————————————
//2.2.2 访问完成后,将访问完成的节点信息 "伪出栈"(注意此时还没有将栈顶信息删除)——————
stack_top--;//⭐️ 注意三个⭐️的配合可以实现栈的出入
//——————————————————————————————————————————————————————————————————————
if(p_Gnode->r_child != NULL)//若右子存在
{
//栈顶x-1上移,到达栈顶x,对当前的栈顶x完成出栈和新入栈———————————————————————————
stack_top ++;//⭐️栈顶上移,到达栈顶x,用来实现覆盖已经完成访问的栈顶元素
Stack[stack_top] = p_Gnode->r_child;//覆盖栈顶 ⇔ 同时完成出栈和入栈操作
}
//———————————————————————————————————————————————————————————————————————————————
if(p_Gnode->l_child != NULL)//若左子存在,入栈左子,使栈顶为左子,下次循环直接访问栈顶(左子)
{
stack_top ++;//⭐️栈顶上移,若上一个if执行则新入栈不覆盖;若上一个if不符合则覆盖.
Stack[stack_top] = p_Gnode->l_child;//执行覆盖栈顶即 出栈+入栈
}
//若左右子均不存在则完成栈顶下移
}
//——————————————————————————————————————————————————————————————————————————————————————————————
}
}
这里要注意用循环模拟递归,在自定义栈中想完成"根左右"的访问顺序的前序遍历,要通过先入栈右子树,再入栈左子树,只有这样如果叶子结点以叶子结点的父亲节点的左子树形式存在的情况下才能直接访问这个左子树,因为每次循环要做的访问是访问栈顶然后再入栈.