非递归遍历要用到stack,出栈即访问
前序遍历:(中结点->左结点->右节点)
思路:先将根节点入栈,之后进入循环,先出栈一个结点A, 之后如果存在的话,将A的右结点入栈,再将A的左结点入栈,之后继续循环。。这样一直循环到栈空为止。
中序遍历: (左结点->中结点->右节点)
思路:扫描根节点,将其所有左孩子结点全部入栈, 之后出栈一个结点A,之后再扫描A结点的右孩子结点,进入循环。一直循环到栈空。
后序遍历:(左结点->右结点->中节点)
思路: 跟中序的差不多,只是在出栈的时候多了个条件限制,必须A左右孩子结点都出栈了,A结点才能出栈,此时需要用个结点指针pre来记录上一个访问的结点。
判断条件: A ->right == pre || A->right ==NULL
若A->right =NULL,则可以直接将A出栈,因为他没有右孩子结点了。
层序遍历:(层序遍历要使用队列,先进先出,后进后出。)
思路: 先将根节点入队,之后只要队列不为空就进入循环,循环内先出队头元素A,之后将A的左孩子跟右孩子再入队,这样一直循环到队列为空为止。
(出队即访问结点)
代码如下:
#include <stdio.h>
#include <malloc.h>
typedef struct node{
int data;
struct node *left,*right;
}Node, *Tree;
Tree createTree()
{
int x;
printf("请输入结点的值(0代表空结点) :");
scanf("%d",&x);
if(x)
{
Node *node = (Node *) malloc(sizeof(Tree));
node->data = x;
node->left = createTree();
node->right = createTree();
return node;
}
else
return NULL;
}
void preView(Tree tree)
{
Node *stack[100],*p;
int top = -1;
p = tree;
stack[++top] = p;
while(top > -1)
{
Node *temp = stack[top--];
printf("%d ",temp->data);
if(temp->right)
stack[++top] = temp->right;
if(temp->left)
stack[++top] = temp->left;
}
printf("\n");
}
void midView(Tree tree)
{
Node *stack[100],*p;
int top = -1;
p = tree;
while(top > -1 || p)
{
while(p)
{
stack[++top] = p;
p = p->left;
}
if(top > -1)
{
p = stack[top--];
printf("%d ",p->data);
p = p->right;
}
}
printf("\n");
}
void postView(Tree tree)
{
Node *stack[100],*p,*pre;
p = tree;
int top = -1;
do
{
while(p)
{
stack[++top] = p;
p = p->left;
}
p = stack[top];
if(p->right == pre || p->right == NULL)
{
printf("%d ",p->data);
top--;
pre = p;
p = NULL;
}
else
{
p = p->right;
}
}while(top > -1);
printf("\n");
}
void levelView(Tree tree)
{
Node *queue[100];
int first,end;
first = 0, end = 0;
queue[end++] = tree;
while(end > first)
{
Node *temp = queue[first++];
printf("%d ",temp->data);
if(temp->left)
queue[end++] = temp->left;
if(temp->right)
queue[end++] = temp->right;
}
printf("\n");
}
int main()
{
Tree tree = createTree();
preView(tree);
midView(tree);
postView(tree);
return 0;
}