二叉树之理解记忆并背诵,了解一下?

内容主要包含:
1. 二叉树中DFS三种搜索的模板程序 (递归+非递归)
2. 二叉树BFS非递归版本
3. 二叉树常见到必背的考题
不管你是刷题学习,还是准备面试,二叉树下面的这几个程序都是 理解记忆并背诵!理解记忆并背诵!理解记忆并背诵!重要的事情说三遍

真的太常用了,小哥哥小姐姐一定要掌握哦~

BFS递归版本

void bfs(TreeNode *node, queue<TreeNode*> q) {
    if (q.empty()) {
        return;
    }

    TreeNode *node = q.front();
    q.pop();
    cout << node->val << endl;

    if (node->left) {
        q.push(node->left);
    }
    if (node->right) {
        q.push(node->right);
    }

    bfs(node, q);
}

二叉树中序遍历

非递归1-最通用的版本

    vector<int> inorderTraversal(TreeNode * root) {
        if (root == NULL) {
            return vector<int>();
        }

        vector<int> ret;
        stack<TreeNode*> s;

        while (root != NULL) {
            s.push(root);
            root = root->left;
        }

        while (!s.empty()) {
            TreeNode *curt = s.top();
            ret.push_back(curt->val);

            if (curt->right == NULL) {
                s.pop();
                while (!s.empty() && s.top()->right == curt) {
                    curt = s.top();
                    s.pop();
                }
            } else {
                curt = curt->right;
                while (curt != NULL) {
                    s.push(curt);
                    curt = curt->left;
                }
            }
        }

        return ret;
    }

非递归2-常见版本

vector<int> inorderTraversal(TreeNode * root) {
        // 中序遍历的非递归版本
        vector<int> result;
        stack<TreeNode*> s;
        TreeNode* cur = root;

        while(cur != NULL || !s.empty()) {
            while(cur != NULL) {
                s.push(cur);
                cur = cur->left;
            }
            cur = s.top();
            s.pop();
            result.push_back(cur->val);
            cur = cur->right;
        }
        return result;
    }

二叉树前序遍历

递归之traverse

    vector<int> preorderTraversal(TreeNode * root) {
        vector<int> result;
        // 定义:以root为根节点的先序遍历结果放到result中
        traverse(root, result); 
        return result;
    }

    void traverse(TreeNode *root, vector<int> &result) { // 这个地方每次都要传地址,因为每次都要修改,相当于一个全局变量
        if (root == NULL) {
            return;
        }

        result.push_back(root->val);
        traverse(root->left, result);
        traverse(root->right, result);
    }

非递归版本

vector<int> preorderTraversal(TreeNode * root) {
    if (root == NULL) {
        return vector<int>();
    }

    vector<int> result;
    stack<TreeNode*> s;


    s.push(root);
    while(!s.empty()) {
        TreeNode *node = s.top();
        s.pop();
        result.push_back(node->val);
        if(node->right!=NULL) {
            s.push(node->right);
        }
        if(node->left!=NULL) {
            s.push(node->left);
        }
    }

    return result;
}

二叉树后序遍历

非递归版本

vector<int> postorderTraversal(TreeNode * root) {
    // write your code here
    vector<int> result;
    stack<TreeNode*> s;

    TreeNode *current = root, *lastVisit = NULL;
    while(current!=NULL || !s.empty()) {
        while(current != NULL) {
            s.push(current);
            current = current->left;
        }
        current = s.top(); // 此时先不要急着出栈
        if(current->right == NULL || current->right == lastVisit) {
            s.pop();
            result.push_back(current->val);
            lastVisit = current;
            current = NULL;
        } else {
            current = current->right;
        }
    }
    return result;
}

二叉树基本考题

MaxDepth of binary tree

int maxDepth(TreeNode *root) {
    // write your code here
    if(root == NULL) {
        return 0;
    }

    // Divide
    int left = maxDepth(root->left);
    int right = maxDepth(root->right);

    // Conquer
    return max(left, right) + 1;
}

MinDepth of binary tree

int minDepth(TreeNode * root) {
        // write your code here
        if(root == NULL) {
            return 0;
        }

        // Divide
        int left = minDepth(root->left);
        int right = minDepth(root->right);

        // Conquer
        if(left == 0 && right == 0) {
            return 1;
        }else if(left == 0 && right != 0) {
            return right + 1;
        }else if(left != 0 && right == 0) {
            return left + 1;
        }else {
            return min(left, right) + 1;
        }
    }

