首页 > 其他 > 详细

JLU数据结构第三次上机实验

时间:2021-06-01 23:55:54      阅读:32      评论:0      收藏:0      [点我收藏+]

JLU数据结构第三次上机实验

7-1 二叉树最长路径

代码长度限制 16 KB
时间限制 100 ms
内存限制 5 MB


题目描述

给定一棵二叉树T,求T中的最长路径的长度,并输出此路径上各结点的值。若有多条最长路径,输出最右侧的那条。

输入格式

第1行,1个整数n,表示二叉树有n个结点, 1≤n≤100000.

第2行,2n+1个整数,用空格分隔,表示T的扩展先根序列, -1表示空指针,结点用编号1到n表示。

输出格式

第1行,1个整数length,length表示T中的最长路径的长度。

第2行,length+1个整数,用空格分隔,表示最右侧的最长路径。

输入样例

在这里给出一组输入。例如:

5
1 2 -1 -1 3 4 -1 -1 5 -1 -1

输出样例

在这里给出一组输出。例如:

2
1 3 5

思路

方法一:不建树,用vector保存当前路径,并随数据输入不断更新,当长度足够大时保存为候选路径。此方法不稳定,频繁保存为候选路径非常耗时。

方法二:建树,加个父节点。记录当前路径长度,保存为候选路径时只需保存该路径的最终结点。当树建完,由保存的路径的最终结点开始,不断访问他的祖先,就能得到最长路径。

代码

#include<iostream>
#include<stack>
using namespace  std;
struct node{
    int right;
    int left;
    int father;
};
int pasw;
int nasw=-1;
int nasw0=-1;
node*a;
void build(int x){
    nasw0++;
    int s1;
    scanf("%d",&s1);
    if(s1!=-1){
        a[x].left=s1;
        a[s1].father=x;
        build(s1);
    }
    int s2;
    scanf("%d",&s2);
    if(s2!=-1){
        a[x].right=s2;
        a[s2].father=x;
        build(s2);
    }
    if(s1==-1&&s2==-1){
        if(nasw0>=nasw){
            pasw=x;
            nasw=nasw0;
        }
    }
    nasw0--;
    return ;
}
int main(){
    int N;
    scanf("%d ",&N);
    a=new node[N+1];

    int x;
    scanf("%d",&x);
    a[x].father=0;
    build(x);

    stack<int>r;
    for(int i=0;i<nasw+1;i++){
        r.push(pasw);
        pasw=a[pasw].father;
    }

    printf("%d\n",nasw);
    for(int i=0;i<nasw+1;i++){
        if(i!=0)printf(" ");
        printf("%d",r.top());
        r.pop();
    }
    return 0;
}

森林的层次遍历

代码长度限制 16 KB
时间限制 100 ms
内存限制 5 MB


题目描述

给定一个森林F,求F的层次遍历序列。森林由其先根序列及序列中每个结点的度给出。

输入格式

第1行,1个整数n,表示森林的结点个数, 1≤n≤100000.

第2行,n个字符,用空格分隔,表示森林F的先根序列。字符为大小写字母及数字。

第3行,n个整数,用空格分隔,表示森林F的先根序列中每个结点对应的度。

输出格式

1行,n个字符,用空格分隔,表示森林F的层次遍历序列。

输入样例

在这里给出一组输入。例如:

14
A B C D E F G H I J K L M N
4 0 3 0 0 0 0 2 2 0 0 0 1 0

输出样例

在这里给出相应的输出。例如:

A M B C G H N D E F I L J K

思路

森林引入总根可以看作树。各种方法的复杂度差不多。但树的储存方式决定代码是否好写。

我用的大儿子+下个兄弟的结构,发现不好写清楚。如果用邻接表的话会清晰很多。

代码

#include<iostream>
#include<stack>
#include<queue>
using namespace  std;
struct node{
    char c;
    int n;
    node*son;
    node*bro;
};
static node*a;

static queue<node>q;
static int begin=0;

int build(int k){//返回建好后下一个兄弟的下标
    int ks=0,kb=k+1;
    if(a[k].n==0)a[k].son=NULL;
    else{
        ks=k+1;
        a[k].son=&a[ks];
        kb=build(ks);
        for(int i=2;i<=a[k].n;i++){
            a[ks].bro=&a[kb];
            ks=kb;
            kb=build(ks);
        }
        a[ks].bro=NULL;
    }
    return kb;
}
void prt(){
    if(::begin)printf(" ");
    else ::begin=1;
    printf("%c",q.front().c);
    node*p=q.front().son;
    for(int i=0;i<q.front().n;i++){
            q.push(*p);
            p=p->bro;
    }
    q.pop();
    return;
}
int main(){
    int n=0;
    scanf("%d\n",&n);
    a=new node[n];
    for(int i=0;i<n;i++){
        scanf(" %c",&a[i].c);
    }
    for(int i=0;i<n;i++){
        scanf("%d",&a[i].n);
    }
    int nb1=0,nb2=0;
    while(nb2!=n){
        nb2=build(nb1);
        q.push(a[nb1]);
        nb1=nb2;
    }
   while(q.size()){
        prt();
    }
    return 0;
}

纸带切割

