其他分享
首页 > 其他分享> > 1-树-遍历、翻转、对称

1-树-遍历、翻转、对称

作者:互联网

1-1 二叉树遍历

1-1-1 非递归遍历\先中后 - 源码

先序遍历 -- 根左右

  1. 思想
    使用栈的左中右遍历;
    先访问根节点,再入栈以待访问右节点;
    每次的当前节点为null时,进入遍历右节点次序;

  2. 代码

// pre
void preOrder_N(BiTNode *T){
    SqStack Sq;
    initStack(Sq);
    BiTNode *p = T;
    while (p || !isEmpty(Sq)){
        if(p){
            visit(p);
            Push(Sq, p);
            p = p->lchild;
        }
        else{
            Pop(Sq, p);
            p = p->rchild;
        }
    }
}

中序遍历 -- 左根右

  1. 思想
    遍历思想和先序遍历类似:因为从顺序来讲都是先从左根到左再向右,只是将访问函数放在了即将pop的结点上;
  2. 代码
// in
void inOrder(BiTNode *T){
    SqStack Sq;
    initStack(Sq);
    BiTNode *p = T;
    while (p || !isEmpty(Sq)){
        if(p){
            Push(Sq, p);
            p = p->lchild;
        }else{
            Pop(Sq, p);
            visit(p);
            p = p->rchild;
        }
    }
}

后序 -- 左右根

  1. 思想
    同样使用栈的结构,每次得到左右结点都进栈之后开始遍历该根节点;

    需要注意的是

    右节点的入栈需要条件:

    1.左到头

    2. 右孩子存在&右孩子不为最近访问过(防止右右打转)

    访问结点: 1. 访问 2.最近rct 3.p设置为空

  2. 代码

具体代码实现
// post
void postOrder(BiTNode *T){
    BiTNode *p = T, *rct = nullptr;
    SqStack Sq;
    initStack(Sq);
    while (p || !isEmptySq(Sq)){
        if(p){
            Push(Sq, p);
            p = p->lchild;
        }else{
            Pop(Sq, p);
            if(p->rchild && p->rchild != rct) 
            // 需要注意右结点存在 && 最近没有访问过
            {
                Push(Sq, p);
                p = p->rchild;
            }else{  // 访问结点的条件在于左右孩子都空,
                visit(p);
                rct = p;
                p = nullptr;
            }
        }
    }
}

1-1-2层序 -- 队列

  1. 思想
    使用队列先将结点入队,

    • TODO
  2. 代码

具体代码实现
void LayerOrder(BiTNode *T){
    SeQueue Se;
    BiTNode *p = T;
    enQueue(Se, p);
    while (!isEmptySe(Se)){
        deQueue(Se, p);
        visit(p);
        if(p->lchild) enQueue(Se, p->lchild);
        if(p->rchild) enQueue(Se, p->rchild);
    }
}

1-2 构建二叉树 (根据俩数组构建)

1-2-1先序-中序

1-2-2后序-中序

1-2-3层序-中序


1-3 翻转二叉树

翻转 递归 迭代
- 将 temp 结点作为中间变量, 交换左右; 先序递归遍历
/*法一: 递归思想--先序递归交换左右*/
//*法一: 递归思想*/  
//将 temp 结点作为中间变量, 交换左右; 先序递归遍历
BiTree invertBTree_N(BiTNode *&root) {
  if (!root)
    return nullptr;
  BiTNode *temp = root->rchild;
  root->rchild = root->lchild;
  root->lchild = temp;
  invertBTree_N(root->lchild);
  invertBTree_N(root->rchild);
  return root;
}
/*法三: 静态转置-- 层序遍历交换*/
/*法三: 静态转置 -- 层序遍历交换*/
// 队列 - 迭代法 -- 层序
BiTree invertBTree_Se(BiTNode *&root) {
  SeQueue Se;
  if (root)
    enQueue(Se, root);
  while (!isEmptySe(Se)) {
    BiTNode *curr, *temp;
    deQueue(Se, curr);
    // swap l r
    temp = curr->lchild;
    curr->lchild = curr->rchild;
    curr->rchild = temp;
    if (curr->lchild)
      enQueue(Se, curr->lchild);
    if (curr->rchild)
      enQueue(Se, curr->rchild);
  }
  return root;
}
// ***栈 - 迭代法 --深度DFS
// 栈 - 迭代法  --深度DFS
BiTree invertBTree_Sq(BiTNode *&root) {
  if (!root)
    return nullptr;
  SqStack Sq;
  initStack(Sq);
  Push(Sq, root);
  while (!isEmptySq(Sq)) {
    BiTree curr;
    Pop(Sq, curr);
    BiTree temp = curr->lchild; // swap
    curr->lchild = curr->rchild;
    curr->rchild = temp;

    if (curr->rchild)
      Push(Sq, curr->rchild);
    if (curr->lchild)
      Push(Sq, curr->lchild);
  }
  return root;
}

1-4 对称二叉树

  1. 思想
    终止条件:
  1. 代码
2.1. 递归
bool compare(BiTNode* left, BiTNode* right) {
    if(left == NULL && right == NULL)   return true;
    else if(left == NULL && right != NULL)  return false;
    else if(left != NULL && right == NULL) return false;
    else if(left->data != right->data)    return false;
    //else    return true;
    bool outside = compare(left->lchild, right->rchild); // 返回左的左,右的右
    bool inside = compare(left->rchild, right->lchild);  // 返回左的右,右的左
    bool isSame = outside && inside;
    return isSame;
    //else return compare(left->lchild, right->rchild) 
    //&& compare(left->rchild, right->lchild);
    }
2.2. 迭代
// 法二 : 迭代
bool isSymmetric(BiTree root) {
  if (root == NULL)
    return true;
  // 左右子树入队列
  SeQueue Se;
  BiTNode *leftNode, *rightNode;
  enQueue(Se, root->lchild);
  enQueue(Se, root->rchild);
  while (!isEmptySe(Se)) { // 判断两棵树是否相互对称
    deQueue(Se, leftNode);
    deQueue(Se, rightNode);
    // 左右结点同时为空,继续判断
    if (!leftNode && !rightNode)
      continue;
    // 左右至少一个不为空,或左右data域不相等
    if ((!leftNode || !rightNode || (leftNode->data != rightNode->data)))
      return false;
    //入队列 左的左, 右的右; 左的右, 右的左
    enQueue(Se, leftNode->lchild);
    enQueue(Se, rightNode->rchild);
    enQueue(Se, leftNode->rchild);
    enQueue(Se, rightNode->lchild);
  }
  return true;
}

标签:lchild,遍历,curr,Sq,对称,rchild,root,Se,翻转
来源: https://www.cnblogs.com/moHyio-YOLO/p/1shu.html