数据结构之树的应用二

 

目录

7-1 二叉搜索树的结构

输入格式:

输出格式:

输入样例:

输出样例:

7-2 平衡二叉树的根

输入格式:

输出格式:

输入样例1:

输出样例1:

输入样例2:

输出样例2:

7-3 关于堆的判断

输入格式:

输出格式:

输入样例:

输出样例:

7-4 修理牧场

输入格式:

输出格式:

输入样例:

输出样例:


7-1 二叉搜索树的结构

分数 10

全屏浏览题目

切换布局

作者 陈越

单位 浙江大学

二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。(摘自百度百科)

给定一系列互不相等的整数,将它们顺次插入一棵初始为空的二叉搜索树,然后对结果树的结构进行描述。你需要能判断给定的描述是否正确。例如将{ 2 4 1 3 0 }插入后,得到一棵二叉搜索树,则陈述句如“2是树的根”、“1和4是兄弟结点”、“3和0在同一层上”(指自顶向下的深度相同)、“2是4的双亲结点”、“3是4的左孩子”都是正确的;而“4是2的左孩子”、“1和3是兄弟结点”都是不正确的。

输入格式:

输入在第一行给出一个正整数N(≤100),随后一行给出N个互不相同的整数,数字间以空格分隔,要求将之顺次插入一棵初始为空的二叉搜索树。之后给出一个正整数M(≤100),随后M行,每行给出一句待判断的陈述句。陈述句有以下6种:

  • A is the root,即"A是树的根";
  • A and B are siblings,即"AB是兄弟结点";
  • A is the parent of B,即"AB的双亲结点";
  • A is the left child of B,即"AB的左孩子";
  • A is the right child of B,即"AB的右孩子";
  • A and B are on the same level,即"AB在同一层上"。

题目保证所有给定的整数都在整型范围内。

输出格式:

对每句陈述,如果正确则输出Yes,否则输出No,每句占一行。

输入样例:

5
2 4 1 3 0
8
2 is the root
1 and 4 are siblings
3 and 0 are on the same level
2 is the parent of 4
3 is the left child of 4
1 is the right child of 2
4 and 0 are on the same level
100 is the right child of 3

输出样例:

Yes
Yes
Yes
Yes
Yes
No
No
No
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int flag=0;
typedef struct Node
{
    int val;
    struct Node *left,*right;
}Node,*ANode;


ANode p;


ANode insertNode(ANode root,int x)
{
    if(root==NULL)
    {
        root=(ANode)malloc(sizeof(Node));
        root->val=x;
        root->left=root->right=NULL;
    }
    else if(x<root->val)
        root->left=insertNode(root->left,x);
    else root->right=insertNode(root->right,x);
    return root;
}


ANode findNode(ANode root,int x)
{
    if(root!=NULL)
    {
        if(x<root->val)findNode(root->left,x);
        else if(x>root->val)findNode(root->right,x);
        else return root;
    }
}


int judgeLeft(ANode root,int x,int y)
{
    ANode t=findNode(root,x);
    if(t->left!=NULL &&y==t->left->val)return 1;
    else return 0;
}


int judgeRight(ANode root,int x,int y)
{
    ANode t=findNode(root,x);
    if(t->right!=NULL &&y==t->right->val)return 1;
    else return 0;
}


void judgeSibling(ANode root,int x,int y)
{
    if(root!=NULL && root->left!=NULL && root->right!=NULL)
    {
        if((root->left->val==x && root->right->val==y) ||
           (root->left->val==y && root->right->val==x))flag=1;
        judgeSibling(root->left,x,y);
        judgeSibling(root->right,x,y);
    }
}


int getlevel(ANode root,int x,int level)
{
    if(root!=NULL)
    {
        if(x<root->val)getlevel(root->left,x,level+1);
        else if(x>root->val)getlevel(root->right,x,level+1);
        else return level;
    }
}

int count(int a[],int b,int k){  //判断是不是有这个数 
	for(int i=0;i<k;i++){
		if(a[i]==b)
		return 1;//表示有 
	}
	return 0;
}


