归纳了一些刷题时候常见的树的算法,不算完整,后续还会补充;
#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);
}
}