二叉树的遍历与改进

// 树与二叉树 practice 1

// 结点的定义
typedef struct BTNode(){
    char data;
    
    struct BTNode *lchild;
    struct BTNode *rchild;
}BTNode;

// 二叉树的先序遍历
void preorder(BTNode *p){
    Visit(p);  // 假设Visit()已经定义为访问结点函数
    
    preorder(p->lchild);
    preorder(p->rchild);
}

// 中序遍历
void inorder(BTNode *p){
    inorder(p->lchild);
    Visit(p);
    inorder(p->rchild);
}

// 后序遍历
void postorder(BTNode *p){
    postorder(p->lchild)postorder(p->child);
    Visit(p);
}

// 三大遍历小结: 根节点visit, 左右孩子结点递归

// 层次遍历: 注意进队、入队的写法
void LevelOrder(BTNode *p){
    int front, rear;
    BTNode *que[maxSize];   // 定义一个循环队列
    front=rear=0;   // 初始化队列
    BTNode *q;     // 接收出队的结点
    if(p!=NULL){
        rear = (rear+1)%maxSize;
        que[rear] = p;
        while(front!=rear){
            front = (front+1)%maxSize;
            q = que[front];
            if(q->lchild!=NULL){
                rear = (rear+1)%maxSize;
                que[rear] = q->lchild;
            }
            if(q->rchild!=NULL){
                rear = (rear+1)%maxSize;
                que[rear] = p->lchild;
            }
        }
    }
    
}


// 改进版二叉树遍历
// 非递归篇

// 非递归先序遍历, 注意:由于栈是先进后出,所以先右孩子,后左孩子
// A[top++]=p; 进栈   A[top--]=p;  出栈
void preorderPlus(BTNode *bt){
	if(bt!=NULL){
        BTNode *Stack[maxSize];
    	int top=-1;
    	BTNode *q;
    	Stack[top++] = bt;
        if(top!=-1){
            q=Stack[top--];
            Visit(q);
            if(q->rchild!=NULL){
                Stack[top++]=q-rchild;
            }
            if(q->lchild!=NULL){
                Stack[top++]=q-lchild;
            }
        }
    }
}

// 中序(这个需要重复复习)
void inorderPlus(BTNode *bt){
    if(bt!=NULL){
        BTNode *Stock[maxSize];
        int top=-1;
        BTNode *q;
        q=bt;
        while(top!=-1||q!=NULL){
            while(q!=NULL){      // 所有左孩子进栈
                Stack[++top]=q;
                q=q->lchild;
            }
            if(top!=-1){
                q=Stack[top--];
                Visit(q);
                q=q-rchild;
            }
        }
    }
}

// 后序(属于难度较大类)
// 关键:逆后序遍历就是先序遍历左右子树替换
void postorderPlus(BTNode *bt){
	if(bt!=NULL){
        // 需要两个栈, Stack2用来储存逆后序
        BTNode *Stack1[maxSize]j; int top1=-1;
        BTNode *Stack2[maxSize]j; int top2=-1;
        BTNode *q = NULL;
        Stack1[++top1]=bt;
        while(top1 != -1){
            q = Stack1[top--];
            Stack2[top++] = q;     // 进入Stack2
            // 左右孩子入栈与先序相反
            if(q->lchild != NULL){
                Stack1[++top1] = p->lchild;
            }
            if(q->rchild != NULL){
                Stack1[++top1] = p->rchild;
            }
        }
        while(top2 != 1){
            // 出栈序列即为后序遍历序列
            q = Stack2[top2--];
            Visit(q);  // Visit()是访问p的函数,在这里执行打印结点值的操作
        }
        
    } 
}

// 线索二叉树   (要反复复习)
// 线索二叉树的结构体
typedef struct TBTNode(){
    char data;
    int ltag,rtag;
    struct TBTNode *lchild;
    struct TBTNode *rchild;
}TBTNode;

// 中序线索二叉树构造
void InThread(TBTNode *p, TBTNode *&pre){
    if(p!=NULL){
        InThread(p->lchild, pre);   // 递归,左子树线索化, 递归到最左侧结点
        if(p->lchild==NULL){
            p->lchild=pre;          // 建立当前结点的前驱线索
            p->ltag=1;
        }
        if(pre!=NULL&&pre->child=NULL){
            pre->rchild=p;           // 建立当前结点的后继线索
            pre->rtag=1;
        }
        pre = p;      
        InThread(p->rchild,pre);   // 递归,右子树线索化
    }
}

// 通过中序遍历建立中序线索二叉树的主程序
void createInThread(TBTNode *roor){
    TBTNode *pre=NULL;    // 前驱结点
    if(root!=NULL){
        InThread(root, pre);
        pre->rchild=NULL;     // 非空二叉树,线索化
        pre->rtag=1;          // 后处理中序最后一个结点
    }
}


// 遍历中序二叉树
// 获取第一个结点
TBTNode *First(TBTNode *p){
    while(p->ltag==0)
        p=p->lchild;      // 最左下结点(不一定是叶节点)
    return p;
}

// 结点p在中序下的后继结点算法
TBTNode *Next(TBTNode *p){
    if(p->rtag==0)
        return First(p->rchild);
    else
        return p->rchild;      // rtag==1, 直接返回后继线索
}

void Inorder (TBTNode *root){
    for(TBTNode *p=First(root); p!=NULL; p=Next(p))
        Visit(p); 
}



标题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值