本题要求实现带头结点的链式表操作集。
函数接口定义:
List MakeEmpty(); Position Find( List L, ElementType X ); bool Insert( List L, ElementType X, Position P ); bool Delete( List L, Position P );
其中List
结构定义如下:
typedef struct LNode *PtrToLNode; struct LNode { ElementType Data; PtrToLNode Next; }; typedef PtrToLNode Position; typedef PtrToLNode List;
各个操作函数的定义为:
List MakeEmpty()
:创建并返回一个空的线性表;
Position Find( List L, ElementType X )
:返回线性表中X的位置。若找不到则返回ERROR;
bool Insert( List L, ElementType X, Position P )
:将X插入在位置P指向的结点之前,返回true。如果参数P指向非法位置,则打印“Wrong Position for Insertion”,返回false;
bool Delete( List L, Position P )
:将位置P的元素删除并返回true。若参数P指向非法位置,则打印“Wrong Position for Deletion”并返回false。
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> #define ERROR NULL typedef enum {false, true} bool; typedef int ElementType; typedef struct LNode *PtrToLNode; struct LNode { ElementType Data; PtrToLNode Next; }; typedef PtrToLNode Position; typedef PtrToLNode List; List MakeEmpty(); Position Find( List L, ElementType X ); bool Insert( List L, ElementType X, Position P ); bool Delete( List L, Position P ); int main() { List L; ElementType X; Position P; int N; bool flag; L = MakeEmpty(); scanf("%d", &N); while ( N-- ) { scanf("%d", &X); flag = Insert(L, X, L->Next); if ( flag==false ) printf("Wrong Answer\n"); } scanf("%d", &N); while ( N-- ) { scanf("%d", &X); P = Find(L, X); if ( P == ERROR ) printf("Finding Error: %d is not in.\n", X); else { flag = Delete(L, P); printf("%d is found and deleted.\n", X); if ( flag==false ) printf("Wrong Answer.\n"); } } flag = Insert(L, X, NULL); if ( flag==false ) printf("Wrong Answer\n"); else printf("%d is inserted as the last element.\n", X); P = (Position)malloc(sizeof(struct LNode)); flag = Insert(L, X, P); if ( flag==true ) printf("Wrong Answer\n"); flag = Delete(L, P); if ( flag==true ) printf("Wrong Answer\n"); for ( P=L->Next; P; P = P->Next ) printf("%d ", P->Data); return 0; } /* 你的代码将被嵌在这里 */
输入样例:
6
12 2 4 87 10 2
4
2 12 87 5
输出样例:
2 is found and deleted.
12 is found and deleted.
87 is found and deleted.
Finding Error: 5 is not in.
5 is inserted as the last element.
Wrong Position for Insertion
Wrong Position for Deletion
10 4 2 5
参考代码:
List MakeEmpty() {
List L;
L = (struct LNode*)malloc(sizeof(struct LNode));
L->Next = NULL;
return L;
}
Position Find(List L, ElementType X) {
// if(L->Next==NULL) return ERROR;
List pre = L->Next;
while (pre) {
if (pre->Data == X)return pre;
pre = pre->Next;
}
return ERROR;
}
bool Insert(List L, ElementType X, Position P) {
List pre = L;
List temp;
temp = (struct LNode*)malloc(sizeof(struct LNode));
temp->Data = X;
temp->Next = NULL;
while (pre) {
if (pre->Next == P) {
temp->Next = pre->Next;
pre->Next = temp;
return true;
}
pre = pre->Next;
}
printf("Wrong Position for Insertion\n");
return false;
}
bool Delete(List L, Position P) {
List pre = L->Next;
if (pre == P) {
pre = pre->Next;
return true;
}
else {
while (pre) {
if (pre->Next == P) {
pre->Next = (pre->Next)->Next;
return true;
}
pre = pre->Next;
}
}
printf("Wrong Position for Deletion\n");
return false;
}
6-2 求链表的倒数第m个元素
分数 20
全屏浏览题目
切换布局
作者 DS课程组
单位 浙江大学
请设计时间和空间上都尽可能高效的算法,在不改变链表的前提下,求链式存储的线性表的倒数第m(>0)个元素。
函数接口定义:
ElementType Find( List L, int m );
其中List
结构定义如下:
typedef struct Node *PtrToNode; struct Node { ElementType Data; /* 存储结点数据 */ PtrToNode Next; /* 指向下一个结点的指针 */ }; typedef PtrToNode List; /* 定义单链表类型 */
L
是给定的带头结点的单链表;函数Find
要将L
的倒数第m
个元素返回,并不改变原链表。如果这样的元素不存在,则返回一个错误标志ERROR
。
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> #define ERROR -1 typedef int ElementType; typedef struct Node *PtrToNode; struct Node { ElementType Data; PtrToNode Next; }; typedef PtrToNode List; List Read(); /* 细节在此不表 */ void Print( List L ); /* 细节在此不表 */ ElementType Find( List L, int m ); int main() { List L; int m; L = Read(); scanf("%d", &m); printf("%d\n", Find(L,m)); Print(L); return 0; } /* 你的代码将被嵌在这里 */
输入样例:
5
1 2 4 5 6
3
输出样例:
4
1 2 4 5 6
参考代码:
ElementType Find( List L, int m ){
List pre=L->Next;
ElementType a[100010];
int cnt=1;
while(pre){
a[cnt++]=pre->Data;
pre=pre->Next;
}
cnt--;
if(cnt>=m){
return a[cnt-m+1];
}
else{
return ERROR;
}
}
6-3 单链表分段逆转
分数 25
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
给定一个带头结点的单链表和一个整数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 ){
List pre=L->Next;
int cnt=0;
List a[100010];
List b[100010];
while(pre)
{
a[cnt++]=pre;
pre=pre->Next;
}
List head=L;
if(K==cnt){
// head=L->Next;
L->Next=a[cnt-1];
for(int i=cnt-2;i>=0;i--){
a[i+1]->Next=a[i];
}
a[0]->Next=NULL;
return;
}
else{
for(int i=1;i<=cnt/K;i++){
for(int j=0;j<K;j++){
b[j+(i-1)*K]=a[i*K-1-j];
}
}
for(int i=(cnt/K)*K;i<cnt;i++){
b[i]=a[i];
}
for(int i=0;i<cnt;i++){
head->Next=b[i];
head=b[i];
}
head->Next=NULL;
}
}
6-4 共享后缀的链表
分数 25
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
有一种存储英文单词的方法,是把单词的所有字母串在一个单链表上。为了节省一点空间,如果有两个单词有同样的后缀,就让它们共享这个后缀。下图给出了单词“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
、
PtrToNode Suffix( List L1, List L2 ){
List pre=L1;
List a[100010];
List b[100010];
int cnt=0;
while(pre){
pre=pre->Next;
a[cnt++]=pre;
}
pre=L2;
int cntb=0;
while(pre){
pre=pre->Next;
b[cntb++]=pre;
}
if(cnt<cntb){
int d=cntb-cnt;
for(int j=d;j<cntb;j++){
if(a[j-d]==b[j]){
return a[j-d];
}
}
}
else{
int d=cnt-cntb;
for(int j=0;j<cntb;j++){
if(a[j+d]==b[j]){
return b[j];
}
}
}
return NULL;
}
7-1 两个有序链表序列的合并
分数 20
全屏浏览题目
切换布局
作者 DS课程组
单位 浙江大学
已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。
输入格式:
输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:
在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL
。
输入样例:
1 3 5 -1
2 4 6 8 10 -1
输出样例:
1 2 3 4 5 6 8 10
#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int main() {
int n;
while (cin >> n) {
if (n == -1)break;
q.push(n);
}
while (cin >> n) {
if (n == -1)break;
q.push(n);
}
int pd = 0;
while (!q.empty()) {
if (pd == 0) {
cout << q.top();
pd = 1;
}
else {
cout <<' '<< q.top();
}
q.pop();
}
if (pd == 0)cout << "NULL" << endl;
else cout <<endl;
}
7-2 一元多项式的乘法与加法运算
分数 20
全屏浏览题目
切换布局
作者 DS课程组
单位 浙江大学
设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0
。
输入样例:
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1
输出样例:
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0
#include <stdio.h>
#include <stdlib.h>
int ans[20100];
int mpa[10100],mpb[10100];
int max(int a,int b){
if(a>b)return a;
else return b;
}
int main(){
int n;
//cin >> n;
scanf("%d",&n);
int maxs=0;
int maxa=0,maxb=0;
for(int i=1;i<=n;i++){
int xs,zs;
scanf("%d%d",&xs,&zs);
maxa=max(maxa,zs);
mpa[zs]=xs;
}
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++){
int xs,zs;
scanf("%d%d",&xs,&zs);
maxb=max(maxb,zs);
mpb[zs]=xs;
}
maxs=max(maxa,maxb);
for(int i=maxa;i>=0;i--){
for(int j=maxb;j>=0;j--){
ans[i+j]+=mpa[i]*mpb[j];
}
}
int pd=0;
for(int i=maxa+maxb;i>=0;i--){
if(ans[i]!=0){
if(pd==0){
printf("%d %d",ans[i],i);
pd=1;
}
else
printf(" %d %d",ans[i],i);
}
}
if(!pd)printf("0 0");
printf("\n");
pd=0;
for(int i=maxs;i>=0;i--){
if(mpa[i]+mpb[i]!=0){
if(pd==0){
printf("%d %d",mpa[i]+mpb[i],i);
pd=1;
}
else
printf(" %d %d",mpa[i]+mpb[i],i);
}
}
if(!pd)printf("0 0");
}
7-3 多项式A除以B
分数 25
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
这仍然是一道关于A/B的题,只不过A和B都换成了多项式。你需要计算两个多项式相除的商Q和余R,其中R的阶数必须小于B的阶数。
输入格式:
输入分两行,每行给出一个非零多项式,先给出A,再给出B。每行的格式如下:
N e[1] c[1] ... e[N] c[N]
其中N
是该多项式非零项的个数,e[i]
是第i
个非零项的指数,c[i]
是第i
个非零项的系数。各项按照指数递减的顺序给出,保证所有指数是各不相同的非负整数,所有系数是非零整数,所有整数在整型范围内。
输出格式:
分两行先后输出商和余,输出格式与输入格式相同,输出的系数保留小数点后1位。同行数字间以1个空格分隔,行首尾不得有多余空格。注意:零多项式是一个特殊多项式,对应输出为0 0 0.0
。但非零多项式不能输出零系数(包括舍入后为0.0)的项。在样例中,余多项式其实有常数项-1/27
,但因其舍入后为0.0,故不输出。
输入样例:
4 4 1 2 -3 1 -1 0 -1
3 2 3 1 -2 0 1
输出样例:
3 2 0.3 1 0.2 0 -1.0
1 1 -3.1
#include <stdio.h>
#include <stdlib.h>
using namespace std;
double mpa[10100], mpb[10100];
double ans[20010];
int max(int a,int b){
if(a>b)return a;
return b;
}
int main() {
int n;
scanf("%d",&n);
int maxs = 0;
int maxa = 0, maxb = 0;
for (int i = 1; i <= n; i++) {
int xs, zs;
scanf("%d%d",&zs,&xs);
maxa = max(maxa, zs);
mpa[zs] = double(xs);
}
int m;
scanf("%d",&m);
for (int i = 1; i <= m; i++) {
int xs, zs;
scanf("%d%d",&zs,&xs);
maxb = max(maxb, zs);
mpb[zs] = double(xs);
}int cnt = 0;
for (int i = maxa; i >=0; i--) {
int d =i - maxb;
cnt = max(cnt, d);
if (d < 0)break;
double c = mpa[i]/mpb[maxb];
for (int j = maxb; j >= 0; j--) {
double t = (double)mpb[j] * c;
mpa[(j + d)] -= t;
}
ans[d] = c;
}
int num = 0;
for (int i = 0; i <= cnt; i++)
if (abs(ans[i]) + 0.05 >= 0.1)num++;//四舍五入
printf("%d", num);
if (num == 0) printf(" 0 0.0");
for (int i = cnt; i >= 0; i--)
{
if (abs(ans[i]) + 0.05 >= 0.1)printf(" %d %.1lf", i, ans[i]);
}
printf("\n");
num = 0;
for (int i = 0; i <= maxb-1; i++)
if (abs(mpa[i]) + 0.05 >= 0.1)num++;//四舍五入
printf("%d", num);
if (num == 0) printf(" 0 0.0");
for (int i = maxb-1; i >= 0; i--)
{
if (abs(mpa[i]) + 0.05 >= 0.1)printf(" %d %.1lf", i, mpa[i]);
}
}