树算法总结

归纳了一些刷题时候常见的树的算法,不算完整,后续还会补充;

#include<iostream>
#include<vector>
#include<stack>
#include<queue>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

//构建二叉树
TreeNode* CreateTree(){
    TreeNode* root;
    int ch;
    cin >> ch;
    if (ch == -1)return root = NULL;
    else{
        root = new TreeNode(ch);
        root->left = CreateTree();
        root->right = CreateTree();
    }
    return root;
}

/*
二叉查找
递归查找二叉排序树T中是否存在key,指针f指向T的双亲,其初始调用值为NULL
若查找成功,则指针p指向该数据元素结点,并返回TRUE
否则指针p指向查找路径上访问的最后一个结点并返回FALSE
*/
bool SearchBST(TreeNode *root, int key, TreeNode* f, TreeNode* &p){
    if (root == NULL){
        p = f;
        return false;
    }
    else if (root->val == key){
        p = root;
        return true;
    }
    else if (root->val < key){
        return SearchBST(root->right, key, root, p);
    }
    else
        return SearchBST(root->left, key, root, p);
}

//二叉树的插入操作
void InsertBST(TreeNode*& root, int key){
    TreeNode *p, *s;
    if (!SearchBST(root, key, NULL, p)){
        s = new TreeNode(key);
        if (!p)root = s;
        else if (p->val > key)p->left = s;
        else p->right = s;
    }
}

//判断二叉树是不是平衡二叉树(1)
int GetDepth(TreeNode *&root){
    if (root == NULL)return 0;
    int left = GetDepth(root->left);
    int right = GetDepth(root->right);
    return (left > right ? left : right) + 1;
}
bool IsBalanceTree(TreeNode*& root){
    if (root == NULL)return true;

    int leftDepth = GetDepth(root->left);
    int rightDepth = GetDepth(root->right);
    //会在这一步有重复的计算
    return (abs(leftDepth - rightDepth) <= 1) && IsBalanceTree(root->left) && IsBalanceTree(root->right);
}

//判断二叉树是不是平衡二叉树(2)
bool IsSubBalance(TreeNode*& root, int& depth){
    if (root == NULL){
        depth = 0;
        return true;
    }
    int left, right;
    //这里仿照后序遍历的方法,不会有重复的计算量
    if (IsSubBalance(root->left, left) && IsSubBalance(root->right, right)){
        if (abs(left - right) <= 1){
            depth = (left > right ? left : right) + 1;
            return true;
        }
    }
    return false;
}

bool IsBalanceTree1(TreeNode*& root){
    int depth = 0;
    return IsSubBalance(root, depth);
}

/*
二叉树--查找两个节点的最近共同父节点
(1)递归方式
假设给定pRoot是NULL,即空树,则返回的公共节点自然就是NULL;
假设给定pRoot与两个节点中不论什么一个同样,说明,pRoot在就是所要找的两个节点之中的一个,则直接返回pRoot,
表明在当前链路中找到至少一个节点;
假设给定pRoot不是两个节点中不论什么一个,则说明,须要在pRoot的左右子树中又一次查找,此时有三种情况:
两个节点都在左子树上;两个节点都在右子树上;一个在左子树,一个在右子树上;详细来说,就是:

情况一:假设左子树查找出的公共节点是NULL,则表明从左子树根节点開始到左子树的全部叶子节点等全部节点中,
没有找到两个节点中的不论什么一个,这就说明,这两个节点不在左子树上,不在左子树,则必然在右子树上;
情况二:假设右子树查找的公共节点是NULL,说明在右子树中无法找到不论什么一个节点,则两个节点必然在左子树上;
情况三:假设左右子树查找的公共节点都不是NULL,说明左右子树中各包括一个节点,则当前节点pRoot就是最低公共节点,返回就能够了。
*/

TreeNode* FindCommonParentNode(TreeNode* root, TreeNode* pNodeOne, TreeNode* pNodeTwo){
    if (root == NULL)return NULL;
    if (root == pNodeOne || root == pNodeTwo)return root;

    TreeNode* left = FindCommonParentNode(root->left, pNodeOne, pNodeTwo);
    TreeNode* right = FindCommonParentNode(root->right, pNodeOne, pNodeTwo);

    if (left == NULL)return right;
    else if (right == NULL)return left;
    else return root;
}

//前序遍历
void PreOrderTraverse1(TreeNode* root){
    if (root == NULL)return;
    cout << root->val << '\t';
    PreOrderTraverse1(root->left);
    PreOrderTraverse1(root->right);
}

