递归建二叉树时遇到的问题:
#include <iostream>
#include <vector>
using namespace std;
typedef struct treenode{
int val;
struct treenode *left;
struct treenode *right;
treenode(int x): val(x), left(nullptr), right(nullptr) {} //默认结构体构造方法
}Tnode,*pnode;
void create_tree(pnode root, vector<int> &pre, vector<int> &mid, int a, int b, int c, int d)
{
int tag = pre.at(a);
root = new treenode(pre.at(a));
// mid中第一次出现 tag的下标
int flag = 0;
for(int i = c; i<=d; i++)
{
if(mid.at(i) == tag)
{
flag = i;
break;
}
}
int left = flag - c;
int right = d - flag; // right + left = d-c +1
if(left != 0)
{
create_tree(root->left, pre, mid, a+1, a+left, c, c+left-1); //左子的 先序 中序
}
if(right != 0)
{
create_tree(root->right, pre, mid, a+left+1, b, c+left+1, d); //
}
}
void print_tree_pre(pnode root)
{
if(root == nullptr)
return;
else{
cout << root->val << ",";
print_tree_pre(root->left);
print_tree_pre(root->right);
}
}
int main()
{
vector<int> pre = {1,2,4,5,3,6,7}; // 中 左 右
vector<int> mid = {4,2,5,1,6,3,7}; // 左 中 右
pnode root = nullptr;
create_tree(root,pre,mid,0,6,0,6);
//print_tree_pre(root);
cout << "Hello World!" << endl;
cout << root->val << endl;
return 0;
}
无法打印出1
原因:
传入指针做入参。
在子函数中改变指针指向 ,对main中指针指向不起作用, root任然为nullptr。
只有传入指针的地址 才能影响main中指针的指向。
想要改什么并且能在main中同步变,就要传入什么的地址。
例子:
#include <iostream>
using namespace std;
int m = 4;
void fun(int *p)
{
p = &m;
cout << *p <<endl;
}
int main(void)
{
int a = 3;
int *p = &a;
fun(p); //4
cout << *p << endl; //3
}
二叉树的代码修改后:
#include <iostream>
#include <vector>
using namespace std;
typedef struct treenode{
int val;
struct treenode *left;
struct treenode *right;
treenode(int x): val(x), left(nullptr), right(nullptr) {} //默认结构体构造方法
}Tnode,*pnode;
void create_tree(pnode *root, vector<int> &pre, vector<int> &mid, int a, int b, int c, int d)
{
int tag = pre.at(a);
*root = new treenode(pre.at(a));
// mid中第一次出现 tag的下标
int flag = 0;
for(int i = c; i<=d; i++)
{
if(mid.at(i) == tag)
{
flag = i;
break;
}
}
int left = flag - c;
int right = d - flag; // right + left = d-c +1
if(left != 0)
{
create_tree(&(*root)->left, pre, mid, a+1, a+left, c, c+left-1); //左子的 先序 中序
}
if(right != 0)
{
create_tree(&(*root)->right, pre, mid, a+left+1, b, c+left+1, d); //
}
}
void print_tree_pre(pnode root)
{
if(root == nullptr)
return;
else{
cout << root->val << ",";
print_tree_pre(root->left);
print_tree_pre(root->right);
}
}
int main()
{
vector<int> pre = {1,2,4,5,3,6,7}; // 中 左 右
vector<int> mid = {4,2,5,1,6,3,7}; // 左 中 右
pnode root = nullptr;
create_tree(&root,pre,mid,0,6,0,6);
print_tree_pre(root); //1,2,4,5,3,6,7
cout << "Hello World!" << endl;
//cout << root->val << endl;
return 0;
}
运行成功
先序遍历栈实现
// 先序用栈
void print_tree_pre_no(pnode root)
{
stack<pnode> a;
pnode p = nullptr;
a.push(root);
while(!a.empty())
{
p = a.top();
cout << a.top()->val <<",";
a.pop();
if(p->right)
a.push(p->right);
if(p->left)
a.push(p->left);
}
}
中序遍历栈实现
void print_tree_mid_no(pnode root) //左 中 右
{
stack<pnode> a;
pnode p = root;
do //遍历p的过程
{
while(p!=nullptr) //走到最左
{
a.push(p);
p = p->left;
}
// 没有左了 打印当前 遍历右(p指向当前的右)
cout << a.top()->val <<","; //最左 //7
p = a.top()->right; //遍历当前的右子树
a.pop();
}while(!a.empty() || p!=nullptr);
}
后序遍历栈实现
// 正常的顺序思维
void print_tree_back_no(pnode root) //左 右 中
{
stack<pnode> a;
pnode p = root;
pnode last = nullptr;
do //遍历p的过程
{
B:
while(p!=nullptr) //走到最左
{
a.push(p);
p = p->left;
}
A:
p = a.top();
if(p->right == nullptr)//遍历当前的右子树
{
cout << a.top()->val << endl;
a.pop();
last = p;
goto A;
}
else if(p->right == last)
{
cout << a.top()->val << endl;
a.pop();
last = p;
goto A;
}
else //p的左遍历完 遍历p的右
{
p = p->right;
goto B;
}
}while(!a.empty() || p!=nullptr);
}
思路
对1
–2—3
4 5 6 7
要遍历p:
124入栈;
取p = 4,
p右为空,(p的左右遍历完了)
取p;
last 记录4;(上一个遍历的是4)
取p = 2;
p右为5;
5入栈; // p = p->right; goto B;
取p = 5;
p右为空,(p的左右遍历完了)
取p;
last 记录5;(上一个遍历的是5)
取p = 2;
p右为5;
上一个遍历过5了
取2;
last记录2;
取p= 1;仿照上面完成遍历;
整理后代码:
void print_tree_back_no(pnode root) //左 右 中
{
stack<pnode> a;
pnode p = root;
pnode last = nullptr;
do //遍历p的过程
{
while(p!=nullptr) //走到最左
{
a.push(p);
p = p->left;
}
A:
p = a.top();
if(p->right == nullptr || p->right == last) //右子树遍历好了
{
cout << a.top()->val << endl;
a.pop();
last = p;
goto A;
}
else //p的左遍历完 遍历p的右
{
p = p->right;
}
}while(!a.empty());
}
如果想再去掉goto A;代码如下:
void print_tree_back_no(pnode root) //左 右 中
{
stack<pnode> a;
pnode p = root;
pnode last = nullptr;
do //因为跳出是在里面进行的 这个循环可以改成 while(1)
{
while(p!=nullptr) //走到最左
{
a.push(p);
p = p->left;
}
while(a.top()->right == nullptr || a.top()->right == last) //右子树遍历好了
{
cout << a.top()->val << ",";
last = a.top();
a.pop();
if(a.empty()) //a空则遍历完了
return;
}
p = a.top()->right; //遍历p的右
}while(!a.empty());
}
顺序遍历 队列实现:
// 顺序遍历 队列实现
void print_tree_order_no(pnode root)
{
queue<pnode> a;
pnode p = root;
a.push(p);
while(!a.empty())
{
p = a.front();
cout << p->val << ",";
if(p->left != nullptr) //不可以写成 !p->left
a.push(p->left);
if(p->right != nullptr)
a.push(p->right);
a.pop();
}
}
后序遍历的其他方法:
将二叉树转为镜像二叉树,顺序遍历镜像二叉树后再reverse();
// 以下为转镜像二叉树
void mirror(pnode root)
{
stack<pnode> a;
pnode p = root;
a.push(root);
while(!a.empty())
{
p = a.top();
pnode tmp = p->left;
p->left = p->right;
p->right = tmp;
a.pop();
if(p->left!=nullptr)
a.push(p->left);
if(p->right!=nullptr)
a.push(p->right);
}
cout << "验证:";
print_tree_pre(root);
}
完整代码:
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
typedef struct treenode{
int val;
struct treenode *left;
struct treenode *right;
treenode(int x): val(x), left(nullptr), right(nullptr) {} //默认结构体构造方法
}Tnode,*pnode;
void create_tree(pnode *root, vector<int> &pre, vector<int> &mid, int a, int b, int c, int d)
{
int tag = pre.at(a);
*root = new treenode(pre.at(a));
// mid中第一次出现 tag的下标
int flag = 0;
for(int i = c; i<=d; i++)
{
if(mid.at(i) == tag)
{
flag = i;
break;
}
}
int left = flag - c;
int right = d - flag; // right + left = d-c +1
if(left != 0)
{
create_tree(&(*root)->left, pre, mid, a+1, a+left, c, c+left-1); //左子的 先序 中序
}
if(right != 0)
{
create_tree(&(*root)->right, pre, mid, a+left+1, b, c+left+1, d); //
}
}
void print_tree_pre(pnode root)
{
if(root == nullptr)
return;
else{
cout << root->val << ",";
print_tree_pre(root->left);
print_tree_pre(root->right);
}
}
// 先序用栈
void print_tree_pre_no(pnode root)
{
stack<pnode> a;
pnode p = nullptr;
a.push(root);
while(!a.empty())
{
p = a.top();
cout << a.top()->val <<",";
a.pop();
if(p->right)
a.push(p->right);
if(p->left)
a.push(p->left);
}
}
void print_tree_mid_no(pnode root) //左 中 右
{
stack<pnode> a;
pnode p = root;
do //遍历p的过程
{
while(p!=nullptr) //走到最左
{
a.push(p);
p = p->left;
}
// 没有左了 打印当前 遍历右(p指向当前的右)
cout << a.top()->val <<","; //最左 //7
p = a.top()->right; //遍历当前的右子树
a.pop();
}while(!a.empty() || p!=nullptr);
}
void print_tree_back_no(pnode root) //左 右 中
{
stack<pnode> a;
pnode p = root;
pnode last = nullptr;
do
{
while(p!=nullptr) //走到最左
{
a.push(p);
p = p->left;
}
while(a.top()->right == nullptr || a.top()->right == last) //右子树遍历好了
{
cout << a.top()->val << ",";
last = a.top();
a.pop();
if(a.empty()) //a空则遍历完了
return;
}
p = a.top()->right; //遍历p的右
}while(!a.empty());
}
// 顺序遍历 队列实现
void print_tree_order_no(pnode root)
{
queue<pnode> a;
pnode p = root;
a.push(p);
while(!a.empty())
{
p = a.front();
cout << p->val << ",";
if(!p->left)
a.push(p->left);
if(!p->right)
a.push(p->right);
a.pop();
}
}
// 转镜像二叉树 先序遍历 再reverse
void mirror(pnode root)
{
stack<pnode> a;
pnode p = root;
a.push(root);
while(!a.empty())
{
p = a.top();
pnode tmp = p->left;
p->left = p->right;
p->right = tmp;
a.pop();
if(p->left!=nullptr)
a.push(p->left);
if(p->right!=nullptr)
a.push(p->right);
}
cout << "验证:";
print_tree_pre(root);
}
int main()
{
vector<int> pre = {1,2,4,5,3,6,7}; // 中 左 右
vector<int> mid = {4,2,5,1,6,3,7}; // 左 中 右
pnode root = nullptr;
create_tree(&root,pre,mid,0,6,0,6);
print_tree_pre(root);
cout << "Hello World!" << endl;
//cout << root->val << endl;
cout << "先序:";
print_tree_pre_no(root);
cout << endl;
cout << "中序:";
print_tree_mid_no(root);
cout << endl;
cout << "后序:";
print_tree_back_no(root);
cout << endl;
cout << "顺序:";
print_tree_order_no(root);
cout << endl;
cout << "mirror\n";
mirror(root);
return 0;
}