(本博客主要是用法,对于二叉树的实现没有过多的讲解好像)
菜鸡一枚,不喜勿喷!~~~~
结点结构
struct Tree
{
int val;
Tree *left;
Tree *right;
};
先序遍历
//递归遍历
void preorderTraversal(Tree* head)
{
if(head == nullptr)return;
cout<val<left);
preorderTraversal(tree->right);
}
//非递归遍历
void preorderTraversal(Tree* head)
{
stacks;
s.push(head);
while(!s.empty())
{
head = s.top();
s.pop();
cout<val<<" ";
if(head->right)
s.push(head->right);
if(head->left)
s.push(head->left);
}
}
中序遍历
//递归遍历
void inOrderUnRecur(Tree* head)
{
if(head == nullptr)return;
inOrderUnRecur(tree->left);
cout<val<right);
}
//非递归遍历
void inOrderUnRecur(Tree* head)
{
stacks;
while (head!=nullptr||!s.empty())
{
//左边界进栈
if (head)
{
s.push(head);
head = head->left;
}
//弹出节点,到右数 重复过程
else
{
head = s.top();
s.pop();
cout << head->val << " ";
head = head->right;
}
}
}
后序遍历
//递归遍历
void postorderTraversal(Tree* head)
{
if(head == nullptr)return;
postorderTraversal(tree->left);
postorderTraversal(tree->right);
cout<val<s;
stackcollection;
s.push(head);
while(!s.empty())
{
head = s.top();
collection.push(head);
s.pop();
if(head->left)
s.push(head->left);
if(head->right)
s.push(head->right);
}
while(!collection.empty())
{
cout<
深度优先遍历 == 先序遍历
宽度优先遍历
用 队列 先放头节点,出队列打印,先放左后放右
void widthTraversal(Tree* head)
{
if (head == nullptr)return;
queueq;
q.push(head);
while (!q.empty())
{
head = q.front();
q.pop();
cout << head->val << " ";
if (head->left)
{
q.push(head->left);
}
if (head->right)
{
q.push(head->right);
}
}
}
//层序遍历
class Solution {
public:
vector> levelOrder(TreeNode* root) {
vector > ret;
if (!root) {
return ret;
}
queue q;
q.push(root);
//每次队列从有到无代表着一层
while (!q.empty()) {
//获取该层的元素个数
int currentLevelSize = q.size();
ret.push_back(vector ());
for (int i = 1; i <= currentLevelSize; ++i) {
auto node = q.front(); q.pop();
ret.back().push_back(node->val);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}
return ret;
}
};
//在深度优先遍历上更改
//使用哈希表
int maxTreeWidth(Tree* head)
{
if (head == nullptr)return 0;
queueq;
unordered_maplevelMap;
//当前的层数 当前层数结点的个数 最大宽度
int curLevel = 1, curLevelNodes = 0, maxNum = -1;
levelMap.insert(make_pair(head, curLevel));
q.push(head);
while (!q.empty())
{
head = q.front();
q.pop();
//根据树的结点找到当前结点的层数
unordered_map::iterator curNodeLevel = levelMap.find(head);
if (curNodeLevel->second == curLevel)
curLevelNodes++;
else
{
maxNum = max(maxNum, curLevelNodes);
++curLevel;
curLevelNodes = 1;
}
if (head->left)
{
levelMap.insert(make_pair(head->left, (curNodeLevel->second) + 1));
q.push(head->left);
}
if (head->right)
{
levelMap.insert(make_pair(head->right, (curNodeLevel->second) + 1));
q.push(head->right);
}
}
return max(maxNum, curLevelNodes);
}
//不使用哈希表 有限几个变量
int maxTreeWidthNoHash(Tree* head)
{
if (head == nullptr)return 0;
queueq;
q.push(head);
Tree* levelEnd = head, * nextEnd = head;
int num = 1, maxNum = -1;
while (!q.empty())
{
head = q.front();
q.pop();
if (head->left)
{
q.push(head->left);
nextEnd = head->left;
}
if (head->right)
{
q.push(head->right);
nextEnd = head->right;
}
if (head == levelEnd)
{
maxNum = max(maxNum, num);
num = 1;
levelEnd = nextEnd;
nextEnd = nullptr;
}
else
{
num++;
}
}
return maxNum;
}
class Solution {
public:
int levelOrder(Tree* root) {
int ret = 0;
if (!root) {
return ret;
}
queue q;
q.push(root);
//每次队列从有到无代表着一层
while (!q.empty()) {
//获取该层的元素个数
int currentLevelSize = q.size();
ret = max(ret, currentLevelSize);
//循环的目的就是清空每一层的节点
for (int i = 1; i <= currentLevelSize; ++i) {
auto node = q.front(); q.pop();
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}
return ret;
}
};
左边小 中间在其中 右边大
右边>中间>左边
判断是否为BST:可以中序遍历进行判断
//递归实现
bool isBST(Tree* head)
{
if (!head)return false;
//判断左树是否为搜索二叉树
bool leftIsBST = isBST(head->left);
int preValue = INT32_MIN;
//左边的BST
if (leftIsBST)
{
//将上次的值改为当前结点的值
preValue = head->val;
}
else
{
return false;
}
//走到这说明左树是BST,直接返回右数是否为BST
return isBST(head->right);
}
//非递归实现
bool isBSTNoRecursion(Tree* head)
{
stacks;
int preValue = INT32_MIN;
while (!s.empty()||head!=nullptr)
{
if (head)
{
s.push(head);
head = head->left;
}
else
{
head = s.top();
s.pop();
if (preValue>=head->val)
return false;
else
preValue = head->val;
head = head->right;
}
}
return true;
}
//黑盒实现 这种情况默认子树给整棵树所有想要的信息 二叉树递归套路
struct returnData
{
int max;
int min;
//是否为搜索二叉树
bool isBST;
//代表树是否村子啊
bool isFlag;
returnData(bool is, int mi, int ma,bool f) :max(ma), min(mi), isBST(is), isFlag(f) {}
};
returnData process(Tree* head)
{
if (head==nullptr)
{
return returnData(true,INT32_MIN,INT32_MAX,false);
}
//获取左树的信息
returnData left = process(head->left);
//获取右树的信息
returnData right = process(head->right);
//整棵树的信息
bool isBST = true;
int min_X = head->val;
int max_X = head->val;
if (left.isFlag)
{
min_X = min(min_X, left.min);
max_X = max(max_X, left.max);
}
if (right.isFlag)
{
min_X = min(min_X, right.min);
max_X = max(max_X, right.max);
}
if (left.isFlag&&(!left.isBST || left.max>=head->val))
{
isBST = false;
}
if (right.isFlag && (!right.isBST || right.min <= head->val))
{
isBST = false;
}
return returnData(isBST, min_X, max_X,true);
}
怎么判断?按照宽度遍历
条件
bool isCBT(Tree* head)
{
queueq;
q.push(head);
//是否遇到了第一个左右不全的节点
bool flag = false;
while (!q.empty())
{
head = q.front();
q.pop();
if (
//左空 右不空
(head->left== nullptr &&head->right!=nullptr)
||
//遇到第一个左右不全的节点,后续的节点有的不是叶节点
(flag&&(head->left != nullptr || head->right != nullptr))
)
{
return false;
}
if (head->left)
q.push(head->left);
if (head->right)
q.push(head->right);
if (head->left == nullptr || head->right == nullptr)
{
flag = true;
}
}
return true;
}
节点个数(N)和最大深度(L)满足:N = 2^L - 1
//满二叉树
class manBinaryTree
{
private:
struct returnData
{
int nodes;
int height;
returnData(int n, int h) :nodes(n), height(h) {}
};
returnData process(Tree* &head)
{
if (head == nullptr)
{
return returnData(0, 0);
}
returnData left = process(head->left);
returnData right = process(head->right);
int height = max(left.height, right.height) + 1;
int nodes = left.nodes + right.nodes + 1;
return returnData(nodes, height);
}
public:
bool isMBT(Tree*& head)
{
returnData data = process(head);
cout << "nodes" << data.nodes << " " << "height:" << data.height << endl;
//1 << data.height代表 1右移data.height位 就是2的data.height次方
return data.nodes == ( (1 << data.height) - 1);
}
};
任一一颗子树,左树的高度和右树的高度差都不能大于一
//代码黑盒 二叉树递归套路
class balanceBinaryTree
{
public:
struct returnData
{
bool isBBT;
//树的高度
int height;
returnData(bool bbt, int h) :isBBT(bbt), height(h) {}
};
returnData process(Tree* head)
{
if (head == nullptr)
{
return returnData(true, 0);
}
returnData left = process(head->left);
returnData right = process(head->right);
//整棵树的信息
//此处会计算树的高度
int height = max(left.height, right.height) + 1;
bool isBBT = true;
if (!left.isBBT||!right.isBBT||abs(left.height - right.height)>1)
isBBT = false;
return returnData(isBBT, height);
}
};
树型DP
给定一棵树,认为左右子树可以给自己所有想要的信息
实用
//使用哈希表实现
//套路的实现 具体看上图
class LowestAncestor
{
public:
Tree* lowerAncestorFun(Tree* head, Tree* o1, Tree * o2)
{
return process(head, o1, o2);
}
private:
Tree* process(Tree* head, Tree* o1, Tree* o2)
{
if (head == nullptr||head==o1||head==o2)
return head;
Tree* left = process(head->left,o1,o2);
Tree* right = process(head->right, o1, o2);
//左边右边都不为空的话 代表该head为公共祖先
if (left!=nullptr&&right!=nullptr)
return head;
//代表左右两个节点全null返回null 一个不为空返回不为空的哪一个
return (left != nullptr) ? left : right;
}
};
一种情况没有父指针:时间复杂度O(N)
如果两个节点距离相差为k:时间复杂度O(K)
struct TreeP
{
int val;
TreeP* left;
TreeP* right;
TreeP* parent;
TreeP() : val(0), left(nullptr), right(nullptr),parent(nullptr) {}
TreeP(int x) : val(x), left(nullptr), right(nullptr), parent(nullptr) {}
TreeP(int x, TreeP* left, TreeP* right, TreeP* parent) : val(x), left(left), right(right), parent(parent) {}
};
//后继节点
class FindBackList
{
public:
TreeP* findBackList(TreeP* curList)
{
if (curList == nullptr)
return nullptr;
//有右树
if (curList->right)
return findLeft(curList->right);
//无右树
else
{
TreeP* parent = curList->parent;
while (parent!=nullptr&& curList != parent->left)
{
curList = parent;
parent = curList->parent;
}
return parent;
}
}
private:
TreeP* findLeft(TreeP* head)
{
while (head->left)
head = head->left;
return head;
}
};
//序列化和反序列化
class TreeBeString
{
public:
string treeBeString(Tree* head)
{
if (head == nullptr)return "#_";
string res =to_string(head->val)+ "_";
res+=treeBeString(head->left);
res+=treeBeString(head->right);
return res;
}
Tree* stringBeTree(string s)
{
int pos = -1,index = 1;
int len = s.size();
queuech;
//6_5_4_#_#_6_#_#_9_8_#_#_10_#_#_
while (poss)
{
string value = s.front();
s.pop();
if (value == "#")
return nullptr;
//aoti将char 或者 char[]转化为int
Tree* head = new Tree(atoi(value.c_str()));
head->left = reconByPreString(s);
head->right = reconByPreString(s);
return head;
}
};
//纸条遍历
class T
{
public:
void printAllFolds(int N)
{
//false代表 凹 true代表凸
process(1, N, false);
}
private:
void process(int i, int N, bool down)
{
//相当于模拟中序遍历二叉树 并不实际存在的二叉树
//i代表当前层数
if (i > N)return;
process(i + 1, N, false);
cout <<(down ? "凸" : "凹");
process(i + 1, N, true);
}
};