1.实现堆结构
描述
定义一个数组,初始化为空。在数组上执行两种操作:
1、增添1个元素,把1个新的元素放入数组。
2、输出并删除数组中最小的数。
使用堆结构实现上述功能的高效算法。
输入
第一行输入一个整数t,代表测试数据的组数。
对于每组测试数据,第一行输入一个整数n,代表操作的次数。
每次操作首先输入一个整数type。
当type=1,增添操作,接着输入一个整数u,代表要插入的元素。
当type=2,输出删除操作,输出并删除数组中最小的元素。
1<=n<=100000。
输出
每次删除操作输出被删除的数字。
样例输入
2
5
1 1
1 2
1 3
2
2
4
1 5
1 1
1 7
2
样例输出
1
2
1
提示
每组测试数据的复杂度为O(nlgn)的算法才能通过本次,否则会返回TLE(超时)
需要使用最小堆结构来实现本题的算法
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<string>
#include<string.h>
#include<queue>
#include<stack>
#define REP(i,a,b) for(int i=(a);i<=(b);++i)
#define PER(i,a,b) for(int i=(a);i>=(b);--i)
#define mk(a,b) make_pair(a,b)
using namespace std;
int heap[100010];
int Num=0;
void shiftup(int pos){
if(pos==0)return;
if((pos-1)/2>=0&&heap[pos]<heap[(pos-1)/2]){
swap(heap[pos],heap[(pos-1)/2]);shiftup((pos-1)/2);
}
}
void shiftdown(int pos){
if(pos*2+2<Num){
if(heap[pos*2+1]<=heap[pos*2+2]&&heap[pos]>=heap[pos*2+1]){
swap(heap[pos],heap[pos*2+1]);shiftdown(pos*2+1);
}
else if(heap[pos*2+1]>=heap[pos*2+2]&&heap[pos]>=heap[pos*2+2]){
swap(heap[pos],heap[pos*2+2]);shiftdown(pos*2+2);
}
}
else if(pos*2+1<Num){
if(heap[pos]>heap[pos*2+1]){
swap(heap[pos],heap[pos*2+1]);shiftdown(pos*2+1);
}
}
}
int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
Num=0;//memset(heap,0,sizeof(heap));
while(n--){
//REP(i,0,Num-1)cout<<heap[i]<<' ';cout<<endl;
int op;cin>>op;
if(op==1){
int num;cin>>num;//cout<<"num="<<num<<endl;
heap[Num]=num;Num++;
shiftup(Num-1);
}
else {
printf("%d\n",heap[0]);
heap[0]=heap[Num-1];Num--;
shiftdown(0);
}
}
}
return 0;
}
2.二叉树的操作
描述
给定一棵二叉树,在二叉树上执行两个操作:
1. 节点交换
把二叉树的两个节点交换。
2. 前驱询问
询问二叉树的一个节点对应的子树最左边的节点。
输入
第一行输出一个整数t(t <= 100),代表测试数据的组数。
对于每组测试数据,第一行输入两个整数n m,n代表二叉树节点的个数,m代表操作的次数。
随后输入n行,每行包含3个整数X Y Z,对应二叉树一个节点的信息。X表示节点的标识,Y表示其左孩子的标识,Z表示其右孩子的标识。
再输入m行,每行对应一次操作。每次操作首先输入一个整数type。
当type=1,节点交换操作,后面跟着输入两个整数x y,表示将标识为x的节点与标识为y的节点交换。输入保证对应的节点不是祖先关系。
当type=2,前驱询问操作,后面跟着输入一个整数x,表示询问标识为x的节点对应子树最左的孩子。
1<=n<=100,节点的标识从0到n-1,根节点始终是0.
m<=100
输出
对于每次询问操作,输出相应的结果。
样例输入
2
5 5
0 1 2
1 -1 -1
2 3 4
3 -1 -1
4 -1 -1
2 0
1 1 2
2 0
1 3 4
2 2
3 2
0 1 2
1 -1 -1
2 -1 -1
1 1 2
2 0
样例输出
1
3
4
2
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<string>
#include<string.h>
#include<queue>
#include<stack>
#define REP(i,a,b) for(int i=(a);i<=(b);++i)
#define PER(i,a,b) for(int i=(a);i>=(b);--i)
#define mk(a,b) make_pair(a,b)
using namespace std;
int leftchild[110];
int rightchild[110];
int parent[110];
int main(){
int t;cin>>t;
while(t--){
int n,m;cin>>n>>m;
while(n--){
int x,y,z;cin>>x>>y>>z;
leftchild[x]=y;rightchild[x]=z;
if(y!=-1)parent[y]=x;
if(z!=-1)parent[z]=x;
}
while(m--){
int type;cin>>type;
if(type==1){
int x,y;cin>>x>>y;
int px,py;px=parent[x];py=parent[y];
parent[x]=py;parent[y]=px;
if(px!=py){
if(leftchild[px]==x)leftchild[px]=y;
else if(rightchild[px]==x)rightchild[px]=y;
if(leftchild[py]==y)leftchild[py]=x;
else if(rightchild[py]==y)rightchild[py]=x;
}
else {
if(leftchild[px]==x){
leftchild[px]=y;rightchild[px]=x;
}
else{
leftchild[px]=x;rightchild[px]=y;
}
}
}
else if(type==2){
int nod;cin>>nod;
while(leftchild[nod]>0){
nod=leftchild[nod];
}
cout<<nod<<endl;
}
}
}
return 0;
}
3.二叉树的深度
描述
给定一棵二叉树,求该二叉树的深度
二叉树深度定义:从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的节点个数为树的深度
输入
第一行是一个整数n,表示二叉树的结点个数。二叉树结点编号从1到n,根结点为1,n <= 10
接下来有n行,依次对应二叉树的n个节点。
每行有两个整数,分别表示该节点的左儿子和右儿子的节点编号。如果第一个(第二个)数为-1则表示没有左(右)儿子
输出
输出一个整型数,表示树的深度
样例输入
3
2 3
-1 -1
-1 -1