二叉树的相关操作一(建树,遍历(非递归),查找指定节点)c版本代码和cpp版本代码

//声明二叉树的节点数据结构
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;
    }

下图为所建树
在这里插入图片描述
测试结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值