代码长度限制 16 KB
时间限制 100 ms
内存限制 5 MB


题目描述

有一条细长的纸带,长度为 L 个单位,宽度为一个单位。现在要将纸带切割成 n 段。每次切割把当前纸带分成两段,切割位置都在整数单位上,切割代价是当前切割纸带的总长度。每次切割都选择未达最终要求的最长纸带切割,若这样的纸带有多条,则任选一条切割。如何切割,才能完成任务,并且总代价最小。

输入格式

第1行,1个整数n,表示切割成的段数, 1≤n≤100000.

第2行,n个整数Li,用空格分隔,表示要切割成的各段的长度,1≤Li≤200000000,1≤i≤n.

输出格式

第1行,1个整数,表示最小的总代价。

第2行,若干个整数,用空格分隔,表示总代价最小时每次切割的代价。

输入样例

在这里给出一组输入。例如:

5
5 6 7 2 4

输出样例

在这里给出一组输出。例如:

54
24 13 11 6

思路

逆向思维,哈夫曼树。切割纸带就是拼接纸带,每次拼接的代价是拼接后的纸带长度。这样自然就想到哈夫曼树。每次取当前最短的两条纸带拼接,直到剩下一条纸带。逆序输出每次拼接后的长度就是切割过程。

代码

#include<iostream>
#include<stack>
#include<deque>
#include<algorithm>
using namespace std;
long long getm(deque<long long>&q1,deque<long long>&q2){
    long long a;
    if(q1.empty()){
        a=q2.front();
        q2.pop_front();
    }else if(q2.empty()){
        a=q1.front();
        q1.pop_front();
    }else{
        if(q1.front()>q2.front()){
            a=q2.front();
            q2.pop_front();
        }else{
            a=q1.front();
            q1.pop_front();
        }
    }
    return a;
}
int main(){
    int n;
    scanf("%d ",&n);
    stack<long long>asw;
    long long nasw=0;

    deque<long long>a;
    deque<long long>q;
    for(int i=0;i<n;i++){
        int x;
        scanf("%d",&x);
        a.push_back(x);
    }
    sort(a.begin(),a.end());

    for(int i=0;i<n-1;i++){
        long long n1;
        n1=getm(a,q);
        n1+=getm(a,q);

        asw.push(n1);
        nasw+=n1;
        q.push_back(n1);
    }
    printf("%lld\n",nasw);
    int begin=0;
    while(!asw.empty()){
        if(begin)printf(" ");
        else begin=1;
        printf("%lld",asw.top());
        asw.pop();
    }
    return 0;
}

序列乘积

代码长度限制 16 KB
时间限制 100 ms
内存限制 5 MB


题目描述

两个递增序列A和B,长度都是n。令 Ai 和 Bj 做乘积,1≤i,j≤n.请输出n*n个乘积中从小到大的前n个。

输入格式

第1行,1个整数n,表示序列的长度, 1≤n≤100000.

第2行,n个整数Ai,用空格分隔,表示序列A,1≤Ai≤40000,1≤i≤n.

第3行,n个整数Bi,用空格分隔,表示序列B,1≤Bi≤40000,1≤i≤n.

输出格式

1行,n个整数,用空格分隔,表示序列乘积中的从小到大前n个。

输入样例

在这里给出一组输入。例如:

5
1 3 5 7 9 
2 4 6 8 10

输出样例

在这里给出相应的输出。例如:

2 4 6 6 8

思路

把序列B当作数组,为B的每个元素匹配一个以序列A为元素的队列,并记录 Bi 与 Bi的队列的队首元素 的乘积Ni(下标 i 是索引),所有的Ni中最小的那个(设为Nk),就是当前的最小乘积。然后让Bk的队首出队,就能维护这个结构,让下一个产生的Nk最小。

证明:Ni是Bi与A中每个元素的乘积中最小的,而Nk又是所有Ni中最小的,所以Nk为当前所有乘积中最小的。

代码

下面的代码有个样例有段错误,但我一直没找到。

#include<iostream>
using namespace  std;
struct numb{
    int N=0;
    int ia=0;
    int Nab=0;
};
int main(){
    int n=0;
    scanf("%d ",&n);
    int a[n+1];
    a[n]=0;
    for(int i=0;i<n;i++)scanf("%d",&a[i]);
    numb b[n+1];
    for(int i=0;i<n;i++){
        scanf("%d",&b[i].N);
        b[i].Nab=b[i].N*a[0];
    }

    int begin=0;
    for(int i=0;i<n;i++){
        if(begin)printf(" ");
        else begin=1;
        printf("%d",b[0].Nab);
        if(b[0].ia!=n-1){
            b[0].ia++;
            b[0].Nab=b[0].N*a[b[0].ia];

            for(int j=0;j<n-1&&b[j].Nab>b[j+1].Nab;j++){
                numb buf=b[j];
                b[j]=b[j+1];
                b[j+1]=buf;
            }
        }
        /*for(int i=0;i<n;i++)printf("%d ",b[i].Nab);
        printf("\n");*/
    }
    return 0;
}

JLU数据结构第三次上机实验

原文:https://www.cnblogs.com/huangyxblog/p/14838768.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!