二叉树各种遍历的结合模板

二叉树各种遍历模板

以下代码假设输入的是先序遍历和中序遍历输出后序遍历

测试用例
3
1 2 3
2 1 3

2 3 1

7
1 2 4 6 5 7 3
6 4 2 5 7 1 3

6 4 7 5 2 3 1

先序遍历 + 中序遍历 = 后序遍历

仅要求输出序列
如果改成后序遍历和中序遍历输出先序遍历,只需要把遍历中的root改成后序遍历中最后一个数字即可(因为后序的最后一个节点为先序的第一个节点)

#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> pre;
vector<int> in;

/*写得剪短一点
//root是指pre中的索引,start\end是指in中的索引
void postorder(int root,int start,int end){
	if(start > end)return;
	int i = start;
	while(i < end&&in[i] != pre[root])++i;
	//左(root + 1,root + i - start)
	postorder(root + 1,start,i - 1);
	//右(root + i - start + 1,end)
	postorder(root + i - start + 1,i + 1,end);
	cout << pre[root] << endl;
}
*/


void postorder(int root, int start, int end) {
	if (start > end) {
		return;
	}
	int i = start;
	for (; i < end; ++i) {
		if (pre[root] == in[i]) {
			break;
		}
	}
	if (i != start) {
		postorder(root + 1, start, i - 1);
	}
	if (i != end) {
		postorder(root + 1 + i - start, i + 1, end);
	}
	cout << pre[root] << ' ';
	return;
}

void preorder(int root, int start, int end) {
	if (start > end) {
		return;
	}
	int i = start;
	for (; i < end; ++i) {
		if (pre[root] == in[i]) {
			break;
		}
	}
	cout << pre[root] << ' ';
	if (i != start) {
		preorder(root + 1, start, i - 1);
	}
	if (i != end) {
		preorder(root + 1 + i - start, i + 1, end);
	}
	return;
}

void inorder(int root, int start, int end) {
	if (start > end) {
		return;
	}
	int i = start;
	for (; i < end; ++i) {
		if (pre[root] == in[i]) {
			break;
		}
	}
	if (i != start) {
		inorder(root + 1, start, i - 1);
	}
	cout << pre[root] << ' ';
	if (i != end) {
		inorder(root + 1 + i - start, i + 1, end);
	}
	return;
}
int main() {
	cin >> n;
	pre.resize(n);
	in.resize(n);
	for (int i = 0; i < n; ++i) {
		cin >> pre[i];
	}
	for (int i = 0; i < n; ++i) {
		cin >> in[i];
	}
	cout << "postorder: ";
	postorder(0, 0, n - 1);
	cout << endl;
	cout << "preorder: ";
	preorder(0, 0, n - 1);
	cout << endl;
	cout << "inorder: ";
	inorder(0, 0, n - 1);
	cout << endl;
	return 0;
}

先序、中序、后序遍历的递归和非递归版本以及根据先序和中序构建二叉树

以下代码为先序、中序、后序遍历的递归和非递归版本,以及根据先序遍历和中序遍历构建二叉树

这里的构建注意要将原来的遍历改为hash表查找,否则会超时,具体就是一开始就建立hash表用以映射中序序列中的每个顶点的位置

后序 + 中序建立树:
后序:左右中
中序:左中右

建立中序序列键值对hash,从后面开始遍历后序序列,这样遍历得到的是右子树的根节点-》左子树的根节点