//非递归前序遍历
void NoPreOrderTraverse(TreeNode* root){
    if (root == NULL)return;
    stack<TreeNode *> temp;
    TreeNode *p = root;
    while (!temp.empty() || p){
        if (p){
            temp.push(p);
            cout << p->val << '\t';
            p = p->left;
        }
        else{
            p = temp.top();
            temp.pop();
            p = p->right;
        }
    }
}

//中序遍历
void InOrderTraverse(TreeNode* root){
    if (root == NULL)return;
    InOrderTraverse(root->left);
    cout << root->val << "\t";
    InOrderTraverse(root->right);
}

//非递归的中序遍历,需要用到栈
void NoInorderTraverse(TreeNode* root){
    if (root == NULL)return;
    stack<TreeNode*>temp;
    TreeNode *p = root;
    while (!temp.empty() || p){
        if (p){
            temp.push(p);
            p = p->left;
        }
        else{
            p = temp.top();
            temp.pop();
            cout << p->val << '\t';
            p = p->right;
        }
    }
}
//后序遍历
void PostOrderTraverse(TreeNode* root){
    if (root == NULL)return;
    PostOrderTraverse(root->left);
    PostOrderTraverse(root->right);
    cout << root->val << "\t";
}

//非递归的后序遍历,需要用到栈
void NoPostOrderTraverse(TreeNode* root){
    if (root == NULL)return;
    stack<TreeNode *> temp;
    TreeNode* p = root;
    TreeNode *pre = NULL;
    while (!temp.empty() || p){
        while (p){
            temp.push(p);
            p = p->left;
        }
        p = temp.top();
        if (p->right == NULL || p->right == pre){
            cout << p->val << '\t';
            pre = p;
            p = NULL;
            temp.pop();
        }
        else{
            p = p->right;
        }
    }
}

//层次遍历
void LevelOrderTraverse(TreeNode* root){
    if (root == NULL)return;
    queue<TreeNode*> temp;
    temp.push(root);
    while (!temp.empty()){
        TreeNode *p = temp.front();
        cout << p->val << '\t';
        temp.pop();
        if (p->left)temp.push(p->left);
        if (p->right)temp.push(p->right);
    }
}

//在二叉树中找出和为某一值的所有路径
vector<vector<int>>res;
void FindPath(TreeNode* root, int sum, int target){
    if (root == NULL)return;
    static deque<int> stack;
    if (root->val + sum == target){
        vector<int> path(stack.begin(), stack.end());
        path.push_back(root->val);
        res.push_back(path);
        path.clear();
    }
    else if (sum + root->val > target)return;
    else{
        stack.push_back(root->val);
        FindPath(root->left, sum + root->val, target);
        FindPath(root->right, sum + root->val, target);
        stack.pop_back();
    }
}

//怎样编写一个程序,把一个有序整数数组放到二叉树中?
void RecurCreateTree(int *p, int len, TreeNode* &head){
    if (len > 0){
        int mid = len / 2;
        head = new TreeNode(p[mid]);
        RecurCreateTree(p, mid, head->left);
        RecurCreateTree(p + mid + 1, len - mid - 1, head->right);
    }
    else {
        head = NULL;
    }
}


//判断整数序列是不是二叉搜索树的后序遍历结果
bool isbt(int *a, int begin, int end){
    if (begin >= end)return true;
    else{
        int res = a[end];
        int i = begin;
        while (a[i] <= res)i++;
        int j = i;
        while (j <= end - 1){
            if (a[j] < res)return false;
        }
        return isbt(a, begin, i - 1) && isbt(a, i, end - 1);
    }
}

//求二叉树的镜像
//递归方式
void mirrorRecursively(TreeNode*& root){
    if (root == NULL || (root->left == NULL && root->right == NULL))return;
    TreeNode *temp = root->left;
    root->left = root->right;
    root->right = temp;
    if(root->left) mirrorRecursively(root->left);
    if(root->right) mirrorRecursively(root->right);
}

//非递归形式
void mirrorRecursively_loop(TreeNode*& root){
    if (root == NULL)return;
    stack<TreeNode*> temp;
    temp.push(root);
    while (!temp.empty()){
        TreeNode *p = temp.top();
        temp.pop();
        TreeNode *tt = p->left;
        p->left = p->right;
        p->right = tt;
        if (p->left)temp.push(p->left);
        if (p->right)temp.push(p->right);
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值