文章目录
在任意一棵非空二叉排序树T1中,删除某结点v之后形成二叉排序树T2,再将v插入T2形成二叉排序树T3。
若v是T1的叶结点,则T1与T3相同1.若v不是T1的叶结点,则T1与T3不同
144.前序遍历
//Note: The returned array must be malloced, assume caller calls free().
//给数组开空间
int Treesize( struct TreeNode*root){
if(root == NULL)
return 0;
return 1 + Treesize(root->left) + Treesize(root->right);}
//前序遍历
void _preorderTraversal( struct TreeNode* root,int* array,int* pi)
{if(root == NULL)
return;//因为是void _preorderTraversal所以返回的不是 return 0
//return;不带返回值的return语句
//return 0;带返回值的return语句,或者返回一个变量或一个函数。
array[ (*pi)++] = root->val;
//方法1(错误):传值,传值过程中 ,每个递归里都有1个i,我的(上1个递归函数)i传给你(下1个递归函数),你+了,但不会影响我,我没有+,
//方法2(正确):只能有一个i,传地址,每次解引用之后 是同一个i,使用pi指针,这样在递归得过程中,对同一个下标i++
_preorderTraversal( root->left, array ,pi);
_preorderTraversal( root->right,array,pi);}
int* preorderTraversal(struct TreeNode *root, int* returnsize){
int size = Treesize(root);
int* array = ( int*)malloc(sizeof(int)*size);int i = 0;
_preorderTraversal(root,array,&i);
*returnsize = size ;
return array;}
非递归:
class Solution {
public:
vector<int> preorderTraversal(TreeNode*root) {
vector<int> v;
stack<TreeNode*> st;
TreeNode*cur = root;
// cur不为空,表示还有树没有开始访问,st不为空,表示还有节点的右子树没有访问
while(cur || !st.empty())
{
// 1、访问左路节点并保存进栈里,把节点压栈为了左路节点都访问完之后回来访问右路子树
while (cur)
{
v.push_back(cur->val);
st.push(cur);
cur = cur->left;
}
// 2、对于root这棵树,乘下的是左路节点的右子树没有访问
//依次从栈里面拿出来左路节点,访问其右子树
TreeNode*top = st.top();
st.pop();
// 右树
cur = top->right;
}
return v;
}
};
访问左路节点1 2 12 并保存进栈里,弹出12 ,访问12的右子树,访问4的左子树5,再访问6,再访问2的右,
145. 后序遍历
class Solution {
public:
vector<int> postorderTraversal(TreeNode*root) {
vector<int> v;
TreeNode* prev = nullptr;
stack<TreeNode*> st;
TreeNode*cur = root;
while (cur || !st.empty())
{
//保存左路节点进栈
while (cur)
{
st.push(cur);
cur = cur->left;
}54
//对于root这棵树,剩下的是左路节点和左路节点右子树没有访问
//依次从栈里面拿出来访问
TreeNode* top = st.top();
//如果右为空,或者右孩子等于上一个访问的节点,则右树都访问过了
//取出当前节点访问
if (top->right == nullptr || top->right == prev)
{
v.push_back(top->val); st.pop();
prev = top;
cur = nullptr;
}
else{
//右树
cur = top->right;
}
}
return v;
}
};
凡是右不为空,都会两次经过这个节点,要想办法区分:两次经过4,第1次经过时,4的右还没有访问,访问右;第2次经过时,4的右已经访问,访问4,再把4出栈。
if 他的右孩子(6)等于上一个访问的节点(5),那么他的右树已经访问过了,应该放他本身, else他的右孩子(6)不等于上一个访问的节点(5),那么他的右树还没有访问,访问(6)右树。
KY11 中序遍历
#include<stdio.h>
#include<stdlib.h>
typedef struct TreeNode
{
char _val;
struct TreeNode* pleft;
struct TreeNode* pright;
}TreeNode;
TreeNode* CreateTree(char* arr,int *pi)
{
if (arr[*pi] == '#')
{
return NULL;
}
else
{
TreeNode * root = (TreeNode *)malloc (sizeof(TreeNode));
root->_val = arr[*pi] ;
++(*pi);
root->pleft = CreateTree(arr,pi);
++(*pi);
root->pright = CreateTree(arr,pi);
return root;
}
}
void InorderTraversal(TreeNode * root)
{
if (root == NULL)
{
return ;
}
InorderTraversal(root->pleft);
printf("%c ",root->_val);
InorderTraversal(root->pright);
}
int main()
{
char arr[100];
scanf("%s",arr);
int i = 0;
TreeNode * root = CreateTree(arr,&i);
InorderTraversal(root);
return 0;
}
之字形顺序打印二叉树
添加链接描述
当前层从左向右遍历访问,下层就从left到right入栈;当前层如果从右向左遍历,下层就从right到 left入栈。first:先入栈 ,second:后入栈。
v.push_back:访问完第1层;q.push:第2层;队列里的节点放入到栈;访问第2层:v.push_back
栈:[3 2]:访问3时,先入6;再访问2时,先入队列5 再入队列4,即[6 5 4];放入栈:[4 5 6]
vector<vector<int> > Print(TreeNode* pRoot) {
vector<vector<int> > result;
if (pRoot == nullptr)
{ return result; }
stack<TreeNode*> st; //保存要遍历的节点 栈
queue<TreeNode*> q; //临时队列:辅助,stack不能既用来出,又用来进
st.push(pRoot);
int dir = 1; //方向dir=1. 入栈顺序从left开始. 2.入栈顺序从right开始.
vector<int> v; 保存临时节点
while(!st.empty())
{
int size = st.size();
for(int i = 0; i < size; i++)
{ //清空本轮stack结构,并遍历,stack本身有逆序的功能
TreeNode *curr = st.top();
st.pop(); 把栈顶元素pop
v.push_back(curr->val); 把pop出的元素放入v
TreeNode *first = (dir == 1)?curr->left:curr->right;
TreeNode *second = (dir == 1)?curr->right:curr->left;
//将下一轮访问顺序放入q中 层序遍历
if(first != nullptr)
q.push(first);
if(second != nullptr)
q.push(second);
}//将1层符合要求的所有节点,入result
result.push_back(v);
//将下一轮访问节点入栈,进行逆序
while(!q.empty())
{ st.push(q.front());把队列里的内容放入栈,q.front():队列的头节点
q.pop(); }//一层遍历完毕,就要更改入栈顺序:
dir = (dir == 1)? 2 : 1;
v.clear();
}
return result;
}
层序
102.二叉树的层序遍历:
方法1:P21第21页:q.size();//获取当前层的数据个数//当前层出完以后,队列中存的就是下一层的所有节点。队列里面只保存一层节点。for循环:1层里的细节。 { //pop完本层all节点,压入下一层all节点。边出队列边入队列。 q.pop(); //去掉当前节点 。
方法2:
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>vv;
if (root == nullptr)
return vv;
vector<TreeNode* > curV;
vector<TreeNode*> nextV;
curV.push_back(root);
while (!curV.empty())
{
vector<int> v;
for (auto e : curV)
{
v.push_back(e->val);
if (e->left)
nextV.push_back(e->left);
if (e->right)
nextV.push_back(e->right);
}
vv.push_back(v);
curV.swap(nextV);
nextV.clear( );
}
return vv;}
};
nextV、curV里放的是节点,不是值,而要求返回的是节点的值
从上往下打印二叉树 层序遍历
vector<int> PrintFromTopToBottom(TreeNode* root) {
if (root == nullptr)
{ return vector<int>();
}
vector<int> v;
queue<TreeNode*> q; 队列 先进先出
q.push(root);
while (!q.empty())
{
TreeNode *father = q.front();
q.pop();出节点
v.push_back(father->val);访问节点
if (father->left){ //左子树不为空 ,当前节点的左入队
q.push(father->left); }
if(father->right){//右子树不为空,当前节点的右入队
q.push(father->right); }
}
return v;
}
搜索树BST 后序遍历
添加链接描述
后序序列S,最后一个元素是x (root节点),如果去掉最后一个元素的序列为 T,T满足:T分成两段,前一段(左子树)小于x,后一段(右子树)大于x,且这两段(子树)都是合法的后序序列 //验证思路:当前序列,及其子序列必须都满足上述定义。闭区间,
bool VerifySquenceOfBSTCore(vector<int> &sequence, int start, int end){
if (start >= end)
{
//在不断查找过程中,区域不断缩小,为空时,证明之前的所有范围都满足检测条件
//也就是是一个BST
return true; }//拿到root节点的值
int root = sequence[end];
//先遍历左半部分,也就是整体都要比root小,拿到左子树序列
int i = start;
while(i < end && sequence[i] < root)
{ i++; }
//在检测右子树是否符合大于root的条件,要从i开始,也就是右半部分的开始
for(int j = i; j < end; j++)
{ if(sequence[j] < root)
{
//在合法位置处,当前值小于root,不满足BST定义
return false;
}
}//走到这里,就说明,当前序列满足需求。但并不代表题目被解决了,还要在检测left和right各自是否也满足
return VerifySquenceOfBSTCore(sequence, 0, i-1) && VerifySquenceOfBSTCore(sequence, i, end-1);
}
bool VerifySquenceOfBST(vector<int> sequence)
{ if(sequence.empty())
{ return false; }
return VerifySquenceOfBSTCore(sequence, 0, sequence.size()-1);
}sequence.size()-1:若有5个元素,最后1个的下标:4
965.单值二叉树
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回true;否则返回false 。输入:[1,1,1,1,1,null,1]输出:true
/* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right; * }; */
bool isUnivalTree( struct TreeNode* root){
if( root == NULL)
return true;//左是空=右是空,具有相同的值,这个值是空
//大框架是前序遍历(根 左右子树 ),切分子树
//当前树
if(root->left && root->val != root->left->val)
return false;
if(root->right &&root->val != root->right->val)
return false;
//递归判断左右子树
return isUnivalTree(root->left) && isUnivalTree(root->right);}
226.求二叉树的镜像
struct TreeNode* invertTree(struct TreeNode* root){
if(root == NULL){
return NULL;}
else{//方法2:中序和后序结合
struct TreeNode* right = root->right;//先复制1个右,否则下面左右交换时,会把原来的右覆盖掉
root->right = invertTree( root->left);
root->left = invertTree(right);
return root;}}
100.2个二叉树是否相同。
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p == NULL && q == NULL)
return true;//不仅这里可能返回true,最后那个return也可能返回true
//结构不同
if(p == NULL && q != NULL)
return false;
//结构不同
if(p != NULL && q == NULL)
return false;
//值不同
if(p->val != q->val)
return false;
//递归开始,以叶子节点2为例:左=空 && 右=空,返回true给2
return isSameTree(p->left,q->left)
&& isSameTree(p->right, q->right );
}
572.s 中是否包含和t具有相同结构和节点值的子树。
添加链接描述
二叉树都是递归定义的,所以递归操作是比较常见的做法,1. 先确定起始位置 //2. 在确定从该位置开始,后续的左右子树的内容是否一致
和当前节点不一样,但可能和其左(右)子树是一样的
//遍历每个节点所在的子树,每个节点当作根,都比较一下
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p == NULL && q == NULL)
return true;
if(p == NULL && q != NULL)
return false;
if(p != NULL && q == NULL)
return false;
if(p->val != q->val)
return false;
return isSameTree(p->left,q->left)
&& isSameTree(p->right, q->right );
}
bool isSubtree(struct TreeNode* s, struct TreeNode* t){
if( s == NULL)
return false;
if( isSameTree(s, t))
return true;
return isSubtree( s->left, t) || isSubtree(s->right, t);
}
110.是否是高度平衡
//方法2:从叶子开始,倒着往上走;左右2边一旦有 1个false则不计算gap;后序判断,判断的同时把高度带给上一层的父亲,过程如上图;优化到最坏是 o(N)
bool _isBalanced(struct TreeNode* root,int* pDepth){
if(root == NULL){
* pDepth=0;
return true;}
else{
int leftDepth = 0;
if(_isBalanced( root->left,&leftDepth) == false)
return false;
int rightDepth = 0;
if(_isBalanced(root->right,&rightDepth) == false)
return false;
//左右树都满足,开始判断当前树,返回false时,高度已经不重要了
if(abs ( leftDepth - rightDepth) > 1)
return false;
*pDepth = leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
return true;//只有返回true时,才算高度
}}
bool isBalanced ( struct TreeNode*root){
int depth = 0;
return _isBalanced(root, &depth) ;
}
error: non-void function does not return a value in all control paths [-Werror,-Wreturn-type]:函数并不是所有分支都有返回值。只包括了y=0 、1、2,三种情况,事实上由于输入参数number是整数,确实也只有这三种情况,但编译器不这样认为,编译器认为还存在其他情况,所以把 else if(y==2)改称else就能包含所有情况了,编译也就不会出现有的情况没有返回值的情况了。没给返回值。