所以建立树的时候先建立右子树再建立左子树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
//post_idx表示后序中的遍历下标
    int post_idx;
    //hash记录中序的hash
    unordered_map<int, int> hash;
    TreeNode* build(int in_left, int in_right, vector<int>& inorder, vector<int>& postorder){
    //in_left是中序中左右子树的开始下标
    //in_right是中序中左右子树的结束下标
        if(in_left > in_right){
            return nullptr;
        }
        //root_val表示当前节点的值
        int root_val = postorder[post_idx];
        TreeNode* root = new TreeNode(root_val);
//index表示该节点所在中序序列的位置		
        int index = hash[root->val];
//post_idx--的原因是下一次的节点所在后序序列的下标
        post_idx--;
//index + 1到in_right为中序序列中右子树的区间
        root->right = build(index + 1, in_right, inorder, postorder);
//in_left到index - 1为中序序列中左子树的区间
        root->left = build(in_left, index - 1, inorder, postorder);

        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
//后序序列开始的下标为最后一个值
        post_idx = postorder.size() - 1;
        for(int i = 0;i < inorder.size();++i){
            hash[inorder[i]] = i; 
        }
        return build(0, postorder.size() - 1, inorder, postorder);
    }
};

//先序和中序建立
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int pre_idx;
    unordered_map<int, int> hash;
    TreeNode* build(int in_left, int in_right, vector<int>& preorder, vector<int>& inorder){
        if(in_left > in_right){
            return nullptr;
        }

        int root_val = preorder[pre_idx];
        TreeNode* root = new TreeNode(root_val);

        pre_idx++;
        int index = hash[root_val];

        root->left = build(in_left, index - 1, preorder, inorder);
        root->right = build(index + 1, in_right, preorder, inorder);

        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        pre_idx = 0;
        for(int i = 0;i < inorder.size();++i){
            hash[inorder[i]] = i;
        }
        return build(0, inorder.size() - 1, preorder, inorder);
    }
};
#include <iostream>
#include <vector>
#include <stack>
using namespace std;

#define maxsize 1000
int n;
vector<int> pre;
vector<int> in;
int loc = 0;

struct node {
	int data;
	node* lchild;
	node* rchild;
}tree[maxsize];

node* creat() {
	tree[loc].lchild = tree[loc].rchild = nullptr;
	return &tree[loc++];
}

node* build(int s1, int e1, int s2, int e2) {
	node* root = creat();
	root->data = pre[s1];
	int rootidx;
	for (int i = s2; i <= e2; ++i) {
		if (in[i] == pre[s1]) {
			rootidx = i;
			break;
		}
	}
	//exist left
	if (rootidx != s2) {
		root->lchild = build(s1 + 1,s1 + rootidx - s2,s2, rootidx - 1);
	}
	//exist right
	if (rootidx != e2) {
		root->rchild = build(s1 + rootidx - s2 + 1,e1,rootidx + 1,e2);
	}
	return root;
}

void preorder(node* root) {
	if (root == nullptr) {
		return;
	}
	cout << root->data << ' ';
	preorder(root->lchild);
	preorder(root->rchild);
	return;
}

void preorder_nonrecursive(node* root) {
	if (root != nullptr) {
		stack<node*> s;
		s.push(root);
		while (!s.empty()) {
			node* temp = s.top();
			s.pop();
			cout << temp->data << ' ';
			if (temp->rchild != nullptr) {
				s.push(temp->rchild);
			}
			if (temp->lchild != nullptr) {
				s.push(temp->lchild);
			}
		}
	}
	return;
}

void inorder(node* root) {
	if (root == nullptr) {
		return;
	}
	inorder(root->lchild);
	cout << root->data << ' ';
	inorder(root->rchild);
	return;
}

void inorder_nonrecursive(node* root) {
	if (root != nullptr) {
		stack<node*> s;
		node* temp = root;
		while (temp != nullptr || !s.empty()) {
			while (temp != nullptr) {
				s.push(temp);
				temp = temp->lchild;
			}
			if (!s.empty()) {
				temp = s.top();
				s.pop();
				cout << temp->data << ' ';
				temp = temp->rchild;
			}
		}
	}
	return;
}

void postorder(node* root) {
	if (root == nullptr) {
		return;
	}
	postorder(root->lchild);
	postorder(root->rchild);
	cout << root->data << ' ';
	return;
}