平衡二叉树判断

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */


class ResultType {
public:
    int maxDepth;
    bool isBalanced;

public:
    ResultType(int maxDepth, int isBalanced) {
        this->maxDepth = maxDepth;
        this->isBalanced = isBalanced;
    }
};


class Solution {
public:
    /*
     * @param root: The root of binary tree.
     * @return: True if this Binary tree is Balanced, or false.
     */
    bool isBalanced(TreeNode * root) {
        // write your code here
        return helper(root).isBalanced;
    }

    ResultType helper(TreeNode* root) {
        if(root == NULL) {
            return ResultType(0, true);
        }

        // Divide
        ResultType left = helper(root->left);
        ResultType right = helper(root->right);

        // Conquer
        if(!left.isBalanced || !right.isBalanced) {
            return ResultType(-1, false);
        }
        if(abs(left.maxDepth - right.maxDepth) > 1) {
            return ResultType(-1, false);
        }
        return ResultType(max(left.maxDepth, right.maxDepth) + 1, true);
    }
};

二叉搜索树判断

class Solution {
public:

    bool isValid;
    TreeNode *lastNode;

    bool isValidBST(TreeNode * root) {
        lastNode = NULL;
        isValid = true;

        traverse(root);

        return isValid;
    }

    // 利用中序遍历是升序序列的特性来做,一边遍历一遍给出结果
    void traverse(TreeNode *root) {
        // 先处理特殊情况,或者是退出情况
        if (root == NULL) {
            return;
        }

        traverse(root->left);
        // 根
        if (lastNode != NULL && lastNode->val >= root->val) {
            isValid = false;
            return;
        }
        lastNode = root;

        traverse(root->right);
    }
};
// 不要去记录最大值最小值,当节点为NULL的时候,不好处理。记录下最小最大的节点。不存在的话就直接给NULL就行了。
struct ResultType {
    bool isBST;
    TreeNode *maxNode;
    TreeNode *minNode;
    ResultType(bool isBST) {
        this->isBST = isBST;
        this->maxNode = NULL;
        this->minNode = NULL;
    }
};

    bool isValidBST(TreeNode * root) {
        return helper(root)->isBST;
    }

    ResultType *helper(TreeNode *root) {
        if (root == NULL) {
            return new ResultType(true);
        }

        // Divide
        ResultType *left = helper(root->left);
        ResultType *right = helper(root->right);

        // Conquer
        // 先处理不是的情况
        if (!left->isBST || !right->isBST) {
            return new ResultType(false);
        }

        if (left->maxNode != NULL && left->maxNode->val >= root->val) {
            return new ResultType(false);
        }

        if (right->minNode != NULL && right->minNode->val <= root->val ) {
            return new ResultType(false);
        }

        // 最后处理复杂的是的情况
        ResultType *ret = new ResultType(true); // 首先,是BST
        ret->minNode = left->minNode != NULL ? left->minNode : root;
        ret->maxNode = right->maxNode != NULL ? right->maxNode : root;
        return ret;

    }

二叉树中最近公共祖先 (Lowest Common Anscestor)

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */


class Solution {
public:
    /*
     * @param root: The root of binary tree
     * @return: An integer
     */
    int minDepth(TreeNode * root) {
        // write your code here
        if(root == NULL) {
            return 0;
        }

        // Divide
        int left = minDepth(root->left);
        int right = minDepth(root->right);

        // Conquer
        if(left == 0 && right == 0) {
            return 1;
        }else if(left == 0 && right != 0) {
            return right + 1;
        }else if(left != 0 && right == 0) {
            return left + 1;
        }else {
            return min(left, right) + 1;
        }
    }
};

二叉树路径和最大值

public int maxPathSum(TreeNode *root) {
  if(root == NULL) {
    return 0;
  }

  // Divide
  int left = maxPathSum(root->left);
  int right = maxPathSum(root->right);

  // Conquer
  //root->leaf
  return max(left, right) + root->val;

  // root->any
  return max(max(left, right), 0) + root->val; // 也就是说如果是到any节点,那么如果是负数,我们不如不要他,但是如果是到leaf则不行,不管是不是负的,你都必须走到leaf才行。
}
// any->any 用到两个分治法


class ResultType {
public:
    int any2any;
    int root2any;
    ResultType(int root2any, int any2any) {
        this->root2any = root2any;
        this->any2any = any2any;
    }
};


