[专题五] 二叉树

Posted recoverableti

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[专题五] 二叉树相关的知识,希望对你有一定的参考价值。

树结构专题

二叉树
几种典型运算
typedef struct BTNode{
  int data;
  struct BTNode *left;
  struct BTNode *right;
}BTNode;
// 创建二叉树
BTNode BinaryTree() {
  BTNode *T = (BTNode*)malloc(sizeof(BTNode));
  T->data = 0;
  return T;
}
//BinaryEmpty(T):bool 判断树是否为空
//Root(T):int 返回根结点data
//构造二叉树
BTNode MakeTree(int x, BTNode *l, BTNode *r) {
  BTNode *T = (BTNode*)malloc(sizeof(BTNode));
  T->data = x;
  T->left = l; T->right = r;
  return T;
}
//BreakTree(x,T,l,r):void makeTree的逆运算 拆成左右树
先序非递归
//PreOrder(root):void 先序遍历
//PreOut(root):void 先序序列
void PreOrder(BTNode *root) {
  if(!root) exit(1);
  stack<BTNode*> stack;
  BTNode *cur;
  stack.push(root);
  while(!stack.empty()) {
    cur = stack.top();
    stack.pop();
    cout << cur->data << " ";
    if (cur->right) {
      stack.push(cur->right);
    }
    if (cur->left) {
      stack.push(cur->left);
    }
  }
}
中序非递归 — 记忆区别 1
//InOrder(root):void 中序遍历
//InOut(root):void 中序序列
void InOrder(BTNode *root) {
  if(!root) exit(1);
  stack<BTNode*> stack;
  // 与先序区分
  BTNode *cur = root;
  while(!stack.empty() || cur) {
    while (cur) {
      stack.push(cur);
      cur = cur->left;
    }
    if (!stack.empty()) {
      cur = stack.top();
      stack.pop();
      cout << cur->data << " ";
      cur = cur->right;
    }
  }
}
后序非递归
//先序左右孩子入栈顺序交换得到逆后序,逆后序再逆序得后序
//PostOrder(root):void 后序遍历
//PostOut(root):void 后序序列
void PostOrder(BTNode *root) {
  if(!root) exit(1);
  stack<BTNode*> stack1;
  stack<BTNode*> stack2;
  BTNode *cur;
  stack1.push(root);
  while(!stack1.empty()) {
    cur = stack1.top();
    stack1.pop();
    stack2.push(cur);
    if (cur->left) { /*左右孩子入栈顺序改变*/
      stack1.push(cur->left);
    }
    if (cur->right) {
      stack1.push(right);
    }
  }
  while (!stack2.empty()) {
    cur = stack2.top();
    cout<< cur->data << " ";
    stack2.pop();
  }
}
层序遍历 可记录层数
void LevelOrder(BTNode *root) {
  queue<BTNode*> que;
  BTNode *cur;
  que.push(root);
  while (!que.empty()) {
    int size = que.size(); // 嵌套for循环使用
    while (!que.empty()) {
      cur = que.front();
      que.pop();
      if (cur->left) {
        que.push(cur->left);
      }
      if (cur->right) {
        que.push(cur->right);
      }
    }
  }
}
中序遍历的二叉树线索化 — 记忆
/** 首先明确是使用递归,传入的是pre和root
    对于某结点而言,如果它没有左孩子,则左线索指向前驱
    同理 如果它的前驱没有右孩子,则指向后继
    然后使pre指针后移一位,而中序遍历中,本结点后继是右孩子,所以p移向右孩子
  **/
void Inthread(BTNode *p, BTNode *&pre) {
  if (p) {
    Inthread(p->left, pre);
    if (p->left==NULL) {
      p->left = pre;
      p->ltag = 1;
    }
    if (pre!=NULL && pre->right==NULL) {
      pre->right = p;
      p->rtag = 1;
    }
    pre = p;
    Inthread(p->rchild, pre);
  }
}
二叉搜索树
二叉搜索树基本操作 — 记忆
/** 根据BST的特性,对于每个节点:如果目标值等于节点的值,则返回节点;如果目标值小于节点的值,则继续在左子树中搜索;如果目标值大于节点的值,则继续在右子树中搜索。 **/

// 增加结点
TreeNode* insertIntoBST(TreeNode* root, int val) {
        TreeNode *p = root, *pre;
        while(p) { /**先搜索,边保存前驱结点**/
            pre = p;// 保存前驱很重要!!
            if(p->val>val) p = p->left;
            else if(p->val<val) p = p->right;
            else return 0;
        }
        TreeNode *r = new TreeNode(val); //创建结点
        if(root) { /**如果树存在,则创建前驱结点与新结点的关系,反之,则将该结点插入空树**/
            if(pre->val > val) pre->left = r;
            else pre->right = r;
        }
        else root = r;
        return root;
    }

// 删除结点 我无能,抄大佬的递归
TreeNode* deleteNode(TreeNode* root, int key) {
        if(root==NULL)return NULL;
        if(root->val>key)
        {
            root->left = deleteNode(root->left,key);
            return root;
        }
        if(root->val<key)
        {
            root->right = deleteNode(root->right,key);
            return root;
        }
        if(root->left==NULL&&root->right==NULL)return NULL;
        if(root->left==NULL&&root->right!=NULL)return root->right;
        if(root->left!=NULL&&root->right==NULL)return root->left;
        int val = findMax(root->left);
        root->val=val;
        root->left = deleteNode(root->left,val);
        return root;
    }
    int findMax(TreeNode* root)
    {
        if(root->right==NULL)return root->val;
        return findMax(root->right);
    }
二叉树的路径最大和
// lmr讨论的是 包含a作为根结点的结果 可能       
int maxs = INT_MIN;
    int maxPathSum(TreeNode* root) {
        findroot(root);
        return maxs;
    }
    int findroot(TreeNode *root) {
        if(!root) return 0;
        int left = max( findroot(root->left), 0); //用这种方法舍去左右孩子可能为负值的情况
        int right = max( findroot(root->right), 0);
        int lmr = root->val + right + left;
        maxs = max(maxs, lmr);  
        // 如果大于0 说明可以使分支变大 太难了
        return max(0,root->val + max(left, right));
    }

知识点和代码均学习于Acwing: https://www.acwing.com/activity/

以上是关于[专题五] 二叉树的主要内容,如果未能解决你的问题,请参考以下文章

二叉树专题

python代码计算二叉树的深度

《寒假算法集训》(专题十六)二叉搜索树

平衡二叉树专题

专题总结-二叉树

开启二叉树专题,递归遍历二叉树模板(2021-7-20))