int main()
{
    ANode root=NULL;
    int n,m,a,b,x;
    int st[100];
    int k=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&x);
        st[k++]=x;
        root=insertNode(root,x);
    }
    char str[100];
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d",&a);
        scanf("%s",str);
        flag=0;
        if(str[0]=='a'&&str[1]=='n'&&str[2]=='d')
        {
            scanf("%d",&b);
            gets(str);
            if(str[strlen(str)-1]=='s')//兄弟节点
            {
                if(count(st,a,k)==1&&count(st,b,k)==1)
                {
                    judgeSibling(root,a,b);
                    if(flag)
					printf("Yes\n");
                    else printf("No\n");
                }
                else printf("No\n");
            }
            else//在同一层
            {
                if(count(st,a,k)==1&&count(st,b,k)==1)
                {
                    if(getlevel(root,a,1)==getlevel(root,b,1))
					printf("Yes\n");
                    else printf("No\n");
                }
                else printf("No\n");
            }
        }
        else
        {
            scanf("%s",str);
            scanf("%s",str);
            if(str[0]=='r'&&str[1]=='o'&&str[2]=='o'&&str[3]=='t')
            {
                if(count(st,a,k)==1&&root->val==a)
				printf("Yes\n");
                else printf("No\n");
            }
            else if(str[0]=='p'&&str[1]=='a'&&str[2]=='r'&&str[3]=='e'&&str[4]=='n'&&str[5]=='t')
            {
                scanf("%s",str);
                scanf("%d",&b);
                if(count(st,a,k)==1&&count(st,b,k)==1)
                {
                    if(judgeLeft(root,a,b) || judgeRight(root,a,b))
					printf("Yes\n");
                    else printf("No\n");
                }
                else printf("No\n");
            }
            else if(str[0]=='l'&&str[1]=='e'&&str[2]=='f'&&str[3]=='t')
            {
                scanf("%s",str);
                scanf("%s",str);
                scanf("%d",&b);
                if(count(st,a,k)==1&&count(st,b,k)==1)
                {
                    if(judgeLeft(root,b,a))printf("Yes\n");
                    else printf("No\n");
                }
                else printf("No\n");
            }
            else
            {
                scanf("%s",str);
                scanf("%s",str);
                scanf("%d",&b);
                if(count(st,a,k)==1&&count(st,b,k)==1)
                {
                    if(judgeRight(root,b,a))
					printf("Yes\n");
                    else printf("No\n");
                }
                else printf("No\n");
            }
        }
    }
 
}

 网上很多都是c++写的,c语言确实不好写尤其是输入的地方需要额外注意一下

 

7-2 平衡二叉树的根

分数 10

全屏浏览题目

切换布局

作者 DS课程组

单位 浙江大学

将给定的一系列数字插入初始为空的AVL树,请你输出最后生成的AVL树的根结点的值。

输入格式:

输入的第一行给出一个正整数N(≤20),随后一行给出N个不同的整数,其间以空格分隔。

输出格式:

在一行中输出顺序插入上述整数到一棵初始为空的AVL树后,该树的根结点的值。

输入样例1:

5
88 70 61 96 120

输出样例1:

70

输入样例2:

7
88 70 61 96 120 90 65

输出样例2:

88
#include <stdio.h>
#include<stdlib.h>
typedef struct node *AVLTree;
struct node{
    int Data;
    AVLTree Left;
    AVLTree Right;
};

int High(AVLTree T){
    if(!T)
        return 0;
    int left=High(T->Left)+1;
    int right=High(T->Right)+1;
    return left>right?left:right;
}

AVLTree LL(AVLTree T){
    AVLTree T1;
    T1=T->Right;
    T->Right=T1->Left;
    T1->Left=T;
    return T1;
}

AVLTree RR(AVLTree T){
    AVLTree T1;
    T1=T->Left;
    T->Left=T1->Right;
    T1->Right=T;
    return T1;
}

AVLTree LR(AVLTree T){
    AVLTree T1,T2;
    T1=T->Left;
    T2=T1->Right;
    T->Left=NULL;
    T2->Right=T;
    T1->Right=NULL;
    T2->Left=T1;
    return T2;
}

AVLTree RL(AVLTree T){
    AVLTree T1,T2;
    T1=T->Right;
    T2=T1->Left;
    T->Right=NULL;
    T2->Left=T;
    T1->Left=NULL;
    T2->Right=T1;
    return T2;
}

