算法:
#include <iostream>
#include <stack>
using namespace std;
/*
二叉树的遍历---中序遍历非递归算法
中序 遍历的几种情况
分析1:什么时候访问根、什么时候访问左子树、什么访问右子树
当左子树为空或者左子树已经访问完毕以后,再访问根
访问完毕根以后,再访问右子树。
分析2:为什么是栈,而不是其他队列。
先走到的后访问,后走到的先访问,显然是栈结构
分析3:结点所有路径情况
步骤1:
如果结点有左子树,该结点入栈;
如果结点没有左子树,访问该结点;
步骤2:
如果结点有右子树,重复步骤1;
如果结点没有右子树(结点访问完毕),根据栈顶指示回退,访问栈顶元素,并访问右子树,重复步骤1
如果栈为空,表示遍历结束。
注意:入栈的结点表示,本身没有被访问过,同时右子树也没有被访问过。
分析4:有一个一直往左走入栈的操作
*/
//二叉链表
typedef struct BiNode{
int data;
struct BiNode *lchild, *rchild;
}BiNode, *BiTree;
#if 1
//找到向左走,找到中序遍历的起点
BiNode *goLeft(BiNode *T, stack<BiNode*> &s)
{
if (T == NULL){
return NULL;
}
//判断T有没有左孩子, 没有把T return ;
//如果有 T入栈 ,再往左走
while (T->lchild != NULL){
s.push(T);
T = T->lchild;
}
return T;
}
void inorder2(BiNode *T)
{
BiNode *t = NULL;
stack<BiNode *> s;
t = goLeft(T, s); //如果结点有左子树, 该结点入栈;
while (t){
printf("%d ", t->data); //如果结点没有左子树,访问该结点(就是打印该节点);
//如果 t有右子树 重复步骤1
if (t->rchild != NULL){
t = goLeft(t->rchild, s); //右子树中中序遍历的起点
}
else if (!s.empty()){ //如果t没有右子树 根据栈顶指示 回退
t = s.top(); //获取栈顶元素
s.pop(); //将栈顶元素弹出
}
else{ //如果t没有右子树 并且栈为空,表示遍历结束
t = NULL;
}
}
}
//中序遍历 左根右 Middle order traversal
void inOrder(BiNode *root)
{
if (root == NULL){
return;
}
//遍历左子树
inOrder(root->lchild);
printf("%d ", root->data);//打印根
//遍历右子树
inOrder(root->rchild);
}
/*
t1
/ \
t2 t3
/ /
t4 t5
*/
void test()
{
BiNode t1, t2, t3, t4, t5;
memset(&t1, 0, sizeof(BiNode));
memset(&t2, 0, sizeof(BiNode));
memset(&t3, 0, sizeof(BiNode));
memset(&t4, 0, sizeof(BiNode));
memset(&t5, 0, sizeof(BiNode));
t1.data = 1;
t2.data = 2;
t3.data = 3;
t4.data = 4;
t5.data = 5;
//建立树关系
t1.lchild = &t2; //t1的左孩子为t2
t1.rchild = &t3; //t1的右孩子为t3
t2.lchild = &t4; //t2的左孩子为t4
t3.lchild = &t5; //t3的左孩子为t5
printf("\n 中序遍历 inorder\n");
inOrder(&t1);
printf("\n\n 中序遍历 使用非递归算法\n");
inorder2(&t1);
}
#endif
int main()
{
test();
printf("\n---------hello\n");
system("pause");
}