数据结构-二叉树的遍历

ipqtjmqj 2020-02-14

一、先序遍历

  • 第一个一定是根结点
  1. 递归式:就是先序递归的定义
  2. 递归边界:二叉树中递归边界是二叉树为一棵空树
void preorder(node* root){
    if(root == NULL){
        return;
    }
    //访问根结点root, 例如将其数据域输出
    printf("%d\n", root->data);
    //访问左子树
    preorder(root->lchild);
    //访问右子树
    preorder(root->rchild);
}

二、中序遍历

  • 只要知道根结点就可以通过根结点在中序遍历的序列中位置分出为左子树和右子树
  1. 递归式:就是中序递归的定义
  2. 递归边界:二叉树中递归边界是二叉树为一棵空树
void inorder(node* root){
    if(root == NULL){
        return;
    }
    inorder(root->lchild);
    printf("%d\n", root->data);
    inorder(root->rchild);
}

三、后序遍历

  • 最优一个结点一定是根结点
void postorder(node* root){
    if(root == NULL){
        return;
    }
    postorder(root->lchild);
    postorder(root->rchild);
    printf("%d\n", root->data);
}
  • 总的来说无论是先序遍历还是后序遍历,都必须知道中序遍历才能唯一确定一棵树

四、层序遍历

void  LayerOrder(node* root){
    queue<node*> q;
    q.push(root);
    while(!q.empty()){
        node* now = q.front();
        q.pop();
        printf("%d\n", now->data);
        if(now->lchild != NULL) q.push(now->lchild);
        if(now->rchild != NULL) q.push(now->rchild);
    }
}
  • 有时候需要记录每个结点的层次
struct node{
    int data;
    int layer;
    node* lchild;
    node* rchild;
}
void  LayerOrder(node* root){
    queue<node*> q;
    root->layer = 1;
    q.push(root);
    while(!q.empty()){
        node* now = q.front();
        q.pop();
        printf("%d\n", now->data);
        if(now->lchild != NULL){
            now->lchild->layer = now->layer+1;
            q.push(now->lchild);
        }
        if(now->rchild != NULL){
            now->rchild->layer = now->layer+1;
            q.push(now->rchild);
        }
    }
}

五、由先序遍历和中序遍历构建二叉树/后序遍历和中序遍历构建二叉树

node* create(int preL, int preR, int inL, int inR){
    if(preL > preR){
        return NULL;//先序序列长度小于等于0时,直接返回
    }
    node* root = new node;//新建一个结点,用于存放二叉树的根结点
    //如果是先序和中序那么这里就是从左边第一个结点就是根结点所以为preL,而后序和中序是从后面第一个是根结点所以为postR
    root->data = pre[preL]/post[postR];//新结点的数据域为根结点的值
    int k;
    for(k = inL; k <= inR; k++){
        if(in[k] == pre[preL]){
            break;
        }
    }
    int numLeft = k - inL;//左子树的结点个数
    //左子树的先序区间为[preL+1, preL+numLeft], 中序区间[inL, k-1]
    //返回左子树的根结点地址,赋值给root的左指针
    root->lchild = create(preL+1/postL, preL+numLeft/postL+numLeft-1, inL, k-1);
    //右子树的先序区间[preL+numLeft+1, preR], 中序区间为[k+1, inR];
    //返回右子树的根结点地址,赋值给root的右指针
    root->rchild = create(preL+numLeft+1/postL+numLeft, preR/postR-1, k+1, inR);
    
    return root;//返回根结点地址
}

相关推荐