class Solution {
public:
    /*
     * @param root: The root of binary tree.
     * @return: An integer
     */
    int maxPathSum(TreeNode * root) {
        // write your code here
        return helper(root).any2any;
    }

    ResultType helper(TreeNode *root) {
        //illegal 这种情况是不合法,找不到 不是找到为0
        if(root == NULL) {
            return ResultType(INT_MIN, INT_MIN);
        }

        // Divide
        ResultType left = helper(root->left);
        ResultType right = helper(root->right);

        // Conquer
        int any2any =  max(left.any2any, right.any2any);
        int root2any = max(0, max(left.root2any, right.root2any)) + root->val;
        any2any = max(any2any, 
                    max(left.root2any, 0) + max(right.root2any, 0) + root->val);
        return ResultType(root2any, any2any);
    }
};
数据结构关于二叉树的建立遍历以及应用二叉树进行编解码 实验要求 必做部分 1. 小明会按照前序的方式输入一棵二叉树。例如,输入$ACG##H##D##BE#I##F##的话,代表了下面这棵树: 2. 请分别按照前序、中序、后序输出这棵树。 选做部分 背景 在影视剧中,我们经常会看到二战期间情报人员使用电报哒哒哒地发送信息,发送电报所使用的编码叫做摩尔斯电码(或者叫做摩斯密码)。甚至在现代,SOS仍然是国际通用的求救信号之一,其“三短、三长、三短”同样是摩斯密码的编码方式。 摩斯密码使用若干个“点”和“划”来表示一个字母,字母和字母之间使用短暂的停顿来表示。例如,一种常见的编码方式为: 字母 摩斯密码 字母 摩斯密码 A .- E . B -... F ..-. C -.-. G --. D -.. H .... 实际上,一个摩斯密码本可以使用一棵二叉树来存储: 上图表示,从根节点start开始,遇到一个点(Dot)就访问它的左子树节点,遇到一个划(Dash)就访问它的右子树节点。例如,三个点...代表了S,三个划---代表了O。所以SOS的摩斯密码是... --- ...(中间用空格隔开,表示短暂的停顿)。再比如,爱疯手机有一种来电铃声的节奏为“哇哇哇 哇-哇- 哇哇哇”,这其实表示的是…… 现在,小明想在课上偷偷跟你传纸条,但又不想被其他同学看到内容。因此他跟你约定,每次给你传纸条时都使用摩斯密码来编写。至于密码本,当然不能使用国际通用的,他会在课前告诉你密码本的内容。然而小明发现,每次写纸条、读纸条都不是很方便,所以他想让你做个程序来自动编码/解码你们的摩斯密码。 题目要求 首先,小明输入的那棵二叉树,代表了你们在这堂课上要使用的摩斯密码本。例如,输入$ACG##H##D##BE#I##F##的话,代表了下面这棵树: 第一个字母$是什么并不重要,因为它只是代表了根节点,而根节点在我们的摩斯电码中并不代表一个字符,仅仅代表“start”。 读入密码本后,请记得按照前序、中序、后序输出这棵树。 然后,小明会输入一个数,代表接下来输入的是明文还是摩斯电码。输入0表示接下来他会输入明文,输入1表示接下来输入的是摩斯电码,输入-1程序退出。 1. 如果输入的是0,代表接下来要输入的是明文。程序接受一个字符串,根据字符串中每一个字母输出对应的摩斯电码,用空格隔开。例如如果小明输入“BED”,则程序应该输出“-空格-.空格.-”。如果遇到密码本中没有的字符,则输出“输入有误”。 2. 如果输入的是1,则表示接下来要输入摩斯电码。小明首先会输入一个数字N,代表有几个电码的输入,例如输入4代表之后会输入4个电码(即这个单词有四个字母)。随后输入空格分割的电码,例如, .. . -- -. 程序需要根据摩斯电码解读出明文单词并输出,例如上面的电码表示“CAFE”。如果遇到密码本中没有的编码,则输出“输入有误”。 输入输出样例 必做部分: 请输入二叉树: $ACG##H##D##BE#I##F## 前序遍历:$ACGHDBEIF 中序遍历:GCHAD$EIBF 后序遍历:GHCDAIEFB$ 选做部分: 请选择(0为明文,1为电码,-1退出):0 请输入明文:BED 摩斯电码为:- -. .- 请选择(0为明文,1为电码,-1退出):1 请输入电码个数:4 请输入电码:.. . -- -. 明文为:CAFE 请选择(0为明文,1为电码,-1退出):-1 // 程序结束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值