void postorder_nonrecursive(node* root) {
	if (root != nullptr) {
		stack<node*> stack1;
		stack<node*> stack2;
		stack1.push(root);
		while (!stack1.empty()) {
			node* temp = stack1.top();
			stack1.pop();
			stack2.push(temp);
			if (temp->lchild != nullptr) {
				stack1.push(temp->lchild);
			}
			if (temp->rchild != nullptr) {
				stack1.push(temp->rchild);
			}
		}
		while (!stack2.empty()) {
			node* temp = stack2.top();
			stack2.pop();
			cout << temp->data << ' ';
		}
	}
	return;
}

int main() {
	cin >> n;
	pre.resize(n);
	in.resize(n);
	for (int i = 0; i < n; ++i) {
		cin >> pre[i];
	}
	for (int i = 0; i < n; ++i) {
		cin >> in[i];
	}
	node* root = build(0, n - 1, 0, n - 1);
	
	cout << "postorder: ";
	postorder(root);
	cout << endl;
	cout << "postorder_nonrecursive: ";
	postorder_nonrecursive(root);
	cout << endl;
	
	cout << "preorder: ";
	preorder(root);
	cout << endl;
	cout << "preorder_nonrecursive: ";
	preorder_nonrecursive(root);
	cout << endl;

	cout << "inorder: ";
	inorder(root);
	cout << endl;
	cout << "inorder_nonrecursive: ";
	inorder_nonrecursive(root);
	cout << endl;
	return 0;
}

层次遍历 + 中序遍历 = 构建树

根据层次遍历和中序遍历构建树可以参考这篇博客https://blog.csdn.net/weixin_42299851/article/details/108423500

流程:
1、层次遍历第一个值为整棵树的根节点
2、在中序遍历中找出根节点所在位置,因此得到左子树和右子树
3、根据左子树的数字和右子树的数字在层次遍历中寻找对应数字的序列,将层次遍历中得到的左子树序列存入left_tree,将层次遍历中得到的右子树序列存入right_tree
4、进行递归,树的根节点的左子树和右子树进行递归,参数是left_tree和中序遍历中对应的左子树区间,和right和中序遍历中对应的右子树区间

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

#define maxsize 1000
int n;
vector<int> level;
vector<int> in;
int loc = 0;

struct node {
	int data;
	node* lchild;
	node* rchild;
}tree[maxsize];

node* creat() {
	tree[loc].lchild = tree[loc].rchild = nullptr;
	return &tree[loc++];
}

node* build(vector<int> lev, int s2, int e2) {
	if (lev.empty()) {
		return nullptr;
	}
	node* root = creat();
	root->data = lev[0];
	int rootidx;
	for (int i = s2; i <= e2; ++i) {
		if (in[i] == lev[0]) {
			rootidx = i;
			break;
		}
	}
	vector<int> left_tree;
	vector<int> right_tree;
	if (rootidx != s2) {
		for (int i = 1; i < lev.size(); ++i) {
			for (int j = s2; j < rootidx; ++j) {
				if (lev[i] == in[j]) {
					left_tree.push_back(lev[i]);
				}
			}
		}
	}
	if (rootidx != e2) {
		for (int i = 1; i < lev.size(); ++i) {
			for (int j = rootidx + 1; j <= e2; ++j) {
				if (lev[i] == in[j]) {
					right_tree.push_back(lev[i]);
				}
			}
		}
	}
	root->lchild = build(left_tree, s2, rootidx - 1);
	root->rchild = build(right_tree, rootidx + 1, e2);
	return root;
}

void preorder(node* root) {
	if (root == nullptr) {
		return;
	}
	cout << root->data << ' ';
	preorder(root->lchild);
	preorder(root->rchild);
	return;
}

void preorder_nonrecursive(node* root) {
	if (root != nullptr) {
		stack<node*> s;
		s.push(root);
		while (!s.empty()) {
			node* temp = s.top();
			s.pop();
			cout << temp->data << ' ';
			if (temp->rchild != nullptr) {
				s.push(temp->rchild);
			}
			if (temp->lchild != nullptr) {
				s.push(temp->lchild);
			}
		}
	}
	return;
}

