二叉树应用题

1. 非递归先序

vector<int> preorderTraversal(TreeNode* root) {
    vector<int> nums;
    stack<TreeNode*> s;
    while(root||!s.empty()){
        if(root){
            nums.push_back(root->val);//输出
            s.push(root);//入栈
            root = root->left;//往左走
        }
        else{
            root = s.top();s.pop();//出栈
            root = root->right;//往右走
        }
    }
    return nums;
}

2. 非递归中序

vector<int> inorderTraversal(TreeNode* root) {
    vector<int> nums;
    stack<TreeNode*> s;
    while(root||!s.empty()){
        if(root){
            s.push(root);//入栈
            root = root->left;//往左走
        }
        else{
            root = s.top();s.pop();//出栈
            nums.push_back(root->val);//输出
            root = root->right;//往右走
        }
    }
    return nums;
}

3. 非递归后序

需要使用辅助指针进行判断

vector<int> postorderTraversal(TreeNode* root) {
    vector<int> nums;
    stack<TreeNode*> s;
    TreeNode* r;//辅助判断指针,判断是从左子树出栈,还是右子树
    while(root||!s.empty()){
        if(root){
            s.push(root);//入栈
            root = root->left;//往左走
        }
        else{
            root = s.top();//得到栈顶
            if(root->right&&root->right!=r)//右子树存在,且不是刚出来
                root = root->right;//往右走
            else{
                s.pop();//出栈
                nums.push_back(root->val);//输出
                r = root;//记录最近访问
                root = NULL;//重置指针
            }
        }
    }
    return nums;
}

4. 自下而上、自右而左的层次遍历

使用队列和栈

void InvertLevel(TreeNode* root) {
    queue<TreeNode*> q;
    stack<int> s;
    q.push(root);
    while(!q.empty()){
        TreeNode* p = q.front();
        q.pop();
        s.push(p->val);
        if(p->left) q.push(p->left);
        if(p->right) q.push(p->right);
    }
    while(!s.empty()){
        cout<<s.top();//逆序输出
        s.pop();
    }
}

5. 非递归求高度(层次遍历)

6. 先序、中序构建二叉树

 TreeNode* myBuildTree(vector<int>& preorder, vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
        if (preorder_left > preorder_right) return nullptr;
        int inorder_root = index[preorder[preorder_left]];// 在中序遍历中定位根节点,这里使用哈希优化,也可以遍历中序序列找根节点
        // 先把根节点建立出来
        TreeNode* root = new TreeNode(preorder[preorder_left]);
        // 得到左子树中的节点数目
        int size_left_subtree = inorder_root - inorder_left;
        root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
        root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
        return root;
    }

7. 判断完全二叉树

借助队列,遇到空节点时,查看其后是否有非空节点

8. 计算度为2的节点

//后序遍历
int DsonNodes(TreeNode* root){
    if(!root) return 0;
    int left = DsonNodes(root->left);
    int right = DsonNodes(root->right);
    if(root->left&&root->right) return left+right+1;
    else return left+right;
}   

9. 交换左右子树

//后序遍历
void exchange(TreeNode* root){
    if(!root) return;//边界条件
    exchange(root->left);
    exchange(root->right);
    swap(root->left,root->right);
}  

10. 找先序遍历第k个值

//全局变量先序遍历
int i = 0;
int Prenode(TreeNode* root,int k){
    if(!root) return '#';//边界条件
    i++;//先序遍历第i个节点
    if(i==k) return root->val;//输出
    int c = Prenode(root->left,k);//左递归
    if(c!='#') return ch;//中断递归
    int c = Prenode(root->right,k);//右递归
    if(c!='#') return ch;//返回指定值
}   

11. 删除指定的子树

//递归删除释放空间,并从父节点释放指针

12. 找指定值节点的所有祖先

//非递归后序遍历,访问到指定节点时,栈中所有元素皆为祖先

13. 两节点最近公共祖先

//非递归后序遍历

14. 二叉树的宽度

//层次遍历

15. 满二叉树先序转后序

int PreToPost(vector<int>&pre,int l1,int r1,vector<int>&post,int l2,int r2){
    if(l1>r1) return;//边界条件
    post[r2] = pre[l1];//先序根节点为后序尾节点
    int half = (r1-l1)/2;//求一半的长度
    PreToPost(pre,l1+1,l1+half,post,l2,l2+half-1);//递归左子树
    PreToPost(pre,l1+half+1,r1,post,l2+half,r2-1);//递归右子树
}   

16. 链表串联叶子节点

//记录全局变量pre和首个叶子节点,以任一种方式递归遍历
ListNode* head, *pre;//记录输出头指针和辅助前驱节点
ListNode* Inorder(TreeNode*root,int depth=1){//默认深度为1
    if(!root) return NULL;
    Inorder(root->left);//左递归入栈
    if(!root->left&&!root->right){//叶子节点
        if(pre==NULL)//首个叶子节点
            head = root, pre = root;
        else
            pre->right = root, pre = root;
    }
    Inorder(root->right);//右递归
}   

17. 判断相似

//后序遍历递归判断
bool Similar(TreeNode*l1,TreeNode*l2){
    if(!l1&&!l2) return true;//两树皆空
    else if(!l1||!l2) return false;//一树为空
    else return Similar(l1->left,l2->left)&&Similar(l1->right,l2->right);//递归判断
}

18.

19. 求带权路径长度

//先序遍历,累积求路径长度,递归时更新传入深度
int wpl = 0;
int WPL(TreeNode*root,int depth=0){//默认深度为0
    if(!root->left&&!root->right)
        wpl+=depth*root->val;
    if(root->left) WPL(root->left,depth+1);
    if(root->right) WPL(root->right,depth+1); 
    return wpl;
}

20. 输出中缀表达式

//中序遍历
void Inorderprint(TreeNode*root,int depth=1){//默认深度为1
    if(!root) return;
    if(!root->left&&!root->right)
        printf("%s",root->data);
    else{
        if(depth>1) printf("(");//有子表达式加一层括号
        Inorderprint(root->left,depth+1);//左递归
        printf("s",root->data);//输出
        Inorderprint(root->right,depth+1);//右递归
        if(depth>1) printf(")");//当前层结束加右括号
    }
}
posted @ 2022-08-21 23:04  失控D大白兔  阅读(32)  评论(0编辑  收藏  举报