数据结构作业19复习

在这里插入图片描述
记住二叉树的概念并据此做题,兵来将挡,水来土掩
在这里插入图片描述
在这里插入图片描述
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并集的中位数。有序序列A​0​​ ,A​1​​ ,⋯,A​N−1 的中位数指A(N−1)/2​​ 的值,即第⌊(N+1)/2⌋个数(A​0​​ 为第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;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值