void inorder(node* root) {
	if (root == nullptr) {
		return;
	}
	inorder(root->lchild);
	cout << root->data << ' ';
	inorder(root->rchild);
	return;
}

void inorder_nonrecursive(node* root) {
	if (root != nullptr) {
		stack<node*> s;
		node* temp = root;
		while (temp != nullptr || !s.empty()) {
			while (temp != nullptr) {
				s.push(temp);
				temp = temp->lchild;
			}
			if (!s.empty()) {
				temp = s.top();
				s.pop();
				cout << temp->data << ' ';
				temp = temp->rchild;
			}
		}
	}
	return;
}

void postorder(node* root) {
	if (root == nullptr) {
		return;
	}
	postorder(root->lchild);
	postorder(root->rchild);
	cout << root->data << ' ';
	return;
}

void postorder_nonrecursive(node* root) {
	if (root != nullptr) {
		stack<node*> stack1;
		stack<node*> stack2;
		stack1.push(root);
		while (!stack1.empty()) {
			node* temp = stack1.top();
			stack1.pop();
			stack2.push(temp);
			if (temp->lchild != nullptr) {
				stack1.push(temp->lchild);
			}
			if (temp->rchild != nullptr) {
				stack1.push(temp->rchild);
			}
		}
		while (!stack2.empty()) {
			node* temp = stack2.top();
			stack2.pop();
			cout << temp->data << ' ';
		}
	}
	return;
}

int main() {
	cin >> n;
	level.resize(n);
	in.resize(n);
	for (int i = 0; i < n; ++i) {
		cin >> level[i];
	}
	for (int i = 0; i < n; ++i) {
		cin >> in[i];
	}
	node* root = build(level, 0, n - 1);
	
	cout << "postorder: ";
	postorder(root);
	cout << endl;
	cout << "postorder_nonrecursive: ";
	postorder_nonrecursive(root);
	cout << endl;
	
	cout << "preorder: ";
	preorder(root);
	cout << endl;
	cout << "preorder_nonrecursive: ";
	preorder_nonrecursive(root);
	cout << endl;

	cout << "inorder: ";
	inorder(root);
	cout << endl;
	cout << "inorder_nonrecursive: ";
	inorder_nonrecursive(root);
	cout << endl;
	return 0;
}

先序遍历和后序遍历求中序遍历

PAT甲级1119 Pre- and Post-order Traversals
这种方法求得的二叉树不一定唯一
判断方法:当左子树的元素个数为奇数时唯一,偶数不唯一
流程:
1、先序中的第一个元素是树的根节点,也是后序的最后一个元素,所以先序中的第二个元素就是左子树树根
2、按照左子树树根找到在后序中的位置rootidx
3、此时后序中s2到rootidx为左子树,rootidx + 1到e2 - 1为右子树,先序中s1 + 1到s1 + 1 + rootidx - s2为左子树,s1 + 2 + rootidx - s2到e1为右子树
4、按照中序进行递归

hash版本:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    unordered_map<int, int> posthash;
    TreeNode* build(int preleft, int preright, int postleft, int postright, vector<int>& preorder, vector<int>& postorder){
        if(preleft > preright||postleft > postright)return nullptr;

        int root_val = preorder[preleft];
        TreeNode* root = new TreeNode(root_val);

        if(preleft == preright){
            root->left = nullptr;
            root->right = nullptr;
            return root;
        }

        int left_root_val = preorder[preleft + 1];
        int left_root_posi_in_post = posthash[left_root_val];

        root->left = build(preleft + 1, left_root_posi_in_post - postleft + 1 + preleft, postleft, left_root_posi_in_post, preorder, postorder);
        root->right = build(left_root_posi_in_post - postleft + 2 + preleft, preright, left_root_posi_in_post + 1, postright - 1, preorder, postorder);
        return root;

    }
    TreeNode* constructFromPrePost(vector<int>& preorder, vector<int>& postorder) {
        for(int i = 0;i < preorder.size();++i){
            posthash[postorder[i]] = i;
        }
        return build(0, preorder.size() - 1, 0, postorder.size() - 1, preorder, postorder);
    }
};
#include <iostream>
#include <vector>
using namespace std;
struct node {
    int data;
    node* lchild;
    node* rchild;
}tree[50];
vector<int> pre;
vector<int> post;
int n;
int loc = 0;
node* creat() {
    tree[loc].lchild = tree[loc].rchild = nullptr;
    return &tree[loc++];
}

