记住二叉树的概念并据此做题,兵来将挡,水来土掩
2-3.若二叉搜索树是有N个结点的完全二叉树,则不正确的说法是:
A.所有结点的平均查找效率是O(logN)
B.最小值一定在叶结点上
C.中位值结点在根结点或根的左子树上
D.最大值一定在叶结点上
解析来自某大佬
答案选D。可以辨析一下B C
D选项。首先我们从知道,比根节点大的放在右边,比根节点小的放在左边,那么有一种情况就是,比根节点大的放在左边,然后这个根节点又没有右孩子。如下图
很简单的例子,那么这棵树中最大值应该是9,而它不是叶子节点。
那么再看B选项,我们假设最小值不在叶节点,而同时我们不要忘了题目要求,是个完全二叉树,那么也就是说,整棵树的左下角,要么是从左到右有部分节点有孩子,要么都没有,那么根据假设条件,这个最小值不是叶节点,它必须有左孩子,那就说明它不是最小值,与假设相反。所以最小值一定在叶节点。
最后是C选项,依然是完全二叉树的问题,如果是一棵满二叉树,那么中位值肯定在根节点上,因为左右子树节点数相同。而如果右子树不满,那么左子树的节点数多,所以中位数自然在左子树里,很好想。
C选项左子树必须小于根结点,右子树必须大于根结点
根据后序遍历和中序遍历画出二叉搜索树,还是比较好画的
实际上折半查找判定树是一棵二叉排序树,所以它的中序遍历是有序序列,咱们可以把1-10填到每个选项中,然后判断图是否正确的一个方法就是,在一棵树中,要么都选择向上取整,要么都选择向下取整,否则错误。
B选项4、5相加除二向上取整,7、8相加除二向下取整,矛盾。C选项,3、4相加除二向上取整,6、7相加除二向下取整,矛盾。D选项,1、10相加除二向下取整,6、7相加除二向上取整,矛盾。A符合折半查找规则,正确。
6-1 二分查找 (20分)
本题要求实现二分查找算法。
函数接口定义:
Position BinarySearch( List L, ElementType X );
其中List结构定义如下:
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
L
是用户传入的一个线性表,其中ElementType
元素可以通过>、==、<进行比较,并且题目保证传入的数据是递增有序的。函数BinarySearch
要查找X在Data中的位置,即数组下标(注意:元素从下标1开始存储)。找到则返回下标,否则返回一个特殊的失败标记NotFound
。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
List ReadInput(); /* 裁判实现,细节不表。元素从下标1开始存储 */
Position BinarySearch( List L, ElementType X );
int main()
{
List L;
ElementType X;
Position P;
L = ReadInput();
scanf("%d", &X);
P = BinarySearch( L, X );
printf("%d\n", P);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例1:
5
12 31 55 89 101
31
输出样例1:
2
输入样例2:
3
26 78 233
31
输出样例2:
0
//每轮与有序区间的中间元素进行比较,若相等则返回当前元素的位置;若带查找元素大于中间元素,则到右侧区间查找;若查找元素小于中间元素,则到左侧区间查找
//不断重复前述折半查找过程,直至查找成功,或者待查找区间失效!
Position BinarySearch( List L, ElementType X )
{
int mid,low=1,high=L->Last;
while(low<=high)
{
mid=(low+high)/2;
if(X==L->Data[mid])
return mid;
else if(X<L->Data[mid])
high=mid-1;
else
low=mid+1;
}
return NotFound;
}
6-2 是否二叉搜索树 (25分)
本题要求实现函数,判断给定二叉树是否二叉搜索树。
函数接口定义:
bool IsBST ( BinTree T );
其中BinTree结构定义如下:
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
函数IsBST须判断给定的T是否二叉搜索树,即满足如下定义的二叉树:
定义:一个二叉搜索树是一棵二叉树,它可以为空。如果不为空,它将满足以下性质:
非空左子树的所有键值小于其根结点的键值。
非空右子树的所有键值大于其根结点的键值。
左、右子树都是二叉搜索树。
如果T是二叉搜索树,则函数返回true
,否则返回false
。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef enum { false, true } bool;
typedef int ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
BinTree BuildTree(); /* 由裁判实现,细节不表 */
bool IsBST ( BinTree T );
int main()
{
BinTree T;
T = BuildTree();
if ( IsBST(T) ) printf("Yes\n");
else printf("No\n");
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例1:如下图
输出样例1:
Yes
输入样例2:如下图
输出样例2:
No
//思路:分别找到左子树的最大结点和右子树的最小结点与根结点作比较,若左子树最大值比根结点大或者右子树最小值比根结点小,则返回0;否则返回1.
//注意:空树也为二叉搜索树
bool IsBST ( BinTree T )
{
if(T==NULL)
return true;
if(T)
{
while(T->Left&&T->Left->Right) T->Left=T->Left->Right;//找到左子树的最大结点
if(T->Left&&T->Left->Data>T->Data) return false;
while(T->Right&&T->Right->Left) T->Right=T->Right->Left;//找到右子树的最小结点
if(T->Right&&T->Right->Data<T->Data) return false;
}
return true;
}
7-1 两个有序序列的中位数 (25分)
已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0 ,A1 ,⋯,AN−1
的中位数指A(N−1)/2
的值,即第⌊(N+1)/2⌋
个数(A0
为第1个数)。
输入格式:
输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。
输出格式:
在一行中输出两个输入序列的并集序列的中位数。
输入样例1:
5
1 3 5 7 9
2 3 4 5 6
输出样例1:
4
输入样例2:
6
-100 -10 1 1 1 1
-50 0 2 3 4 5
输出样例2:
1
1.链表实现
//库函数头文件包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
//函数状态码定义
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int ElemType; //假设线性表中的元素均为整型
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
//链表创建函数
void ListInput_L(LinkList &L,int n)
{
L=(LNode*)malloc(sizeof(LNode)); L->next=NULL;//建立一个带头结点的新链表
if(!L) exit(OVERFLOW);
LNode* p=L,*t;//一个尾指针,一个指向新节点的指针
int e;
//scanf("%d",&e);
for(int i=0;i<n;i++)
{
scanf("%d",&e);
t=(LNode*)malloc(sizeof(LNode));//开辟新空间用来存放新数据
t->data=e;
t->next=NULL;
p->next=t;
p=t;
}
p->next=NULL;
L=p;
}
LinkList MergeList_L(LNode* &la,LNode* &lb)
{
LNode*pa,*pb,*pc;
LinkList lc;
pa=la->next;pb=lb->next;
lc=(LNode*)malloc(sizeof(LNode));lc->next=NULL;
if(!lc) exit(OVERFLOW);
pc=lc;
while(pa&&pb)
{
if(pa->data>=pb->data)
{
pc->next=pb;
pb=pb->next;
pc=pc->next;
}
else
{
pc->next=pa;
pa=pa->next;
pc=pc->next;
}
}
if(!pa)
{
pc->next=pb;free(la);
}
else
{
pc->next=pa;free(lb);
}
return lc;
}
void FindMedian(LinkList &L)
{
LNode *p=L->next;
int ans,mid,high=0,low=0,count=0;
while(L->next!=NULL)
{
count++;
L=L->next;
//printf("%x\n",L->next);
}
high=count;
mid=(low+high)/2;
for(int i=1;i<mid;i++)
{
p=p->next;
}
ans=p->data;
printf("%d",ans);
}
//链表输出函数
/*void ListPrint_L(LinkList &L)
{
LNode *p=L->next;
if(!p){
printf("NULL");
return;
}
while(p!=NULL)
{
if(p->next!=NULL)
printf("%d ",p->data);
else
printf("%d",p->data);
p=p->next;
}
}*/
int main()
{
int n;
scanf("%d",&n);
LinkList La,Lb,Lc;
ListInput_L(La,n);//ListPrint_L(La);
ListInput_L(Lb,n);//ListPrint_L(Lb);
Lc=MergeList_L(La,Lb);
// ListPrint_L(Lc);
FindMedian(Lc);
return 0;
}
2.动态数组实现
#include <iostream>
using namespace std;
#define MAXSIZE 100001
typedef int KeyType;
typedef struct
{
KeyType key;
} ElemType;
typedef struct
{ ElemType *R;
int length;
} SSTable;
void Create(SSTable &T,int n)
{
int i;
T.R=new ElemType[MAXSIZE+1];
T.length=n;
for(i=0;i<T.length;i++)
cin>>T.R[i].key;
}
SSTable Merge(SSTable t1,SSTable t2)
{
SSTable t3;
t3.R=new ElemType[MAXSIZE+1];
int i=0,j=0;
int temp=0;
while (i<t1.length&&j<t2.length)
{
if(t1.R[i].key<=t2.R[j].key)
t3.R[temp++].key=t1.R[i++].key;
else t3.R[temp++].key=t2.R[j++].key;
}
while(i<t1.length)
{
t3.R[temp++].key=t1.R[i++].key;
}
while(j<t2.length)
{
t3.R[temp++].key=t2.R[j++].key;
}
t3.length=temp;
return t3;
}
int Search(SSTable T)
{
int ans;
int low=0,high=T.length,mid;
mid=(low+high-1)/2;
ans=T.R[mid].key;
return ans;
}
int main()
{
int n;
cin>>n;
SSTable T1;
SSTable T2;
Create(T1,n);
/*for(int i=0;i<T1.length;i++)
{
cout<<T1.R[i].key<<" ";
}
cout<<endl;*/
Create(T2,n);
/*for(int i=0;i<T2.length;i++)
{
cout<<T2.R[i].key<<" "<<endl;
}
cout<<endl;*/
SSTable t3=Merge(T1,T2);
/*for(int i=0;i<t3.length;i++)
{
cout<<t3.R[i].key<<" ";
}
cout<<endl;*/
int A=(int)Search(t3);
cout<<A<<endl;
return 0;
}