17级计科与信安的数据结构期末题(A卷)
这个判断选择的顺序考试时都是打乱的,我这个是作废版的,顺序有点混乱,但题都是一样的
有不会的私聊我就好
二.选择题
三.函数题
本题要求按照先序遍历的顺序输出给定二叉树的叶结点。
void PreorderPrintLeaves( BinTree BT );
其中BinTree
结构定义如下:
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
函数PreorderPrintLeaves
应按照先序遍历的顺序输出给定二叉树BT
的叶结点,格式为一个空格跟着一个字符。
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
BinTree CreatBinTree(); /* 实现细节忽略 */
void PreorderPrintLeaves( BinTree BT );
int main()
{
BinTree BT = CreatBinTree();
printf("Leaf nodes are:");
PreorderPrintLeaves(BT);
printf("\n");
return 0;
}
/* 你的代码将被嵌在这里 */
Leaf nodes are: D E H I
答案:
啥难度都没有
递归先序遍历输出结点时判断下,是空的就输出即可
void PreorderPrintLeaves( BinTree BT )
{
if(BT)
{
if(!BT->Left&&!BT->Right)
printf(" %c",BT->Data);
PreorderPrintLeaves(BT->Left);
PreorderPrintLeaves(BT->Right);
}
return;
}
本题要求编写函数实现带头结点的单链线性表的就地逆置操作函数。L是一个带头结点的单链表,函数ListReverse_L(LinkList &L)要求在不新开辟节点的前提下将单链表中的元素进行逆置,如原单链表元素依次为1,2,3,4,则逆置后为4,3,2,1。
void ListReverse_L(LinkList &L);
其中 L
是一个带头结点的单链表。
//库函数头文件包含
#include
#include
#include
//函数状态码定义
#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;
Status ListCreate_L(LinkList &L,int n)
{
LNode *rearPtr,*curPtr; //一个尾指针,一个指向新节点的指针
L=(LNode*)malloc(sizeof (LNode));
if(!L)exit(OVERFLOW);
L->next=NULL; //先建立一个带头结点的单链表
rearPtr=L; //初始时头结点为尾节点,rearPtr指向尾巴节点
for (int i=1;i<=n;i++){ //每次循环都开辟一个新节点,并把新节点拼到尾节点后
curPtr=(LNode*)malloc(sizeof(LNode));//生成新结点
if(!curPtr)exit(OVERFLOW);
scanf("%d",&curPtr->data);//输入元素值
curPtr->next=NULL; //最后一个节点的next赋空
rearPtr->next=curPtr;
rearPtr=curPtr;
}
return OK;
}
void ListReverse_L(LinkList &L);
void ListPrint_L(LinkList &L){
//输出单链表
LNode *p=L->next; //p指向第一个元素结点
while(p!=NULL)
{
if(p->next!=NULL)
printf("%d ",p->data);
else
printf("%d",p->data);
p=p->next;
}
}
int main()
{
LinkList L;
int n;
scanf("%d",&n);
if(ListCreate_L(L,n)!= OK) {
printf("表创建失败!!!\n");
return -1;
}
ListReverse_L(L);
ListPrint_L(L);
return 0;
}
/* 请在这里填写答案 */
输入格式:
第一行输入一个整数n,表示单链表中元素个数,接下来一行共n个整数,中间用空格隔开。
输出格式:
输出逆置后顺序表的各个元素,两个元素之间用空格隔开,最后一个元素后面没有空格。
4
1 2 3 4
4 3 2 1
答案:
这个还是有难度的
思路:逆置链表初始为空,表中节点从原链表中依次“删除”,再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的第一个结点,如此循环,直至原链表为空。
void ListReverse_L(LinkList &L)//L为头结点
{
LinkList p,q;
p = L->next;
L->next = NULL;
while(p)
{
//向后挪
q = p;//
p = p->next;
//头插
q->next = L->next;//非常重要,相当于p和q之间没有了指针连接
L->next = q;//把q接到头的后面
}
}
新浪微博上有个“悄悄关注”,一个用户悄悄关注的人,不出现在这个用户的关注列表上,但系统会推送其悄悄关注的人发表的微博给该用户。现在我们来做一回网络侦探,根据某人的关注列表和其对其他用户的点赞情况,扒出有可能被其悄悄关注的人。
输入首先在第一行给出某用户的关注列表,格式如下:
人数N 用户1 用户2 …… 用户N
其中N
是不超过5000的正整数,每个用户i
(i
=1, ..., N
)是被其关注的用户的ID,是长度为4位的由数字和英文字母组成的字符串,各项间以空格分隔。
之后给出该用户点赞的信息:首先给出一个不超过10000的正整数M
,随后M
行,每行给出一个被其点赞的用户ID和对该用户的点赞次数(不超过1000),以空格分隔。注意:用户ID是一个用户的唯一身份标识。题目保证在关注列表中没有重复用户,在点赞信息中也没有重复用户。
我们认为被该用户点赞次数大于其点赞平均数、且不在其关注列表上的人,很可能是其悄悄关注的人。根据这个假设,请你按用户ID字母序的升序输出可能是其悄悄关注的人,每行1个ID。如果其实并没有这样的人,则输出“Bing Mei You”。
10 GAO3 Magi Zha1 Sen1 Quan FaMK LSum Eins FatM LLao
8
Magi 50
Pota 30
LLao 3
Ammy 48
Dave 15
GAO3 31
Zoro 1
Cath 60
Ammy
Cath
Pota
11 GAO3 Magi Zha1 Sen1 Quan FaMK LSum Eins FatM LLao Pota
7
Magi 50
Pota 30
LLao 48
Ammy 3
Dave 15
GAO3 31
Zoro 29
Bing Mei You
答案:
这个题我是用Java写的,有一个样例会超时。。。
大体的思路就是一个arraylist两个map(一个map一个map2),如果map的key不在list中,就把这个map对应的key和value存到map2中,再对map2进行排序即可
不过这个题时间卡的很紧,STL或者java的容器都会超时。
这个题考试时,超时的话十分给8分,不会的话直接输出也能得三分。。。
还有个问题,就是关于输入,我这个题考试就得了3分。。。就是因为STL的map不会使,java不会输入。。。
记住java的String输入,next()是遇到空格就截止,nextline()是遇到换行才截止,不然就一直读。。。
现在想想真心累。。。
import java.util.*;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
List list = new ArrayList();
//请注意这个输入!!!nextLine是一直输入,遇到换行才停止。next则是遇到空格就停止
int n = sc.nextInt();
//sc.next();
String s1 = sc.nextLine();
String []s2 = s1.split(" ");
int m = sc.nextInt();
sc.nextLine();
Map map = new HashMap();
for(int i = 0;i < m;i++)
{
String a = sc.next();
int b = sc.nextInt();
map.put(a, b);
}
for(int i = 0;i < s2.length;i++)
{
list.add(s2[i]);
}
//System.out.println(0);
// System.out.println(map);
int average = 0,sum = 0;
for(Integer i : map.values())
{
sum += i;
}
average = sum/m;//求出average
//System.out.println(average+" "+sum);
Map map2 = new HashMap();
//遍历map,如果map的key不包含在list中,就把那个map的key和value放到map2中
for (Map.Entry entry : map.entrySet())
{
if(!list.contains(entry.getKey())&&entry.getValue()>average)
{
map2.put(entry.getKey(), entry.getValue());
}
}
//System.out.println(map2);
if(map2.isEmpty())
{
System.out.println("Bing Mei You");
}
else
{
//System.out.println("hh");
List> lis = new ArrayList>(map2.entrySet());
Collections.sort(lis, new Comparator>() {
public int compare(Map.Entry e1, Map.Entry e2) {
return e1.getKey().compareTo(e2.getKey());
}
});
for(int i = 0;i < lis.size();i++)
{
System.out.println(lis.get(i).getKey());
}
}
}
}
这是一个大佬写的Accept代码
#include
#include
#include
#include
#include
#include
#include
p1-1:
后者把2提到前面,N方肯定比2N快
p1-2:
访问结点必须要找到他的直接前驱,需要遍历单链表,时间复杂度O(N)
p1-3:
他是循环(环状)队列,rear可能会等于0的
p1-4:
4输出完了之后不是5的话不可能直接输出1
p1-5:
顺序表一定连续,链表很随性,连不连续都成
p1-6:
堆的每个同一层之间并没有顺序,这题不会的话好好理解堆的定义去
p1-7:
画一画就知道不可能
p1-8:
p1-10:
只要理解了啥是平方探测法(当然要注意这道题的平方探测不太正规,没有负的,那其实就更简单了)
这个题没任何难度
p1-11:
prime算法就是让一颗小树长大的过程
x2-2:
逻辑上可以把数据结构分成:线性结构和非线性结构
x2-3:
链栈的top指针应该设在头部
x2-4:
这个没啥可说的
x2-5:
画图就好了
x2-6:
x2-7:
这个其实你只要会了森林转换成二叉树的方法画个图自己看看就成
比如最下面这个图,你看看bd和ac的过程就会发现只有父子和兄弟两种关系
x2-8:
x2-9:
具有n个顶点的有向完全图有n*(n-1)条弧,即完全无向图的2倍
x2-11:
三趟每次都是最大的在最后边,所以是冒泡
x2-12:
快排最好的时候为O(NlogN),最坏时是O(N)方
x2-13:
二分查找的时间复杂度:O(log2n)
x2-15:
这个一看就知道D是顶点集,R是边集,所以肯定是图
x2-16:
这个就是考拓扑序的定义,不知道啥是拓扑序的百度就好
x2-17:
这个就是A,可别错选成C
x2-18:
二分查找次数不超过【log2n】+1(以2为底n的对数)