bool flag = true;
node* build(int s1, int e1, int s2, int e2) {
    if (s1 > e1 || s2 > e2) {
        return nullptr;
    }
    node* root = creat();
    root->data = pre[s1];
    if (s1== e1) {
        return root;
    }
    else {
        int temp = pre[s1 + 1];
        int left_root;
        for (int i = s2; i <= e2; ++i) {
            if (temp == post[i]) {
                left_root = i;
                break;
            }
        }
        if ((left_root - s2 + 1) % 2 == 0 || (e2 - 1 - left_root) % 2 == 0) {
            flag = false;
        }
        root->lchild = build(s1 + 1, s1 + left_root - s2 + 1, s2, left_root);
        root->rchild = build(s1 + left_root - s2 + 2, e1, left_root + 1, e2 - 1);
        return root;
    }
}
bool out_flag = false;
void inorder(node* root) {
    if (root->lchild != nullptr) {
        inorder(root->lchild);
    }
    if (out_flag == false) {
        cout << root->data;
        out_flag = true;
    }
    else {
        cout << ' ' << root->data;
    }
    if (root->rchild != nullptr) {
        inorder(root->rchild);
    }
}
int main() {
    cin >> n;
    pre.resize(n);
    post.resize(n);
    for (int i = 0; i < n; ++i) {
        cin >> pre[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> post[i];
    }
    node* root = build(0, n - 1, 0, n - 1);
    if (flag == true) {
        cout << "Yes" << endl;
    }
    else {
        cout << "No" << endl;
    }
    inorder(root);
    cout << endl;
    return 0;
}
#include <iostream>
#include <vector>
using namespace std;
vector<int> pre;
vector<int> post;
vector<int> in;
int n;
bool unique = true;

void getin(int s1,int e1,int s2,int e2){
    if(s1 > e1||s2 > e2){
        return;
    }
    if(s1 == e1){
        in.push_back(pre[s1]);
        return;
    }
    int left_root = pre[s1 + 1];
    int rootidx;
    for(int i = s2;i <= e2;++i){
        if(post[i] == pre[s1 + 1]){
            rootidx = i;
            break;
        }
    }
    if((rootidx - s2 + 1) % 2 == 0||(e2 - rootidx - 1) % 2 == 0){
        unique = false;
    }
    getin(s1 + 1,rootidx - s2 + s1 + 1,s2,rootidx);
    in.push_back(pre[s1]);
    getin(rootidx - s2 + s1 + 2,e1,rootidx + 1,e2 - 1);
    return;
}

int main(){
    cin >> n;
    pre.resize(n);
    post.resize(n);
    for(int i = 0;i < n;++i){
        cin >> pre[i];
    }
    for(int i = 0;i < n;++i){
        cin >> post[i];
    }
    getin(0,n - 1,0,n - 1);
    if(unique == false){
        cout << "No" << endl;
    }
    else{
        cout << "Yes" << endl;
    }
    for(int i = 0;i < n;++i){
        if(i != 0){
            cout << ' ';
        }
        cout << in[i];
    }
    cout << endl;
    return 0;
}

如果还有缺漏的麻烦各位评论或私信我,谢谢

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值