一、单项选择题
1、设n是描述问题规模的非负整数,下面程序片段的时间复杂度为( )。
x=1;
while (x<=n) x=5*x;
A.
O
(
l
o
g
5
n
)
O(log_5^n)
O(log5n)
B.
O
(
n
)
O(n)
O(n)
C.
O
(
n
l
o
g
5
n
)
O(nlog_5^n)
O(nlog5n)
D.
O
(
n
5
)
O(n^5)
O(n5)
2、顺序表和链表相比存储密度较大,这是因为( )。
A.顺序表的存储空间是预先分配的
B.顺序表不需要增加指针来表示元素之间的逻辑关系
C.链表中所有节点的地址是连续的
D.顺序表中所有元素的存储地址是不连续的
3、在长度为n(n≥1)的循环双链表L中,在尾节点之后插入一个新节点的时间复杂度为( )。
A.
O
(
n
2
)
O(n^2)
O(n2)
B.
O
(
n
)
O(n)
O(n)
C.
O
(
1
)
O(1)
O(1)
D.
O
(
n
l
o
g
2
n
)
O(nlog_2^n)
O(nlog2n)
4、设栈的输入序列是1、2、3、4,则( )不可能是其出栈序列。
A.1,2,4,3
B.2,1,3,4
C.1,4,3,2
D.4,3,1,2
5、当用一个数组data[0…n-1]存放栈中元素时,栈底最好( )。
A. 设置在data[0]或data[n-1]处
B.设置在data[n-1]处
C. 设置在data[0]处
D.设置在data数组的任何位置
6、在数据处理过程中常需要保存一些中间数据,如果先保存的数据先处理,则使用( )来保存这些数据。
A.线性表
B. 队列
C. 栈
D.单链表
7、在环形队列中,元素的排列顺序( )。
A.与队头和队尾指针的取值有关
B.与元素值的大小有关
C.由元素进队的先后顺序确定
D.与存放队中元素的数组大小有关
8、将10阶对称矩阵压缩存储到一维数组A中,则数组A的长度最少为( )。
A.100
B.40
C.80
D.55
9、设目标串为s,模式串为是t,在KMP模式匹配中,next[4]=2的含义是( )。
A.表示t4字符前面最多有2个字符和开头的2个字符相同
B.表示s4字符前面最多有2个字符和开头的2个字符相同
C.表示目标串匹配失败的位置是i=4
D.表示模式串匹配失败的位置是j=2
10、由权值分别为9、2、7、5的四个叶子节点构造一棵哈夫曼树,该树的带权路径长度为( )。
A.23
B.44
C.37
D.27
11、对于无向图的邻接矩阵来说,( )。
A.第i行上、第i列上非零元素总数等于顶点i的度数
B.矩阵中的非零元素个数等于图中的边数
C.第i行上的非零元素个数和第i列的非零元素个数一定相等
D.邻接矩阵中非全零行的行数等于图中的顶点数
12、有一个顶点编号为0~4的带权有向图G,现用Floyd算法求任意两个顶点之间的最短路径,在算法执行的某时刻,已考虑了0~2的顶点,现考虑顶点3,则以下叙述中正确的是( )。
A.只可能修改从顶点0~2到顶点3的最短路径
B.只可能修改从顶点3到顶点0~2的最短路径
C.只可能修改从顶点0~2到顶点4的最短路径
D.所有两个顶点之间的路径都可能被修改
13、适合于折半查找的数据组织方式是( )。
A.以顺序表存储的有序线性表
B.以顺序表存储的线性表
C.以链表存储的有序线性表
D. 以链表存储的线性表
14、对含有n个元素的顺序表采用顺序查找方法,不成功时的比较次数是( )。
A. 1
B. n
C. n-1
D. n+1
15、在一棵平衡二叉树中,每个节点的平衡因子的取值范围是( )。
A. 1~2
B. -2~2
C. -1~1
D. 0~1
16、在一棵m阶B-树中删除一个关键字会引起合并,则该节点原有( )个关键字。
A. 1
B.
⌈
m
2
⌉
⌈\frac{m}2⌉
⌈2m⌉
C.
⌈
m
2
⌉
⌈\frac{m}2⌉
⌈2m⌉+1
D.
⌈
m
2
⌉
⌈\frac{m}2⌉
⌈2m⌉-1
17、以下关于哈希查找的叙述中正确的是( )。
A.哈希查找中不需要任何关键字的比较
B.采用拉链法解决冲突时,查找每个元素的时间是相同的
C.哈希表在查找成功时的平均查找长度仅仅与表长有关
D.哈希表的装填因子等于表中填入的记录数除以哈希表的长度
18、以下排序方法中,( )在初始序列已基本有序的情况下,排序效率最高。
A.二路归并排序
B. 快速排序
C. 直接插入排序
D.堆排序
19、如要在1000个整数中找出前10个最小的整数,在以下排序方法中最好采用( )。
A.直接插入排序
B. 冒泡排序
C.二路归并排序
D. 希尔排序
20、有n个十进制整数进行基数排序,其中最大的整数为5位,则基数排序过程中临时建立的队数个数是( )。
A.10
B.n
C.5
D.2
21、 在一棵含有n个关键字的m阶B树中进行查找,至多读盘()次。
A.
l
o
g
2
n
log_2^n
log2n
B.
1
+
l
o
g
2
n
1+log_2^n
1+log2n
C.
l
o
g
⌈
m
2
⌉
n
+
1
2
+
1
log_⌈\frac m2⌉^{\frac{n+1}2+1}
log⌈2m⌉2n+1+1
D.
l
o
g
⌈
n
2
⌉
m
+
1
2
+
1
log_⌈\frac n2⌉^{\frac{m+1}2+1}
log⌈2n⌉2m+1+1
- 要使读盘次数最多,则B树的高要最大,因为B树的高度就是读盘的次数。此时应保证每个结点的关键字最少,即分支最少。
- 此题可用排除法快速解决:关键字的个数n是固定的,此时B树的阶数越大,B树会变得"矮胖",而该题要求读盘次数最多,即B树要"瘦高"。它取决于B树的阶m,而A、B选项中不包含m,排除。由D选项可知,关键字越多,读盘次数越少,显然不对,关键字多,读盘次数就多,D排除。
- 将5个字母“ooops"按此顺序进栈,则有()种不同的出栈顺序可以仍然得到“ooops"。
A.1
B.3
C.5
D.6
- 此题转换一个思路可能更好做,将它看成是5个数字进栈,最后要得到出栈序列是【(123任意顺序)45】。此时1 2 3入栈,会得到6种出栈结果:123、132、213、231、321、312,但其中312的出栈序列是不合法的,因此一共有五种不同的出栈顺序。
- 已知待排序的n个元素可分为
n
k
\frac nk
kn个组,每个组包含k个元素,且任一组内的各元素均分别大于前一组内的所有元素和小于后一组内的所有元素,若采用基于比较的排序,其时间下界应为( )。
A. n l o g 2 n nlog_2^n nlog2n
B. n l o g 2 k nlog_2^k nlog2k
C. k l o g 2 n klog_2^n klog2n
D. k l o g 2 k klog_2^k klog2k
- 分析可知:这三个组组间是有序的,组内无序,所以只需要把三个组内部都分别排序,所有元素就有序了。每组元素为k,最好的比较排序(快排、堆排、归并)的平均复杂度是 O ( k l o g 2 k ) O(klog_2^k) O(klog2k),再乘以组数 n k \frac nk kn,就是 n l o g 2 k nlog_2^k nlog2k。
二、问答题
1、 若要在N个海量数据(超过十亿,不能一次全部放入内存)中找出最大的k个数(内存可以容纳k个数),最好采用什么数据结构和策略?请详细说明你采用的数据结构和策略,并用时间复杂度和空间复杂度来说明理由。
- 首先读入k个数,假设第一次读取的k个数就是前k个最大的数,然后把k个数建成小顶堆。然后从第k+1个数开始,每个数都与堆顶的数值进行比较,如果数字d大于堆顶元素,则把堆顶的元素的元素替换成d,再将其调整成为小顶堆。当所有数据都读入并比较完之后,这个小顶堆里面的所有元素就是最大的k个数。时间复杂度为O(NlogK),空间复杂度为O(K)。
2、 一棵二叉排序树的结构如图1所示,其中各结点的关键字依次为32~40,请标出各结点的关键字。
3、 一组记录关键字为(5,11,7,2,3,17),利用堆排序方法建立初始大根堆,给出你建立的初始大根堆对应的关键字序列。
- 初始大根堆对应的关键字序列为(17,11,7,2,3,5)
三、算法设计题
1. 假设一个有向图G采用邻接表存储。设计一个算法判断顶点i和顶点j(i≠j)之间是否相互连通,假设这两个顶点均存在。
bool HasEdge(AdjGraph g, VertexType x, VertexType y) //传入两个顶点的数据
{
int i, j, k;
for (i = 0; i < g.vexnum; i++) //寻找两个顶点对应的数组下标
{
if (g.adjlist[i].data == x) j = i; //第一个顶点的下标
if (g.adjlist[i].data == y) k = i; //第二个顶点的下标
}
ArcNode* p = g.adjlist[j].firstarc, * q = g.adjlist[k].firstarc;
bool first = false, second = false;
while (p != NULL) //遍历第一个顶点中的单链表
{
if (p->adjvex == k) //如果当前访问结点与第二个结点的下标相同
{
first = true; //标记
break; //退出循环
}
else p = p->nextarc; //如果不相同,指针后移,继续判断
}
while (q != NULL)
{
if (q->adjvex == j) //如果当前访问结点与第一个结点的下标相同
{
second = true; //标记
break; //退出循环
}
else q = q->nextarc; //如果不相同,指针后移,继续判断
}
return first && second; //当两个值都是true时,才说明存在相互的边
}
运行结果:
2. 有一个含有n个整数的无序数据序列,所有的数据元素均不相同,采用整数数组R[0…n-1]存储,请完成以下任务:
(1)设计一个尽可能高效的算法,输出该序列中第k(1≤k≤n)小的元素,算法中给出适当的注释信息。
(2)分析你所设计的求解算法的平均时间复杂度,并给出求解过程。
3. 将一个数组最开始的若干元素搬到数组的末尾,称之为数组的旋转。输入一个己排好序数组的一个旋转,求该旋转数组的最小元素。如,数组(3,4,5,1,2}为有序数组(1,2,3,4,5}的一个旋转数组,该数组的最小值为1。
- 方法一:遍历数组一次,最小值即为所求,此时的时间复杂度为O(n)
- 方法二:采用二分法:此时的时间复杂度为 O ( l o g 2 n ) O(log_2^n) O(log2n)
int MinEle(int a[], int num)
{
int low = 0, high = num - 1, mid;
while (low <= high)
{
mid = (low + high) / 2; //取数组最中间的元素
if (a[mid] > a[high]) //如果中间的值比最后一个元素值大
{
low = mid + 1; //在后半部分查找
if (low == high) return a[low];
}
else if (a[mid] < a[high]) //如果中间的值比最后一个元素值小
{
high = mid; //在中前半部分查找
if (low == high) return a[low];
}
else high--; //如果中间的值和最后一个元素值相等,每次将数组的长度缩短一个
}
}
运行结果: