二叉树专题

Complete Binary Search Tree (30)

Link
这道题相当于是已知完全二叉排序树的中序遍历,要输出其层序遍历。做法很巧妙,根本不用建树。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <cmath>
#include <unordered_set>
using namespace std;
int n,cur;
int a[1010],b[1010];
void levelTraverse(int r){
	if(r<=n){
		levelTraverse(r<<1);
		b[r]=a[++cur];
		levelTraverse((r<<1)+1);
	}
}
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	sort(a+1,a+1+n);
	levelTraverse(1);
	for(int i=1;i<n;++i)
		printf("%d ",b[i]);
	printf("%d\n",b[n]);
	return 0;
}

我在官方OJ上做的时候, 想出了一种很巧妙的非递归解法:
Link
思路是: 假设完全二叉树从根节点开始层次遍历的所有节点依次编号为 1~n, 那么我先用栈存储下中序遍历这棵树的编号顺序, 也就是代码中 cnt 的遍历顺序. 由于中序遍历得到的一定是原数组 a 的增序排列, 因此将中序遍历的编号顺序与增序排列的值一次关联, 最后将编号顺序从小到大排序——也就得到了层次遍历的顺序. 一次输出与其关联的值即可.

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <stack>
using namespace std;
int n;
int a[1010];
stack<int>st;
struct node{
	int index,val;
	bool operator<(node x)const{
		return index<x.index;
	}
}b[1010];
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	sort(a+1,a+1+n);
	int cnt=1,num=1;
	st.push(cnt);
	while(!st.empty()){
		cnt=st.top();
		if((cnt<<1)<=n)
			st.push(cnt<<1);
		else{
			st.pop();
			b[num]={cnt,a[num]};
			num++;
			while(!st.empty()){
				cnt=st.top();
				st.pop();
				b[num]={cnt,a[num]};
				num++;
				if((cnt<<1)+1<=n){
					st.push((cnt<<1)+1);
					break;
				}
			}
		}
	}
	sort(b+1,b+1+n);
	for(int i=1;i<n;++i)
		printf("%d ",b[i].val);
	printf("%d\n",b[n].val);
	return 0;
}

Root of AVL Tree (25)

Link
AVL模板题

借用网上的图在此解释一下4种旋转的情形:(左右图都是不平衡的AVL)

先左旋后右旋指的是先左旋左子树,后右旋根节点。实际上左子树是平衡的,但是左孩子(左子树的根节点)满足两边高度之差等于1,这就导致了根节点不平衡。如果左孩子的右子树高度比左子树高度大1,那么就要先左旋以左孩子为根节点的左子树(这就会让新的左孩子的左子树高度比右子树高度大1);如果左孩子的左子树高度比右子树高度大1,那么就不必进行任何操作。也就是说,这种情况下首先要让长度的不平衡集中到左孩子的左边,最后将根节点右旋即可。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <cmath>
using namespace std;
struct node{
	int val;
	struct node *left,*right;
};
//return root
//左旋的情况:根节点所在的树不平衡
node *rotateLeft(node *root){
	node *t=root->right;
	root->right=t->left;
	t->left=root;
	return t;
}
node *rotateRight(node *root){
	node *t=root->left;
	root->left=t->right;
	t->right=root;
	return t;
}
//先左旋后右旋的情况:先左旋左子树,后右旋根节点
//左子树平衡,但左子树的两边高度差是1,导致了根节点不平衡
node *rotateLeftRight(node *root){
	//先在左子树上完成左旋
	root->left=rotateLeft(root->left);
	//后右旋根节点
	return rotateRight(root);
}
node *rotateRightLeft(node *root){
	root->right=rotateRight(root->right);
	return rotateLeft(root);
}
int getHeight(node *root){
	if(root==NULL) return 0;
	return max(getHeight(root->left),getHeight(root->right))+1;
}
node *insert(node *root,int val){
	if(root==NULL){
		root=new node();
		root->val=val;
		root->left=root->right=NULL;
	}else if(val<root->val){
		root->left=insert(root->left,val);
		if(getHeight(root->left)-getHeight(root->right)==2)
			root=val<root->left->val?rotateRight(root):rotateLeftRight(root);
	}else{
		root->right=insert(root->right,val);
		if(getHeight(root->right)-getHeight(root->left)==2)
			root=val<root->right->val?rotateRightLeft(root):rotateLeft(root);
	}
	return root;
}
int main() {
	int n,val;
	scanf("%d",&n);
	node *root=NULL;
	for(int i=1;i<=n;++i){
		scanf("%d",&val);
		root=insert(root,val);
	}
	printf("%d\n",root->val);
	return 0;
}

Is It a Binary Search Tree (25)

Link
根据BST的前序遍历输出其后序遍历。不用建树。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
int n;
int a[1010];
bool isMirror=false;
bool isBST=true;
vector<int>ans;
void build(int l,int r){
	if(!isBST||l>r) return;
	int root=a[l];
	if(isMirror){
		int i=l+1;
		for(;i<=r;++i){
			if(a[i]<a[l])
				break;
		}
		for(int j=i;j<=r;++j){
			if(a[j]>=a[l]){
				isBST=false;
				break;
			}
		}
		build(l+1,i-1);
		build(i,r);
	}else{
		int i=l+1;
		for(;i<=r;++i){
			if(a[i]>=a[l])
				break;
		}
		for(int j=i;j<=r;++j){
			if(a[j]<a[l]){
				isBST=false;
				break;
			}
		}
		build(l+1,i-1);
		build(i,r);
	}
	ans.push_back(root);
}
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	if(n==1){
		printf("YES\n%d",a[0]);
		return 0;
	}
	if(n>1&&a[2]>=a[1]) isMirror=true;
	build(1,n);
	if(!isBST) printf("NO\n");
	else{
		printf("YES\n");
		printf("%d",ans[0]);
		for(int i=1;i<ans.size();++i)
			printf(" %d",ans[i]);
	}
	return 0;
}

第二次在官方OJ上做时提交的代码:
Link

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
int n;
int a[1010];
bool flag=true;
vector<int>ans;
void Traverse(int l,int r){
	if(l>r||r>n) return;
	int i=l+1;
	for(;i<=r;++i)
		if(a[i]>=a[l])
			break;
	for(int j=i+1;j<=r;++j)
		if(a[j]<a[l]){
			flag=false;
			break;
		}
	Traverse(l+1,i-1);
	Traverse(i,r);
	ans.push_back(a[l]);
}
void MirrorTraverse(int l,int r){
	if(l>r||r>n) return;
	int i=l+1;
	for(;i<=r;++i)
		if(a[i]<a[l])
			break;
	for(int j=i+1;j<=r;++j)
		if(a[j]>=a[l]){
			flag=false;
			break;
		}
	MirrorTraverse(l+1,i-1);
	MirrorTraverse(i,r);
	ans.push_back(a[l]);
}
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	if(n==1){
		printf("YES\n%d\n",a[1]);
		return 0;
	}
	if(a[2]<a[1]){
		Traverse(1,n);
	}else{
		MirrorTraverse(1,n);
	}
	if(!flag) printf("NO\n");
	else{
		printf("YES\n");
		for(int i=0;i<n-1;++i)
			printf("%d ",ans[i]);
		printf("%d\n",ans[n-1]);
	}
	return 0;
}

1086 Tree Traversals Again

Link

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <stack>
using namespace std;
int n,num;
char op[5];
vector<int>pre,in,post;
stack<int>st;
void Traverse(int l1,int r1,int l2,int r2){
	if(l1>r1||l2>r2) return;
	int root=pre[l1],pos=0;
	for(int i=l2;i<=r2;++i)
		if(in[i]==root){
			pos=i;
			break;
		}
	Traverse(l1+1,l1+pos-l2,l2,pos-1);
	Traverse(l1+pos-l2+1,r1,pos+1,r2);
	post.push_back(root);
}
int main() {
	scanf("%d",&n);
	for(int i=1;i<=(n<<1);++i){
		scanf("%s",op);
		if(op[1]=='u'){
			scanf("%d",&num);
			pre.push_back(num);
			st.push(num);
		}else{
			in.push_back(st.top());
			st.pop();
		}
	}
	Traverse(0,n-1,0,n-1);
	for(int i=0;i<n-1;++i)
		printf("%d ",post[i]);
	printf("%d\n",post[n-1]);
	return 0;
}
posted @ 2022-07-15 12:23  Ryomk  阅读(33)  评论(0编辑  收藏  举报