//声明二叉树的节点数据结构
typedef struct node {
char data;
struct node *lchild, *rchild;
int flag;//只在后序非递归2中使用
}BiTNode,*BiTree;
int N = 0;//控制先序遍历序列的下标
/*
根据先序遍历序列建树
char *str为先序序列数组
*/
BiTree createTree(char *str) {
if (*(str + N) == '#') {
N++;
return NULL;
}
BiTree root = (BiTree)malloc(sizeof(BiTNode));
root->data = *(str + N);
N++;
root->lchild = createTree(str);
root->rchild = createTree(str);
return root;
}
/*
查找值为key的节点 返回节点的地址
bt为树的头指针
key为要查找的值
成功时返回值为节点的地址,失败返回null
*/
BiTree locate(BiTree bt, char key) {
BiTree res;
if (!bt) {
return NULL;
}
if (bt->data == key) {
return bt;
}
res = locate(bt->lchild, key);
if(!res)
res = locate(bt->rchild, key);
return res;
}
/*
先序遍历的非递归思想:
1,先将根节点入栈
2,从栈中弹出栈顶元素,若不为空,先将该节点的右孩子(非空,有时也要将空的入栈,视情况定)入栈,再将做孩子入栈。
3,重复2,3步。
*/
void preorder(BiTree bt) {//非递归先序遍历,可利用此遍历清晰的解决一些问题
BiTree stack[M],p;
int top = -1;
stack[++top] = bt;
while (top > -1) {
p = stack[top--];
if (p) {
printf("%c ", p->data);//直接输出结果
}
if(p->rchild)
stack[++top] = p->rchild;
if(p->lchild)
stack[++top] = p->lchild;
}
}
// c++ version
vector<int> preorderTraversal(TreeNode* root) {
// write code here
// 非递归,先将根节点压入栈,弹栈后,先压右节点再压左节点
if(root == nullptr) return {};
vector<int> ans;
stack<TreeNode*> stack;
stack.push(root);
while(!stack.empty()){
TreeNode* temp = stack.top();
stack.pop();
ans.push_back(temp->val);
if(temp->right) stack.push(temp->right);
if(temp->left) stack.push(temp->left);
}
return ans;
}
/*
先将左孩子入栈,再将右孩子入栈,正常访问,讲结果存入另一个辅助栈中,最后将辅助栈中的元素输出即为后序遍历结果
*/
void postorder_1(BiTree bt) {//后序非递归,相对较麻烦一点
BiTree MainStack[M], p;
char ViceStack[M];
int Maintop = -1,Vicetop=-1;
MainStack[++Maintop] = bt;
while (Maintop > -1) {
p = MainStack[Maintop--];
if (p) {
ViceStack[++Vicetop] = p->data;
}
if (p->lchild)
MainStack[++Maintop] = p->lchild;
if (p->rchild)
MainStack[++Maintop] = p->rchild;
}
while (Vicetop > -1)
printf("%c ", ViceStack[Vicetop--]);
printf("\n");
}
// c++ version
vector<int> postorderTraversal(TreeNode* root) {
if(root == nullptr) return {};
stack<TreeNode*> nodeStack;
stack<int> data;
vector<int> ans;
nodeStack.push(root);
TreeNode* temp = nullptr;
while(!nodeStack.empty()){
temp = nodeStack.top();
nodeStack.pop();
data.push(temp->val);
if(temp->left) nodeStack.push(temp->left);
if(temp->right) nodeStack.push(temp->right);
}
while(!data.empty()){
ans.push_back(data.top());
data.pop();
}
return ans;
}
/*
每次把栈顶元素出栈后,栈中剩余全为该元素的祖先
*/
void postorder_2(BiTree bt) {//后序非递归2,适合查找每个节点的所有祖先节点
BiTree stack[M], p;
int top = -1;
stack[++top] = bt;
stack[top]->flag = 1;
while (top > -1) {
p = stack[top];
if ((p->lchild == NULL || p->lchild->flag==1)&&(p->rchild == NULL || p->rchild->flag == 1)) {
p = stack[top--];//出栈后栈中的所有元素均为该元素的祖先
printf("%c ", p->data);
}
else if (p->lchild != NULL && p->lchild->flag==0) {
stack[++top] = p->lchild;
stack[top]->flag = 1;
}
else if (p->rchild != NULL && p->rchild->flag == 0) {
stack[++top] = p->rchild;
stack[top]->flag = 1;
}
}
}
/*
查找元素key的所有祖先节点,并输出
*/
void postorder_3(BiTree bt,char key) {
BiTree stack[M], p;
int top = -1;
stack[++top] = bt;
stack[top]->flag = 1;
while (top > -1) {
p = stack[top];
if ((p->lchild == NULL || p->lchild->flag == 1) && (p->rchild == NULL || p->rchild->flag == 1)) {
p = stack[top--];
if (p->data == key) {//判断要出栈的节点值是否与key相同,相同就退出循环,栈中的元素即为所求
break;
}
}
else if (p->lchild != NULL && p->lchild->flag == 0) {
stack[++top] = p->lchild;
stack[top]->flag = 1;
}
else if (p->rchild != NULL && p->rchild->flag == 0) {
stack[++top] = p->rchild;
stack[top]->flag = 1;
}
}
while (top > -1) {
printf("%c ", stack[top--]->data);
}
}
// cpp version 打印各个节点的祖先节点
// 寻找所有节点的祖先, 利用后序遍历
void getAnstor(TreeNode* rt){
if(rt == nullptr) return;
stack<TreeNode*> stack_, ts; // ts为中间栈
unordered_set<TreeNode*> hash;
stack_.push(rt);
TreeNode* temp = nullptr;
while(!stack_.empty()){
temp = stack_.top();
if((temp->left == nullptr || hash.count(temp->left) != 0) &&
(temp->right == nullptr || hash.count(temp->right) != 0)){
cout << temp->val << ": anstor have ";
// 倒栈,打印祖先,然后重新入栈
while(!stack_.empty()){
cout << stack_.top()->val << " ";
ts.push(stack_.top());
stack_.pop();
}
cout << "\n";
while(!ts.empty()){
stack_.push(ts.top());
ts.pop();
}
stack_.pop();
}else if(temp->left && hash.count(temp->left) == 0){
hash.insert(temp->left);
stack_.push(temp->left);
}else if(temp->right && hash.count(temp->right) == 0){
hash.insert(temp->right);
stack_.push(temp->right);
}
}
}
/*
中序非递归算法:
思想:
从传入的根节点开始,不断的先将左子树压入栈中(如果有的话),否则从栈中弹出栈顶元素并访问,随后进行访问当前节点的右子树,直到占空时退出,下面的while循环的第一个条件只在第一次进行while循环判断时有效,其后都是有top>-1进行判断的。参见leetcode 94二叉树遍历:
/*
#include<vector>
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
TreeNode* stack[256],*p;
int top = -1;
p = root;
while (p || top > -1) {
if (p) {
stack[++top] = p;
p = p->left;
}
else {
p = stack[top--];
res.push_back(p->val);
p = p->right;
}
}
return res;
}
};
*/
*/
void inorder(BiTree bt) {
BiTree stack[M],p;
int top = -1;
p = bt;
while (p || top > -1) {
if (p) {
stack[++top] = p;
p = p->lchild;
}
else {
p = stack[top--];
printf("%c ", p->data);
p = p->rchild;
}
}
}
// c++ version
vector<int> inorderTraversal(TreeNode* root) {
// write code here
if(root == nullptr) return {};
vector<int> ans;
stack<TreeNode*> stack;
TreeNode* temp = root;
while(temp || !stack.empty()){
if(temp){
stack.push(temp);
temp = temp->left;
}else{
ans.push_back(stack.top()->val);
temp = stack.top()->right;
stack.pop();
}
}
return ans;
}
// 二叉树层序遍历[牛客 BM26],利用队列
// cpp version
vector<vector<int> > levelOrder(TreeNode* root) {
// write code here
if(root == nullptr) return {};
vector<vector<int>> ans;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
int size = que.size();
vector<int> tempAns;
while(size--){
TreeNode* temp = que.front();
tempAns.push_back(temp->val);
que.pop();
if(temp->left) que.push(temp->left);
if(temp->right) que.push(temp->right);
}
ans.push_back(move(tempAns));
}
return ans;
}
下图为所建树
测试结果