目录
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
,即"A
和B
是兄弟结点";A is the parent of B
,即"A
是B
的双亲结点";A is the left child of B
,即"A
是B
的左孩子";A is the right child of B
,即"A
是B
的右孩子";A and B are on the same level
,即"A
和B
在同一层上"。
题目保证所有给定的整数都在整型范围内。
输出格式:
对每句陈述,如果正确则输出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 root
:x
是根结点;x and y are siblings
:x
和y
是兄弟结点;x is the parent of y
:x
是y
的父结点;x is a child of y
:x
是y
的一个子结点。
输入格式:
每组测试第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);
}