• [专题五] 二叉树


    二叉树

    构建二叉树

    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/

  • 相关阅读:
    Demo
    Demo
    Demo
    Demo
    Demo
    【csp模拟赛6】树上统计-启发式合并,线段树合并
    【csp模拟赛6】计数--单调栈
    【csp模拟赛6】相遇--LCA
    【poj1734】Sightseeing trip--无向图最小环
    【poj2709】Painter--贪心
  • 原文地址:https://www.cnblogs.com/recoverableTi/p/12248046.html
Copyright © 2020-2023  润新知