AVLTree Insert(AVLTree T,int x){
    if(!T){
        AVLTree T =(AVLTree)malloc(sizeof(struct node));
        T->Data=x;
        T->Left=T->Right=NULL;
        return T;
    }else if(x>T->Data){
        T->Right=Insert(T->Right,x);
        if((High(T->Right)-High(T->Left))>=2){
            if(x>T->Right->Data)
                T=LL(T);
            else
                T=RL(T);
        }
    }else if(x<T->Data){
        T->Left=Insert(T->Left,x);
        if((High(T->Left)-High(T->Right))==2){
            if(x<T->Left->Data)
                T=RR(T);
            else
                T=LR(T);
        }
    }
    return T;
}
int main() { 
    int n,x;
    AVLTree T=NULL;
    scanf("%d",&n);
    for (int i = 0; i < n; i++) {
        scanf("%d",&x);
        T=Insert(T,x);
    }
    printf("%d\n",T->Data);
    return 0;
}

 

7-3 关于堆的判断

分数 10

全屏浏览题目

切换布局

作者 陈越

单位 浙江大学

将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种:

  • x is the rootx是根结点;
  • x and y are siblingsxy是兄弟结点;
  • x is the parent of yxy的父结点;
  • x is a child of yxy的一个子结点。

输入格式:

每组测试第1行包含2个正整数N(≤ 1000)和M(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[−10000,10000]内的N个要被插入一个初始为空的小顶堆的整数。之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。

输出格式:

对输入的每个命题,如果其为真,则在一行中输出T,否则输出F

输入样例:

5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10

输出样例:

F
T
F
T
#include<stdio.h>
void swap(int a[],int i,int k){
    int t=a[i];
    a[i]=a[k];
    a[k]=t;
}
void stack(int a[],int s){
    for(int i=s/2;i>0;s=i,i/=2)
        if(a[s]<a[i])
            swap(a,s,i);
}
int find(int a[],int n,int m){
    for(int l=1;l<=n;l++)
        if(a[l]==m) return l;
    return 0;
}
int main(){
    int n,m,i,p,q;
    scanf("%d %d",&n,&m);
    int a[n+1];
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
        stack(a,i);
    }getchar();
    while(m--){
        char g[10],h[10],str[10];
        scanf("%d %s %s %s",&p,g,h,str);
        if(str[0]=='r'){
            if(a[1]!=p) printf("F\n");
            else printf("T\n");
        }else if(str[0]=='a'){
            scanf("%s",g);
            sscanf(h,"%d",&q);
            if(find(a,n,p)/2==find(a,n,q)/2)
                printf("T\n");
            else printf("F\n");
        }else if(str[0]=='p'){
            scanf("%s %d",g,&q);
            if(find(a,n,p)==find(a,n,q)/2)
                printf("T\n");
            else printf("F\n");
        }else if(str[0]=='c'){
            scanf("%s %d",g,&q);
            if(find(a,n,p)/2==find(a,n,q))
                printf("T\n");
            else printf("F\n");
        }
    }
    return 0;
}

 这道题跟第一道题大同小异,知识点不难,恶心的还是输入问题(但是这题要稍微简单一点)。如果有同学按照书上的方法建立堆可能是会有部分错误,原因是堆不符合题目的要求。

一下代码是第一次写的结果,发现第1个测试点无法通过,想了很久可能是堆不符合要求,如果有大佬能够改进望告知,万分感谢!!!

#include<stdio.h>
#include<stdlib.h>
int max=10000;
typedef struct HNode* Heap;
struct HNode{
    int* Date;//数组
    int size;//当前堆的元素个数
};

Heap creat(){  //说白了就是初始化
    Heap h=(Heap)malloc(sizeof(struct HNode));
    h->Date=(int*)malloc(sizeof(int)*(max+1));
    h->size=0;
    h->Date[0]=-99999;//哨兵元素,小于所有数字
    return h;
}

int find(Heap h,int x){  //返回x在数组中的下表
    for(int i=1;i<=h->size;i++){
        if(h->Date[i]==x)
            return i;
    }
    return -1;//没有
}

int isfull(Heap h){
    if(h->size==max)
        return 0;
    return 1;
}

int insert(Heap h,int x){
    int i;
    if(isfull(h)==0)
        return 0;

    i=++h->size;
    while(h->Date[i/2]>x){
        h->Date[i]=h->Date[i/2];
        i=i/2;
    }
    h->Date[i]=x;
    return 1;
}

int fa1(Heap h,int x){
    if(h->Date[1]==x)
        return 1;
    return 0;
}

int fa2(Heap h,int x,int y){
    if(find(h,x)+1==find(h,y)||find(h,y)+1==find(h,x))
        return 1;
    return 0;
}

int fa3(Heap h,int x,int y){
    if(find(h,y)/2==find(h,x))
        return 1;
    return 0;
}

