1-1
在具有N个结点的单链表中,访问结点和增加结点的时间复杂度分别对应为O(1)和O(N)。
F
1-2
将N个数据按照从小到大顺序组织存放在一个单向链表中。如果采用二分查找,那么查找的平均时间复杂度是O(logN)。
F
1-3
若用链表来表示一个线性表,则表中元素的地址一定是连续的。
F
1-4
链表 - 存储结构
链表是一种随机存取的存储结构。
F
1-5
线性表L如果需要频繁地进行不同下标元素的插入、删除操作,此时选择顺序存储结构更好。
F
2-1
在具有N个结点的单链表中,实现下列哪个操作,其算法的时间复杂度是O(N)?
A.在地址为p的结点之后插入一个结点
B.删除开始结点
C.遍历链表和求链表的第i个结点
D.删除地址为p的结点的后继结点
2-2
将线性表La和Lb头尾连接,要求时间复杂度为O(1),且占用辅助空间尽量小。应该使用哪种结构?
A.单链表
B.单循环链表
C.带尾指针的单循环链表
D.带头结点的双循环链表
2-3
对于一个具有N个结点的单链表,在给定值为x的结点后插入一个新结点的时间复杂度为
A.O(1)
B.O(N/2)
C.O(N)
D.O(N2)
2-4
对于一非空的循环单链表,h
和p
分别指向链表的头、尾结点,则有:
A.p->next == h
B.p->next == NULL
C.p == NULL
D.p == h
2-5
分数 2
作者 DS课程组
单位 浙江大学
将两个结点数都为N且都从小到大有序的单向链表合并成一个从小到大有序的单向链表,那么可能的最少比较次数是:
A.1
B.N
C.2N
D.NlogN
2-6
采用多项式的非零项链式存储表示法,如果两个多项式的非零项分别为N1和N2个,最高项指数分别为M1和M2,则实现两个多项式相乘的时间复杂度是:
A.O(N1+N2)
B.O(M1+M2)
C.O(N1×N2)
D.O(M1×M2)
2-7
已知表头元素为c
的单链表在内存中的存储状态如下表所示:
现将f
存放于1014H
处,并插入到单链表中,若f
在逻辑上位于a
和e
之间,则a
、e
、f
的“链接地址”依次
是:
A.1010H
, 1014H
, 1004H
B.1010H
, 1004H
, 1014H
C.1014H
, 1010H
, 1004H
D.1014H
, 1004H
, 1010H
2-8
已知指针ha和hb分别是两个单链表的头指针,下列算法将这两个链表首尾相连在一起,并形成一个循环链表(即ha的最后一个结点链接hb的第一个结点,hb的最后一个结点指向ha),返回ha作为该循环链表的头指针。请将该算法补充完整。
typedef struct node{
ElemType data;
struct node *next;
}LNode;
LNode *merge(LNode *ha, LNode *hb) {
LNode *p=ha;
if (ha==NULL || hb==NULL) {
cout<<”one or two link lists are empty!”<<endl;
return NULL;
}
while ( p->next!=NULL )
p=p->next;
p->next=hb;
while ( p->next!=NULL )
p=p->next;
__________
}
A.ha=p->next; return ha;
B.p->next=ha; return ha;
C.ha=p->next; return p;
D.p->next=ha; return p;
2-9
假设某个带头结点的单链表的头指针为head,则判定该表为空表的条件是( )
A.head==NULL
B.head->next==NULL
C.head!=NULL
D.head->next==head
2-10
单链表 - 时间复杂度
在包含 n 个数据元素的单链表中,▁▁▁▁▁ 的时间复杂度不为 O(n)。
A.访问第 i(1≤i≤n) 个数据元素
B.在位序 i(1≤i≤n+1) 处插入一个新结点
C.删除位序 i(1≤i≤n) 处的结点
D.将 n 个元素按升序排序
5-1
单链表逆转
分数 5
作者 DS课程组
单位 浙江大学
下列代码的功能是返回带头结点的单链表L
的逆转链表。
List Reverse( List L )
{
Position Old_head, New_head, Temp;
New_head = NULL;
Old_head = L->Next;
while ( Old_head ) {
Temp = Old_head->Next;
______________________________;
New_head = Old_head;
Old_head = Temp;
}
______________________________;
return L;
}
Old_head->Next = New_head;
L->Next = New_head;
6-1 单链表分段逆转
给定一个带头结点的单链表和一个整数K,要求你将链表中的每K个结点做一次逆转。例如给定单链表 1→2→3→4→5→6 和 K=3,你需要将链表改造成 3→2→1→6→5→4;如果 K=4,则应该得到 4→3→2→1→5→6。
函数接口定义:
void K_Reverse( List L, int K );
其中List
结构定义如下:
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
L
是给定的带头结点的单链表,K
是每段的长度。函数K_Reverse
应将L
中的结点按要求分段逆转。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
List ReadInput(); /* 裁判实现,细节不表 */
void PrintList( List L ); /* 裁判实现,细节不表 */
void K_Reverse( List L, int K );
int main()
{
List L;
int K;
L = ReadInput();
scanf("%d", &K);
K_Reverse( L, K );
PrintList( L );
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
6
1 2 3 4 5 6
4
输出样例:
4 3 2 1 5 6
void K_Reverse( List L, int K )
{
int count = 0,cnt = 1;
List New, Old, Tag, p = L->Next, q = L, Last;
while(p!=NULL)
{
p = p->Next;
count++;
}
for(int i = 0;i < count/K;i++)
{
cnt = 1;
New = q->Next;
Old = New->Next;
Last = New;//Last指向每一轮逆转的第一个结点,逆转后就变成了最后一个结点
while(cnt < K)
{
Tag = Old->Next;
Old->Next = New;
New = Old;
Old = Tag;
cnt++;
}
q->Next = New;
Last->Next = Old;
q = Last;
}
}
6-2 共享后缀的链表
有一种存储英文单词的方法,是把单词的所有字母串在一个单链表上。为了节省一点空间,如果有两个单词有同样的后缀,就让它们共享这个后缀。下图给出了单词“loading”和“being”的存储形式。本题要求你找出两个链表的公共后缀。
函数接口定义:
PtrToNode Suffix( List L1, List L2 );
其中List
结构定义如下:
typedef struct Node *PtrToNode; struct Node { ElementType Data; /* 存储结点数据 */ PtrToNode Next; /* 指向下一个结点的指针 */ }; typedef PtrToNode List; /* 定义单链表类型 */
L1
和L2
都是给定的带头结点的单链表。函数Suffix
应返回L1
和L2
的公共后缀的起点位置。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef char ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
void ReadInput( List L1, List L2 ); /* 裁判实现,细节不表 */
void PrintSublist( PtrToNode StartP ); /* 裁判实现,细节不表 */
PtrToNode Suffix( List L1, List L2 );
int main()
{
List L1, L2;
PtrToNode P;
L1 = (List)malloc(sizeof(struct Node));
L2 = (List)malloc(sizeof(struct Node));
L1->Next = L2->Next = NULL;
ReadInput( L1, L2 );
P = Suffix( L1, L2 );
PrintSublist( P );
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
如图存储的链表
输出样例:
ing
#include<math.h>
PtrToNode Suffix( List L1, List L2 )
{
PtrToNode p = L1, q = L2;
int len1 = 0, len2 = 0;
while(p != NULL)
{
p = p->Next;
len1++;
}
while(q != NULL)
{
q = q->Next;
len2++;
}
if(len1 > len2)
p = L1,q = L2;
else
p = L2,q = L1;
for(int i = 0;i < abs(len1-len2);i++)
{
p = p->Next;
}
for(int i = 0;i < 5;i++)
{
int j = i;
}
while(p->Next != q->Next)
{
p = p->Next;
q = q->Next;
}
return p->Next;
}
7-1 喊山
喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤。呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的。原来它是彝族先民用来求援呼救的“讯号”,慢慢地人们在生活实践中发现了它的实用价值,便把它作为一种交流工具世代传袭使用。(图文摘自:http://news.xrxxw.com/newsshow-8018.html)
一个山头呼喊的声音可以被临近的山头同时听到。题目假设每个山头最多有两个能听到它的临近山头。给定任意一个发出原始信号的山头,本题请你找出这个信号最远能传达到的地方。
输入格式:
输入第一行给出3个正整数n
、m
和k
,其中n
(≤10000)是总的山头数(于是假设每个山头从1到n
编号)。接下来的m
行,每行给出2个不超过n
的正整数,数字间用空格分开,分别代表可以听到彼此的两个山头的编号。这里保证每一对山头只被输入一次,不会有重复的关系输入。最后一行给出k
(≤10)个不超过n
的正整数,数字间用空格分开,代表需要查询的山头的编号。
输出格式:
依次对于输入中的每个被查询的山头,在一行中输出其发出的呼喊能够连锁传达到的最远的那个山头。注意:被输出的首先必须是被查询的个山头能连锁传到的。若这样的山头不只一个,则输出编号最小的那个。若此山头的呼喊无法传到任何其他山头,则输出0。
输入样例:
7 5 4
1 2
2 3
3 1
4 5
5 6
1 4 5 7
输出样例:
2
6
4
0
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct shan
{
int l;
int no;
};
const int N = 10001;
vector<int>v[N];
int bj[N];
queue<shan>q;
void clear(queue<shan> &p)
{
queue<shan> empty;
swap(empty, p);
}
int bfs(int x)
{
//clear(q);
memset(bj, 0, sizeof(bj));
shan s;
int lc = 0, No = x;
s.l = 0;
s.no = x;
q.push(s);
bj[x] = 1;
while (1)
{
if (q.empty())
break;
shan s1 = q.front();
if (lc == s1.l)
No = min(No, s1.no);
else if (lc < s1.l)
{
lc = s1.l;
No = s1.no;
}
for (int i = 0; i < v[s1.no].size(); i++)
{
if (bj[v[s1.no][i]] == 0)
{
bj[v[s1.no][i]] = 1;
s.l = s1.l + 1;
s.no = v[s1.no][i];
q.push(s);
}
}
q.pop();
}
if (lc == 0)
return 0;
else
return No;
}
int main()
{
int n, m, k;
cin >> n >> m >> k;
int m1, m2;
memset(bj, 0, sizeof(bj));
for (int i = 0; i < m; i++)
{
cin >> m1 >> m2;
v[m1].push_back(m2);
v[m2].push_back(m1);//建图
}
for (int i = 1; i <= k; i++)
{
int x;
cin >> x;
cout << bfs(x) << endl;
}
return 0;
}