#include <stdio.h>
#include <stdlib.h>
typedef struct{
struct TreeNode *left;
struct TreeNode *right;
char val;
int visitCount;
}TreeNode;
typedef struct {
TreeNode *base;
TreeNode *top;
int size;
int currentSize;
}Stack;
Stack* initStack(){
Stack *stack;
stack = (Stack*)malloc(sizeof(Stack));
if(!stack) exit(0);
stack->base = (TreeNode*)malloc(sizeof(TreeNode)*20);
if(!stack->base) exit(0);
stack->top = stack->base;
stack->size = 20;
stack->currentSize = 0;
return stack;
}
TreeNode* pop(Stack *stack){
if(stack->currentSize<=0)
return NULL;
else
stack->currentSize--;
return (--stack->top);
}
void push(Stack *stack,TreeNode node){
if(stack->top-stack->base>=stack->size){
stack->base = (TreeNode*)realloc(stack->base,sizeof(TreeNode)*(stack->size+20));
if(!stack->base) exit(0);
stack->top =stack->size+stack->base;
stack->size +=20;
}
stack->currentSize++;
*(stack->top)=node;
;
stack->top++;
}
TreeNode* peek(Stack *stack){
if(stack->base==stack->top)
return NULL;
else
return (stack->top-1);
}
int size(Stack *stack){
return stack->currentSize;
}
TreeNode* createTree(){
TreeNode *root;
if(!root) exit(0);
char ch;
printf("输入该节点的值 回车退出该节点的输入\n");
if((ch=getchar())!='\n'){
root = (TreeNode*)malloc(sizeof(TreeNode));
root->val = ch;
root->visitCount = 0;
fflush(stdin);
root->left = createTree();
root->right = createTree();
}else{
printf("该节点作废\n");
return NULL;
}
return root;
}
void work(TreeNode *node){
printf("node's val = %c \n",node->val);
}
void visitRecursion_mid(TreeNode *root){
if(root==NULL)
return;
visitRecursion_mid(root->left);
work(root);
visitRecursion_mid(root->right);
}
void visitRecursion_before(TreeNode *root){
if(root==NULL)
return;
work(root);
visitRecursion_before(root->left);
visitRecursion_before(root->right);
}
void visitRecursion_after(TreeNode *root){
if(root==NULL)
return;
visitRecursion_after(root->left);
visitRecursion_after(root->right);
work(root);
}
void visitIteration_mid(TreeNode *root){
Stack *stack = initStack();
push(stack,*root);
TreeNode *temp = root->left;
while(size(stack)>0||temp){
while(temp){
//向左遍历到底
push(stack,*temp);
temp = temp->left;
}
//退栈 向右遍历
temp = pop(stack);
work(temp);
while(!temp->right&&size(stack)>0){
temp = pop(stack);
work(temp);
}
temp = temp->right;
}
}
void visitIteration_before(TreeNode *root){
if(!root)return;
work(root);
Stack *stack = initStack();
push(stack,*root);
TreeNode *temp = root->left;
while(size(stack)>0||temp){
while(temp){
//向左遍历到底
push(stack,*temp);
work(temp);
temp = temp->left;
}
//退栈 向右遍历
temp = pop(stack);
while(!temp->right&&size(stack)>0){
temp = pop(stack);
}
temp = temp->right;
}
}
//总体思路:
根节点先入栈 向左遍历到底 其中国条件为该节点为空并且是之前没有访问过的 (否则会造成退栈时再次左子树入栈)
然后退栈,设置个临时变量flag指向栈顶元素的右子树
如果右子树为空 则说明该栈顶元素temp节点没有子节点 可以访问 或者该节点已经在之前访问过一次了 那本次也可以访问
否则即当该栈顶元素temp存在右子树并且是第一次访问
即对把该节点temp和该节点的右子树节点flag再次入栈 并且设置访问过的标记
然后令temp指向flag的左子树再次进入循环 (就相当于把flag的节点当作了root进行了递归操作)
void visitIteration_after(TreeNode *root){
if(!root)return;
Stack *stack = initStack();
push(stack,*root);
TreeNode *temp = root->left;
TreeNode *flag;
while(size(stack)>0){
while(temp&&temp->visitCount ==0){
//向左遍历到底
push(stack,*temp);
temp = temp->left;
}
temp = pop(stack);
flag = temp->right;
//flag为NULL或者之前已经访问过该节点一次 则直接访问
if(!flag||temp->visitCount == 1){
work(temp);
temp->visitCount = 1;//设置访问记号
}else{//flag为真并且之前没有访问过 则取flag的左子树继续遍历 并设置访问记号
temp->visitCount = 1;//设置访问记号
push(stack,*temp);
push(stack,*flag);
temp = flag->left;
}
}
}
int main()
{
TreeNode * root = createTree();
visitIteration_before(root);
printf("-------------\n");
visitRecursion_before(root);
printf("Hello world!\n");
return 0;
}
C语言进行二叉树的递归遍历和非递归遍历
最新推荐文章于 2020-04-05 18:19:13 发布