int fa4(Heap h,int x,int y){
    if(find(h,x)/2==find(h,y))
        return 1;
    return 0;
}

int main(){
    int n1;
    int n2;
    scanf("%d %d",&n1,&n2);
    Heap h=creat();
    int t;
    for(int i=0;i<n1;i++){
        scanf("%d",&t);
        insert(h,t);
    }
    char str[100];
    int t1;
    int t2;
    for(int i=0;i<n2;i++){
        scanf("%d",&t1);
        scanf("%s",str);
        if(str[0]=='a'){
            scanf("%d",&t2);
            gets(str);//把后面的读取玩
            if(fa2(h,t1,t2)==1)
            printf("T\n");
            else
            printf("F\n");
        }
        else{
            scanf("%s",str);
            scanf("%s",str);
            if(str[0]=='r'){
                if(fa1(h,t1)==1)
                   printf("T\n");
                   else
                 printf("F\n"); 
            }
            else if(str[0]=='p'){
                scanf("%s",str);
                scanf("%d",&t2);
                if(fa3(h,t1,t2)==1)
                   printf("T\n");
                   else
                 printf("F\n"); 
            }
            else if(str[0]=='c'){
                 scanf("%s",str);
                scanf("%d",&t2);
                if(fa4(h,t1,t2)==1)
                   printf("T\n");
                   else
                 printf("F\n"); 
            }
        }
    }
}

 

7-4 修理牧场

分数 10

全屏浏览题目

切换布局

作者 DS课程组

单位 浙江大学

农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li​个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li​的总和。

但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。

请编写程序帮助农夫计算将木头锯成N块的最少花费。

输入格式:

输入首先给出正整数N(≤104),表示要将木头锯成N块。第二行给出N个正整数(≤50),表示每段木块的长度。

输出格式:

输出一个整数,即将木头锯成N块的最少花费。

输入样例:

8
4 5 1 2 1 3 1 1

输出样例:

49
#include <stdio.h>
#include <stdlib.h>
 
//哈夫曼树的存储表示
typedef struct
{
    int weight; //
    int parent, lchild,rchild;
}HTNode, *HuffmanTree;
 
//查找最小的两个根节点 
void Select(HuffmanTree HT, int len, int *s1, int *s2)
//这里解释一下为什么要传入两个指针,因为一个函数不好直接有两个返回值,因此采用指针的方式直接修改地址上的值 
{
    int i, min1 = 999999, min2 = min1;
    for(i=1; i<=len; i++)
    {
        //HT[i].parent == 0说明还未被安排,是根节点
        if(HT[i].parent==0)
        {
            if(HT[i].weight<min1)
            {
                min2=min1;
                *s2=*s1;
                min1=HT[i].weight;
                *s1=i;
            }
            else if(HT[i].weight<min2)
            {
                min2=HT[i].weight;
                *s2=i;
            }
        }
    }
}
 
 //创建 
int CreateHuffmanTree(HuffmanTree HT, int n)
{
    if(n<=1) 
    return 0;
    int i;
    int sum=0;
    int m = 2*n-1;
    //开辟所需要的结点
    HT = (HuffmanTree)malloc(sizeof(HTNode)*(m+1));
    //将1~m号单元中的双亲,左孩子,右孩子全初始化为零
    for(i = 1; i<=m; i++)
    {
        HT[i].parent = 0;
        HT[i].lchild = 0;
        HT[i].rchild = 0;
    }
    for(i = 1; i <=n; i++)
    {
        scanf("%d",&HT[i].weight);
    }
    //初始化结束,开始创建哈夫曼树
    //通过n-1次的选择、删除、合并来创建哈夫曼树
    for(i = n+1; i <= m; i++)
    {
        int s1,s2;
        Select(HT, i-1, &s1, &s2);
        HT[s1].parent = i;
        HT[s2].parent = i;
 
        HT[i].lchild = s1;
        HT[i].rchild = s2;
        //新结点未被合并过,所以parent要赋值为0
        HT[i].parent = 0;
 
        HT[i].weight = HT[s1].weight + HT[s2].weight;
        //每次都将合并的权值加到sum里
        sum += HT[i].weight;
    }
    return sum;
}
 
 
 
int main()
{
    HuffmanTree HT;
    int n;
    scanf("%d",&n);
    int sum = 0;
    sum=CreateHuffmanTree(HT,n);
    printf("%d", sum);
}

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值