在网上看了很多的人写的二叉树的非递归的遍历,但是能运行的正确的并不多。感谢hackbuteer1 前辈 写出了这样清晰和完美的代码。
特转载和保存于此。
转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/6583988
先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序、中序、后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组队列,分别使用了front和rear两个数组的下标来表示入队与出队,还有两个操作就是求二叉树的深度、结点数。。。
运行效果图如下:
分别输入:
1
2
4
#
#
5
#
#
3
6
#
#
7
#
#
就可以构造如下图所示的二叉树了。。
后序遍历非递归的另外一种写法:
转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/6583988
#include
#include
#include
using namespace std;
//二叉树结点的描述
typedef struct BiTNode
{
char data;
struct BiTNode *lchild, *rchild; //左右孩子
}BiTNode, *BiTree;
//按先序遍历创建二叉树
//BiTree *CreateBiTree() //返回结点指针类型
//void CreateBiTree(BiTree &root) //引用类型的参数
//为什么使用二级指针作为函数的参数,因为要改变指针,就需要用二级指针作为参数,如果要改变二级指针,就需要用三级指针作为参数。
void CreateBiTree(BiTNode **root) //二级指针作为函数参数
{
char ch; //要插入的数据
scanf_s("\n%c", &ch, 1);
//cin>>ch;
if (ch == '#')//如果输入的要是'#'运算符,那么我就让root等于空。相当于root没有左孩子,或者右孩子。
*root = NULL;
else
{
*root = (BiTNode *)malloc(sizeof(BiTNode));
(*root)->data = ch;
printf("请输入%c的左孩子:", ch);
CreateBiTree(&((*root)->lchild));
printf("请输入%c的右孩子:", ch);
CreateBiTree(&((*root)->rchild));
}
}
//前序遍历的算法程序
void PreOrder(BiTNode *root)
{
if (root == NULL)
return;
printf("%c ", root->data); //输出数据
PreOrder(root->lchild); //递归调用,前序遍历左子树
PreOrder(root->rchild); //递归调用,前序遍历右子树
}
//中序遍历的算法程序
void InOrder(BiTNode *root)
{
if (root == NULL)
return;
InOrder(root->lchild); //递归调用,前序遍历左子树
printf("%c ", root->data); //输出数据
InOrder(root->rchild); //递归调用,前序遍历右子树
}
//后序遍历的算法程序
void PostOrder(BiTNode *root)
{
if (root == NULL)
return;
PostOrder(root->lchild); //递归调用,前序遍历左子树
PostOrder(root->rchild); //递归调用,前序遍历右子树
printf("%c ", root->data); //输出数据
}
/*【思想非常重要】
二叉树的非递归前序遍历,前序遍历思想:先让根进栈,只要栈不为空,就可以做弹出操作,
每次弹出一个结点,记得把它的左右结点都进栈,记得右子树先进栈,这样可以保证右子树在栈中总处于左子树的下面。
*/
void PreOrder_Nonrecursive(BiTree T) //先序遍历的非递归 ------------方法一
{//注意参数T的类型是BiTree是一个BiTNode*指针类型
if (!T)//如果指针为NULL,那么返回
return;
stack s;
s.push(T);//首先把树的根节点压入到栈中。
while (!s.empty())//只要栈不为空
{
BiTree temp = s.top();//那么我就取出元素
cout << temp->data << " ";//打印元素
s.pop();//弹出
if (temp->rchild)//如果弹出的这个元素有右孩子,那么就把右孩子压入
s.push(temp->rchild);
if (temp->lchild)//如果弹出的这个元素有左孩子,那么就把这个左孩子压入
s.push(temp->lchild);
}
}
void InOrderTraverse1(BiTree T) // 中序遍历的非递归
{
if (!T)//如果根节点为空,那么直接返回
return;
BiTree curr = T; // 指向当前要检查的节点
stack s;
while (curr != NULL || !s.empty())
{
while (curr != NULL)
{
s.push(curr);//压入当前节点
curr = curr->lchild;//让当前的节点变成,当前节点的根节点。
}//while
if (!s.empty())
{
curr = s.top();
s.pop();
cout << curr->data << " ";
curr = curr->rchild;
}
}
}
//比如下面树,当4在栈顶的时候弹出4,然后4->rchild==NULL,然后就不压入栈中任何元素,
//然后再次执行到if(!s.empty())的时候弹出2,然后2->rchild=5;这个时候就可以把5压入到栈中。
/*
1
/ \
2 3
/ \ / \
4 5 6 7
*/
/*
【思想非常重要】
设置两个栈,把根压入s1栈,只要s1不为空,那么就弹出来,同时把这个元素压入到s2中
然后把这个元素的左孩子压入栈s1,然后把这个元素的右孩子压入栈s2*/
void PostOrder_Nonrecursive(BiTree T) // 后序遍历的非递归 双栈法
{
stack s1, s2;
BiTree curr; // 指向当前要检查的节点
s1.push(T);
while (!s1.empty()) // 栈空时结束
{
curr = s1.top();
s1.pop();
s2.push(curr);
if (curr->lchild)
s1.push(curr->lchild);
if (curr->rchild)
s1.push(curr->rchild);
}
while (!s2.empty())//最后所有的元素都在栈s2中然后依次弹出就可以了。
{
printf("%c ", s2.top()->data);
s2.pop();
}
}
int visit(BiTree T)
{
if (T)
{
printf("%c ", T->data);
return 1;
}
else
return 0;
}
void LeverTraverse(BiTree T) //非递归层次遍历二叉树
{
queue Q;
BiTree p;
p = T;
if (visit(p) == 1)
Q.push(p);
while (!Q.empty())
{
p = Q.front();
Q.pop();
if (visit(p->lchild) == 1)
Q.push(p->lchild);
if (visit(p->rchild) == 1)
Q.push(p->rchild);
}
}
int depth(BiTNode *T) //树的深度
{
if (!T)
return 0;
int d1, d2;
d1 = depth(T->lchild);
d2 = depth(T->rchild);
return (d1 > d2 ? d1 : d2) + 1;
//return (depth(T->lchild)>depth(T->rchild)?depth(T->lchild):depth(T->rchild))+1;
}
int CountNode(BiTNode *T)
{
if (T == NULL)
return 0;
return 1 + CountNode(T->lchild) + CountNode(T->rchild);
}
int main(void)
{
BiTNode *root = NULL; //定义一个根结点
int flag = 1, k;
printf(" 本程序实现二叉树的基本操作。\n");
printf("可以进行建立二叉树,递归先序、中序、后序遍历,非递归先序、中序遍历及非递归层序遍历等操作。\n");
while (flag)
{
printf("\n");
printf("|--------------------------------------------------------------|\n");
printf("| 二叉树的基本操作如下: |\n");
printf("| 0.创建二叉树 |\n");
printf("| 1.递归先序遍历 |\n");
printf("| 2.递归中序遍历 |\n");
printf("| 3.递归后序遍历 |\n");
printf("| 4.非递归先序遍历 |\n");
printf("| 5.非递归中序遍历 |\n");
printf("| 6.非递归后序遍历 |\n");
printf("| 7.非递归层序遍历 |\n");
printf("| 8.二叉树的深度 |\n");
printf("| 9.二叉树的结点个数 |\n");
printf("| 10.退出程序 |\n");
printf("|--------------------------------------------------------------|\n");
printf(" 请选择功能:");
scanf_s("%d", &k, 1);
switch (k)
{
case 0:
printf("请建立二叉树并输入二叉树的根节点:");
CreateBiTree(&root);
break;
case 1:
if (root)
{
printf("递归先序遍历二叉树的结果为:");
PreOrder(root);
printf("\n");
}
else
printf(" 二叉树为空!\n");
break;
case 2:
if (root)
{
printf("递归中序遍历二叉树的结果为:");
InOrder(root);
printf("\n");
}
else
printf(" 二叉树为空!\n");
break;
case 3:
if (root)
{
printf("递归后序遍历二叉树的结果为:");
PostOrder(root);
printf("\n");
}
else
printf(" 二叉树为空!\n");
break;
case 4:
if (root)
{
printf("非递归先序遍历二叉树:");
PreOrder_Nonrecursive(root);
printf("\n");
}
else
printf(" 二叉树为空!\n");
break;
case 5:
if (root)
{
printf("非递归中序遍历二叉树:");
InOrderTraverse1(root);
printf("\n");
}
else
printf(" 二叉树为空!\n");
break;
case 6:
if (root)
{
printf("非递归后序遍历二叉树:");
PostOrder_Nonrecursive(root);
printf("\n");
}
else
printf(" 二叉树为空!\n");
break;
case 7:
if (root)
{
printf("非递归层序遍历二叉树:");
LeverTraverse(root);
printf("\n");
}
else
printf(" 二叉树为空!\n");
break;
case 8:
if (root)
printf("这棵二叉树的深度为:%d\n", depth(root));
else
printf(" 二叉树为空!\n");
break;
case 9:
if (root)
printf("这棵二叉树的结点个数为:%d\n", CountNode(root));
else
printf(" 二叉树为空!\n");
break;
default:
flag = 0;
printf("程序运行结束,按任意键退出!\n");
}
}
system("pause");
return 0;
}