数据结构与算法(三)二叉树

本文介绍了如何使用堆结构实现增添和删除最小元素的操作,并探讨了二叉树的相关操作,包括节点交换、前驱询问、深度计算等。此外,还涉及序列求和、Huffman编码树构建、二叉搜索树、树的序列重建以及表达式树的求值等问题,深入讲解了二叉树在不同场景下的应用和解题策略。
摘要由CSDN通过智能技术生成

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值