郑州轻工业大学2022-2023(2) 数据结构题目集 - ZZULI

6-1 线性表元素的区间删除

6-1 线性表元素的区间删除

分数 20

全屏浏览题目

切换布局

作者 DS课程组

单位 浙江大学

给定一个顺序存储的线性表,请设计一个函数删除所有值大于min而且小于max的元素。删除后表中剩余元素保持顺序存储,并且相对位置不能改变。

函数接口定义:

 
  

List Delete( List L, ElementType minD, ElementType maxD );

其中List结构定义如下:

 
  

typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 保存线性表中最后一个元素在数组中的位置 */ };

L是用户传入的一个线性表,其中ElementType元素可以通过>、==、<进行比较;minDmaxD分别为待删除元素的值域的下、上界。函数Delete应将Data[]中所有值大于minD而且小于maxD的元素删除,同时保证表中剩余元素保持顺序存储,并且相对位置不变,最后返回删除后的表。

裁判测试程序样例:

 
  

#include <stdio.h> #define MAXSIZE 20 typedef int ElementType; typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 保存线性表中最后一个元素的位置 */ }; List ReadInput(); /* 裁判实现,细节不表。元素从下标0开始存储 */ void PrintList( List L ); /* 裁判实现,细节不表 */ List Delete( List L, ElementType minD, ElementType maxD ); int main() { List L; ElementType minD, maxD; int i; L = ReadInput(); scanf("%d %d", &minD, &maxD); L = Delete( L, minD, maxD ); PrintList( L ); return 0; } /* 你的代码将被嵌在这里 */

输入样例:

10
4 -8 2 12 1 5 9 3 3 10
0 4

输出样例:

4 -8 12 5 9 10 

代码长度限制

16 KB

时间限制

200 ms

内存限制

64 MB

代码

List Delete( List L, ElementType minD, ElementType maxD ){
    int endNum = 0;
    int length = L->Last + 1;
    int* remain = (int*)malloc(sizeof(int) * length);
    int j = 0;
    for(int i = 0; i < length; i++){
        if(L->Data[i] <= minD || L->Data[i] >= maxD){ //保留需要删除的区间之外的值
            endNum++;
            remain[j++] = L->Data[i];
        }
    }
    List list = (List)malloc(sizeof(struct LNode));
    memset(list->Data, 0, sizeof(list->Data));
    for(int i = 0; i < endNum; i++){ //用保留的值重新创建一个链表
        list->Data[i] = remain[i];
    }
    list->Last = endNum - 1;
    return list;
}

 6-2 有序表的插入

6-2 有序表的插入【有题解视频】

分数 10

全屏浏览题目

切换布局

作者 CUIT通信DS课程组

单位 成都信息工程大学

设顺序表中的数据元素是按值非递减有序排列的,试编写一算法,将x插入到顺序表的适当位置上,以保持顺序表的有序性。

函数接口定义:

 
  

void ListInsertSort(SqList *L, DataType x);

其中 L 和 x 都是用户传入的参数。 L 表示顺序表, x 是要插入的元素。

裁判测试程序样例:

 
  

#include"stdio.h" #define LISTSIZE 100 typedef int DataType; typedef struct{ DataType items[LISTSIZE]; int length; }SqList; /* 本题要求函数 */ void ListInsertSort(SqList *L, DataType x); int InitList(SqList *L) {/*L为指向顺序表的指针*/ L->length=0; return 1; } int ListLength(SqList L) {/*L为顺序表*/ return L.length; } int ListInsert(SqList *L,int pos,DataType item) {/*L为指向顺序表的指针,pos为插入位置,item为待插入的数据元素*/ int i; if(L->length>=LISTSIZE){ printf("顺序表已满,无法进行插入操作!");return 0;} if(pos<=0 || pos>L->length+1){ printf("插入位置不合法,其取值范围应该是[1,length+1]"); return 0; } for(i=L->length-1; i>=pos-1; i--) /*移动数据元素*/ L->items[i+1]=L->items[i]; L->items[pos-1]=item; /*插入*/ L->length++; /*表长增一*/ return 1; } int TraverseList(SqList L) {/*L为顺序表*/ int i; for(i=0;i<L.length;i++) printf("%d ",L.items[i]); printf("\n"); return 1; } void main() { int i,input,x; SqList L1; //定义顺序表 InitList(&L1); //初始化建空表 for(i=0;;i++) { scanf("%d",&input); if(input==-1)break; ListInsert(&L1, i+1, input); //插入数据 } scanf("%d",&x); ListInsertSort(&L1, x); // 本题要求函数在主函数中的调用 TraverseList(L1); //遍历 } /* 请在这里填写答案 */

输入样例:

在这里给出一组输入。例如:

1 3 6 7 8 9 -1
3

输出样例:

在这里给出相应的输出。例如:

1 3 3 6 7 8 9 

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

void ListInsertSort(SqList *L, DataType x) {
    int insertPoint = -1;
    while (L->items[++insertPoint] <= x && insertPoint < L->length);//寻找插入位置
    ListInsert(L, insertPoint + 1, x);//调用题目给的函数进行插入
}

 6-3 合并两个有序数组

6-3 合并两个有序数组

分数 20

全屏浏览题目

切换布局

作者 李廷元

单位 中国民用航空飞行学院

要求实现一个函数merge,将长度为m的升序数组a和长度为n的升序数组b合并到一个新的数组c,合并后的数组仍然按升序排列。

函数接口定义:

 
  

void printArray(int* arr, int arr_size); /* 打印数组,细节不表 */ void merge(int* a, int m, int* b, int n, int* c); /* 合并a和b为c */

其中a和b是按升序排列的数组,m和n分别为数组a、b的长度;c为合并后的升序数组。

裁判测试程序样例:

 
  

#include <stdio.h> #include <stdlib.h> void printArray(int* arr, int arr_size); /* 打印数组,细节不表 */ void merge(int* a, int m, int* b, int n, int* c); /* 合并a和b为c */ int main(int argc, char const *argv[]) { int m, n, i; int *a, *b, *c; scanf("%d", &m); a = (int*)malloc(m * sizeof(int)); for (i = 0; i < m; i++) { scanf("%d", &a[i]); } scanf("%d", &n); b = (int*)malloc(n * sizeof(int)); for (i = 0; i < n; i++) { scanf("%d", &b[i]); } c = (int*)malloc((m + n) * sizeof(int)); merge(a, m, b, n, c); printArray(c, m + n); return 0; } /* 请在这里填写答案 */

输入样例:

输入包含两行。
第一行为有序数组a,其中第一个数为数组a的长度m,紧接着m个整数。
第二行为有序数组b,其中第一个数为数组b的长度n,紧接着n个整数。

7 1 2 14 25 33 73 84
11 5 6 17 27 68 68 74 79 80 85 87

输出样例:

输出为合并后按升序排列的数组。

1 2 5 6 14 17 25 27 33 68 68 73 74 79 80 84 85 87

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

void merge(int* a, int m, int* b, int n, int* c){
    int j = 0, k = 0;
    for(int i = 0; i < m; k++){
        if(j < n)//以有序放完a为前提,尽量放符合条件的b
            a[i] < b[j] ? (c[k] = a[i++]) : (c[k] = b[j++]);
        else
            c[k] = a[i++];
    }
    for(; j < n; j++){//如果b有剩余
        c[k++] = b[j];
    }
}

 6-4 顺序表操作集

6-4 顺序表操作集

分数 20

全屏浏览题目

切换布局

作者 陈越

单位 浙江大学

本题要求实现顺序表的操作集。

函数接口定义:

 
  

List MakeEmpty(); Position Find( List L, ElementType X ); bool Insert( List L, ElementType X, Position P ); bool Delete( List L, Position P );

其中List结构定义如下:

 
  

typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 保存线性表中最后一个元素的位置 */ };

各个操作函数的定义为:

List MakeEmpty():创建并返回一个空的线性表;

Position Find( List L, ElementType X ):返回线性表中X的位置。若找不到则返回ERROR;

bool Insert( List L, ElementType X, Position P ):将X插入在位置P并返回true。若空间已满,则打印“FULL”并返回false;如果参数P指向非法位置,则打印“ILLEGAL POSITION”并返回false;

bool Delete( List L, Position P ):将位置P的元素删除并返回true。若参数P指向非法位置,则打印“POSITION P EMPTY”(其中P是参数值)并返回false。

裁判测试程序样例:

 
  

#include <stdio.h> #include <stdlib.h> #define MAXSIZE 5 #define ERROR -1 typedef enum {false, true} bool; typedef int ElementType; typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 保存线性表中最后一个元素的位置 */ }; 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; L = MakeEmpty(); scanf("%d", &N); while ( N-- ) { scanf("%d", &X); if ( Insert(L, X, 0)==false ) printf(" Insertion Error: %d is not in.\n", X); } 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 printf("%d is at position %d.\n", X, P); } scanf("%d", &N); while ( N-- ) { scanf("%d", &P); if ( Delete(L, P)==false ) printf(" Deletion Error.\n"); if ( Insert(L, 0, P)==false ) printf(" Insertion Error: 0 is not in.\n"); } return 0; } /* 你的代码将被嵌在这里 */

输入样例:

6
1 2 3 4 5 6
3
6 5 1
2
-1 6

输出样例:

FULL Insertion Error: 6 is not in.
Finding Error: 6 is not in.
5 is at position 0.
1 is at position 4.
POSITION -1 EMPTY Deletion Error.
FULL Insertion Error: 0 is not in.
POSITION 6 EMPTY Deletion Error.
FULL Insertion Error: 0 is not in.

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

List MakeEmpty(){//创建空表
    List list = (List) malloc(sizeof(struct LNode));
    memset(list->Data, 0, sizeof(list->Data));//初始化数据域
    list->Last = -1;//初始化尾指针
    return list;
}
Position Find( List L, ElementType X ){
    int pos = -1;
    while(++pos <= L->Last){//遍历表
        if(L->Data[pos] == X)//找到数据
            return pos;
    }
    return ERROR;
}
bool Insert( List L, ElementType X, Position P ){
    if(L->Last >= MAXSIZE - 1){//表已满
        printf("FULL");
        return false;
    }
    if(P < 0 || P > L->Last + 1){//越界
        printf("ILLEGAL POSITION");
        return false;
    }
    for(int i = L->Last; i >= P; i--){//移动元素
        L->Data[i + 1] = L->Data[i];
    }
    L->Data[P] = X;//插入
    L->Last++;//更新属性
    return true;
}
bool Delete( List L, Position P ){
    if(P < 0 || P > L->Last){//越界
        printf("POSITION %d EMPTY", P);
        return false;
    }
    for(int i = P; i < L->Last; i++){//移动元素
        L->Data[i] = L->Data[i + 1];
    }
    L->Last--;//更新属性
    return true;
}

6-5 递增的整数序列链表的插入

6-5 递增的整数序列链表的插入

分数 15

全屏浏览题目

切换布局

作者 DS课程组

单位 浙江大学

本题要求实现一个函数,在递增的整数序列链表(带头结点)中插入一个新整数,并保持该序列的有序性。

函数接口定义:

 
  

List Insert( List L, ElementType X );

其中List结构定义如下:

 
  

typedef struct Node *PtrToNode; struct Node { ElementType Data; /* 存储结点数据 */ PtrToNode Next; /* 指向下一个结点的指针 */ }; typedef PtrToNode List; /* 定义单链表类型 */

L是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Insert要将X插入L,并保持该序列的有序性,返回插入后的链表头指针。

裁判测试程序样例:

 
  

#include <stdio.h> #include <stdlib.h> typedef int ElementType; typedef struct Node *PtrToNode; struct Node { ElementType Data; PtrToNode Next; }; typedef PtrToNode List; List Read(); /* 细节在此不表 */ void Print( List L ); /* 细节在此不表 */ List Insert( List L, ElementType X ); int main() { List L; ElementType X; L = Read(); scanf("%d", &X); L = Insert(L, X); Print(L); return 0; } /* 你的代码将被嵌在这里 */

输入样例:

5
1 2 4 5 6
3

输出样例:

1 2 3 4 5 6 

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

List Insert( List L, ElementType X ){
    PtrToNode p = L;
    while(p->Next && (p->Next->Data < X)){ //寻找插入位置
        p = p->Next;
    }
    PtrToNode x = (PtrToNode)malloc(sizeof(struct Node));
    //插入
    x->Data = X;
    x->Next = p->Next;
    p->Next = x;
    return L;
}

6-6 删除单链表偶数节点

6-6 删除单链表偶数节点

分数 20

全屏浏览题目

切换布局

作者 C课程组

单位 浙江大学

本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中偶数值的结点删除。链表结点定义如下:

struct ListNode {
    int data;
    struct ListNode *next;
};

函数接口定义:

 
  

struct ListNode *createlist(); struct ListNode *deleteeven( struct ListNode *head );

函数createlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。

函数deleteeven将单链表head中偶数值的结点删除,返回结果链表的头指针。

裁判测试程序样例:

 
  

#include <stdio.h> #include <stdlib.h> struct ListNode { int data; struct ListNode *next; }; struct ListNode *createlist(); struct ListNode *deleteeven( struct ListNode *head ); void printlist( struct ListNode *head ) { struct ListNode *p = head; while (p) { printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { struct ListNode *head; head = createlist(); head = deleteeven(head); printlist(head); return 0; } /* 你的代码将被嵌在这里 */

输入样例:

1 2 2 3 4 5 6 7 -1

输出样例:

1 3 5 7 

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

struct ListNode *createlist(){
    int n;
    struct ListNode * head = NULL;
    scanf("%d", &n);
    if(n != -1){//题目要求
        //先独立创建一个节点,在使用while创建其他节点,防止多分配内存
        head = (struct ListNode*) malloc(sizeof(struct ListNode));//创建头指针
        struct ListNode * body = head;
        body->data = n;
        body->next = NULL;
        while(scanf("%d", &n), n != -1){//继续读入
            //继续创建
            body->next = (struct ListNode*) malloc(sizeof(struct ListNode));
            body = body->next;
            body->data = n;
            body->next = NULL;
        }
    }
    return head;
}
struct ListNode *deleteeven( struct ListNode *head ){
    while(head && !(head->data % 2)){//先删除从开头便存在并且连续出现的偶数节点
        struct ListNode * p = head;
        head = head->next;
        free(p);
    }
    //第一个while过后,链表开头便不是偶数节点,方便继续删除
    struct ListNode * body = head;
    while(body && body->next){//再删除剩余的偶数节点
        if(!(body->next->data % 2)){
            struct ListNode * p = body->next;
            body->next = body->next->next;
            free(p);
        }else{
            body = body->next;
        }
    }
    return head;
}

6-7 逆序数据建立链表

6-7 逆序数据建立链表

分数 20

全屏浏览题目

切换布局

作者 C课程组

单位 浙江大学

本题要求实现一个函数,按输入数据的逆序建立一个链表。

函数接口定义:

 
  

struct ListNode *createlist();

函数createlist利用scanf从输入中获取一系列正整数,当读到−1时表示输入结束。按输入数据的逆序建立一个链表,并返回链表头指针。链表节点结构定义如下:

 
  

struct ListNode { int data; struct ListNode *next; };

裁判测试程序样例:

 
  

#include <stdio.h> #include <stdlib.h> struct ListNode { int data; struct ListNode *next; }; struct ListNode *createlist(); int main() { struct ListNode *p, *head = NULL; head = createlist(); for ( p = head; p != NULL; p = p->next ) printf("%d ", p->data); printf("\n"); return 0; } /* 你的代码将被嵌在这里 */

输入样例:

1 2 3 4 5 6 7 -1

输出样例:

7 6 5 4 3 2 1 

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

//头插,其他的和上一题的创建道理一样
struct ListNode *createlist(){
    int n;
    struct ListNode * head = NULL;
    scanf("%d", &n);
    if(n != -1){
        head = (struct ListNode*) malloc(sizeof(struct ListNode));
        head->data = n;
        head->next = NULL;
        while(scanf("%d", &n), n != -1){
            struct ListNode* p = (struct ListNode*) malloc(sizeof(struct ListNode));;
            p->data = n;
            p->next = head;//头插
            head = p;//更新头
        }
    }
    return head;
}

6-8 求链表的倒数第m个元素

6-8 求链表的倒数第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 

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

/*
* 思路:
* 使用两个指针依次开始遍历链表,让两个指针产生长为m的区间差
* 当第一个指针遍历到链表尾时,第二个指针恰好在倒数m处。:
* 若有链表:1->2->3->4->5->6,m = 3,则:
*               p2↓       p1↓
* 1 -> 2 -> 3 -> 4 -> 5 -> 6
*                |----3----|
* */
ElementType Find( List L, int m ){
    PtrToNode p = L;
    int i = 0;
    while((L = L->Next)){
        if(++i >= m){//产生区间
            p = p->Next;
        }
    }
    if(i < m){//没有倒数第m
        return ERROR;
    }
    return p->Data;
}

6-9 两个有序链表序列的合并

6-9 两个有序链表序列的合并

分数 15

全屏浏览题目

切换布局

作者 DS课程组

单位 浙江大学

本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个非递减的整数序列。

函数接口定义:

 
  

List Merge( List L1, List L2 );

其中List结构定义如下:

 
  

typedef struct Node *PtrToNode; struct Node { ElementType Data; /* 存储结点数据 */ PtrToNode Next; /* 指向下一个结点的指针 */ }; typedef PtrToNode List; /* 定义单链表类型 */

L1L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1L2合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。

裁判测试程序样例:

 
  

#include <stdio.h> #include <stdlib.h> typedef int ElementType; typedef struct Node *PtrToNode; struct Node { ElementType Data; PtrToNode Next; }; typedef PtrToNode List; List Read(); /* 细节在此不表 */ void Print( List L ); /* 细节在此不表;空链表将输出NULL */ List Merge( List L1, List L2 ); int main() { List L1, L2, L; L1 = Read(); L2 = Read(); L = Merge(L1, L2); Print(L); Print(L1); Print(L2); return 0; } /* 你的代码将被嵌在这里 */

输入样例:

3
1 3 5
5
2 4 6 8 10

输出样例:

1 2 3 4 5 6 8 10 
NULL
NULL

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

List Merge( List L1, List L2 ){
    List ans = (List) malloc((sizeof(struct Node)));
    List body1 = L1->Next, body2 = L2->Next;
    List head = ans;
    //任意一个链表的数据判断完就停
    while(body1 && body2){
        if(body1->Data < body2->Data){
            ans->Next = body1;
            body1 = body1->Next;
        }else{
            ans->Next = body2;
            body2 = body2->Next;
        }
        ans = ans->Next;
    }
    //剩下没判断的数据必然相对于新链表尾有序,直接接上即可
    body1 ? (ans->Next = body1) : (ans->Next = body2);
    //题目要求,合并后原链表头将失去访问权限
    L1->Next = NULL;
    L2->Next = NULL;
    return head;
}

7-1 一元多项式的乘法与加法运算

7-1 一元多项式的乘法与加法运算

分数 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

代码长度限制

16 KB

时间限制

200 ms

内存限制

64 MB

代码


#include <stdio.h>
#include <malloc.h>

//运算单元,bottom底数,top指数
typedef struct unit{
    int bottom;
    int top;
}unit;

//多项式,fml为运算单元数组,length为运算单元个数
typedef struct formula{
    unit* fml;
    int length;
}formula;

//运算单元相加函数
unit add(const unit a, const unit b){
    unit c = {a.bottom + b.bottom, a.top };
    if(!c.bottom)
        c.top = 0;
    return c;
}

//运算单元相乘函数
unit mul(const unit a, const unit b){
    unit c = {a.bottom * b.bottom, a.top + b.top};
    if(!c.bottom)
        c.top = 0;
    return c;
}

//排序规则,给qsort函数(stdlib.h中)用的
int sortRule(const void* a, const void * b){
    unit* c = (unit*)a;
    unit* d = (unit*)b;
    return d->top - c->top;
}

//多项式合并相同指数的运算单元的函数
formula* mergeCommon(const formula* f){
    if(f->length == 1){//多项式只有一个运算单元,不用合并直接返回
        return (formula*)f;
    }
    formula* f1 = (formula*) malloc(sizeof(formula));
    f1->fml = (unit*) malloc(sizeof(unit) * f->length);
    f1->length = 1;
    f1->fml[0] = f->fml[0];
    int k = 0;
    //过第一遍筛
    for(int i = 0, j = 1; j < f->length;){
        if(f->fml[j].bottom != 0){
            if(f->fml[i].top == f->fml[j].top){//指数相同,合并
                f1->fml[k] = add(f->fml[i], f->fml[j]);
            }else{//跳到未合并的位置,等待接收下一组运算单元的合并
                i = j;
                f1->fml[++k] = f->fml[i];//未遇到该指数的运算单元,添加入结果多项式
                f1->length++;
            }
        }
        j++;
    }
    k = 0;
    formula* f2 = (formula*) malloc(sizeof(formula));
    f2->fml = (unit*) malloc(sizeof(unit) * f1->length);
    f2->length = 0;
    //把得到的结果多项式再过一遍筛,筛除合并中出现的0
    for(int i = 0; i < f1->length; i++){
        if(!f1->fml[i].bottom)//如果底数为0
            continue;
        f2->fml[k++] = f1->fml[i];
        f2->length++;
    }
    free(f1);
    //若全为0,则至少保留一个
    if(!f2->length){
        f2->fml[0].top = 0;
        f2->fml[0].bottom = 0;
        f2->length = 1;
    }
    return f2;
}

//多项式相乘函数
formula* mulFormula(const formula* a, const formula* b){
    formula* f = (formula*) malloc(sizeof(formula));
    f->fml = (unit*) malloc(sizeof(unit) * a->length * b->length);
    f->length = a->length * b->length;
    int k = 0;
    //暴力运算,不管系数合并,先算出来再说。(其实效率很好,下面的加也一样,qsort似乎是双轴,极快)
    for(int i = 0; i < a->length; i++){
        for(int j = 0; j < b->length; j++){
            f->fml[k++] = mul(a->fml[i], b->fml[j]);
        }
    }
    //如果乘完只有一项,不用合并直接返回
    if(a->length == b->length && b->length == 1){
        return f;
    }
    //按指数从大到小排序,题目要求也方便合并
    qsort(f->fml, a->length * b->length, sizeof(unit), sortRule);
    //合并相同指数的运算单元并返回合并后的多项式
    return mergeCommon(f);
}

//多项式相加函数
formula* addFormula(const formula* a, const formula* b){
    formula* f = (formula*) malloc(sizeof(formula));
    f->fml = (unit*) malloc(sizeof(unit) * (a->length + b->length));
    f->length = a->length + b->length;
    //同样暴力,把俩多项式直接连成一个,不管合并
    for(int i = 0; i < f->length; i++){
        if(i < a->length)
            f->fml[i] = a->fml[i];
        else
            f->fml[i] = b->fml[i - a->length];
    }
    //同理
    qsort(f->fml, a->length + b->length, sizeof(unit), sortRule);
    return mergeCommon(f);
}

//输出函数
void printFormula(formula* f){
    for(int i = 0; i < f->length; i++){
        printf("%d %d", f->fml[i].bottom, f->fml[i].top);
        if(i < f->length - 1)
            printf(" ");
    }
    printf("\n");
}

int main(){
    int n;
    scanf("%d", &n);

    //创建多项式1
    formula* f1 = (formula*) malloc(sizeof(formula));
    f1->fml = (unit*)malloc(sizeof(unit) * n);
    for(int i = 0; i < n; i++){
        scanf("%d %d", &f1->fml[i].bottom, &f1->fml[i].top);
    }
    f1->length = n;
    scanf("%d", &n);

    //创建多项式2
    formula* f2 = (formula*) malloc(sizeof(formula));
    f2->fml = (unit*)malloc(sizeof(unit) * n);
    for(int i = 0; i < n; i++){
        scanf("%d %d", &f2->fml[i].bottom, &f2->fml[i].top);
    }
    f2->length = n;

    //运算
    printFormula(mulFormula(f1,f2));
    printFormula(addFormula(f1,f2));
}

7-2 符号配对

7-2 符号配对

分数 20

全屏浏览题目

切换布局

作者 DS课程组

单位 浙江大学

请编写程序检查C语言源程序中下列符号是否配对:/**/()[]{ }

输入格式:

输入为一个C语言源程序。当读到某一行中只有一个句点.和一个回车的时候,标志着输入结束。程序中需要检查配对的符号不超过100个。

输出格式:

首先,如果所有符号配对正确,则在第一行中输出YES,否则输出NO。然后在第二行中指出第一个不配对的符号:如果缺少左符号,则输出?-右符号;如果缺少右符号,则输出左符号-?

输入样例1:

void test()
{
    int i, A[10];
    for (i=0; i<10; i++) { /*/
        A[i] = i;
}
.

输出样例1:

NO
/*-?

输入样例2:

void test()
{
    int i, A[10];
    for (i=0; i<10; i++) /**/
        A[i] = i;
}]
.

输出样例2:

NO
?-]

输入样例3:

void test()
{
    int i
    double A[10];
    for (i=0; i<10; i++) /**/
        A[i] = 0.1*i;
}
.

输出样例3:

YES

鸣谢用户 王渊博 补充数据!

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

/*
*  思路:使用栈对括号进行消消乐,最后没消完或中途出现不可消即为配对失败
*/

#include <malloc.h>
#include <string.h>
#include <stdio.h>

//使用枚举创建布尔型变量,方便写代码(也可以不创建,直接0,1,一样)
typedef enum bool{true = 1, false = 0}bool;

//栈
typedef struct stack{
    char* dataBase;
    char top;
    int size;
    int capacity;
}stack;

//创建栈函数
stack getStack(int capacity){
    stack s;
    s.dataBase = (char*) malloc(sizeof(char) * capacity);
    memset(s.dataBase, 0, sizeof(char));
    s.capacity = capacity;
    s.size = 0;
    s.top = '\0';
    return s;
}

//向栈中添加数据
void push(stack* s, char data){
    if(s->size >= s->capacity){//如果容量不够,扩容
        s->capacity *= 2;
        s->dataBase = realloc(s->dataBase, s->capacity);
    }
    s->dataBase[s->size] = data;
    s->top = data;
    s->size++;
}

//弹出栈顶数据
char pop(stack* s){
    if(!s->size){
        return '\0';
    }
    char ans = s->dataBase[s->top];
    s->size--;
    s->dataBase[s->size] = '\0';
    if(s->size)
        s->top = s->dataBase[s->size - 1];
    else
        s->top = '\0';
    return ans;
}

//判断栈是否为空
bool isEmpty(stack* s){
    return s->size == 0 ? true : false;
}

int main(){
    stack s = getStack(100);
    char c, defAns; // defAns 第一个未配对的符号
    //isEnd 用于判断是否结束; right 用于判断是否有未配对的括号
    //isL 判断是否是/**/的左侧符号‘/*’; isR 判断是否是/**/的右侧符号‘*/’
    bool isEnd = false, right = true, isL = false, isR = false;
    while((c = (char)getchar())){
        //判断是否结束
        if(isEnd){
            if(c == '\n')
                break;
            else
                isEnd = false;
        }
        if(c == '.')
            isEnd = true;

        //是否有不配对的括号,如果有则不进行下方的判断,读完输入就进行下一步
        if(right){
            //如果上一个符号是‘/’并且这个符号是*。下面的判断类同
            if(c == '*' && isL){
                push(&s, '<');//把‘/*’看做<压入栈,方便消消乐,也可以用其他符号,看自己喜欢
                isL = false;
            }
            else if(c == '*')
                isR = true;
            else if(c == '/' && isR){
                if(isEmpty(&s) || s.top != '<'){//如果栈是空的或者栈顶的符号无法与之配对
                    right = false;//符号配对失败
                    defAns = s.top;//记录未能配对的符号
                }else if(s.top == '<'){
                    pop(&s);
                    isR = false;
                }
            }
            //下方的比较类同
            else if(c == '/')
                isL = true;
            else if(c == '{' || c == '[' || c == '(')
                push(&s, c);
            else if(c == '}' || c == ']' || c == ')'){
                if(isEmpty(&s)){
                    right = false;
                    defAns = c;
                }else{
                    bool flag = false;
                    switch(c){
                        case '}':
                            if(s.top == '{'){
                                pop(&s);
                            }else flag = true; break;
                        case ']':
                            if(s.top == '['){
                                pop(&s);
                            }else flag = true; break;
                        case ')':
                            if(s.top == '('){
                                pop(&s);
                            }else flag = true; break;
                        default:break;
                    }
                    if(flag){
                        right = false;
                        if(isEmpty(&s))
                            defAns = c;
                        else
                            defAns = s.top;
                    }
                }
            }
        }
    }
    if(isEmpty(&s) && right){
        printf("YES");
    }else{//按要求输出即可
        printf("NO\n");
        if(defAns == '}' || defAns == ']' || defAns == ')'){
            printf("?-%c", defAns);
        }else if(defAns == '{' || defAns == '[' || defAns == '('){
            printf("%c-?", defAns);
        }else{
            if(defAns == '<')
                printf("/*-?");
            else
                printf("?-*/");
        }
    }
}

7-3 银行业务队列简单模拟

7-3 银行业务队列简单模拟

分数 25

全屏浏览题目

切换布局

作者 DS课程组

单位 浙江大学

设某银行有A、B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 —— 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客。给定到达银行的顾客序列,请按业务完成的顺序输出顾客序列。假定不考虑顾客先后到达的时间间隔,并且当不同窗口同时处理完2个顾客时,A窗口顾客优先输出。

输入格式:

输入为一行正整数,其中第1个数字N(≤1000)为顾客总数,后面跟着N位顾客的编号。编号为奇数的顾客需要到A窗口办理业务,为偶数的顾客则去B窗口。数字间以空格分隔。

输出格式:

按业务处理完成的顺序输出顾客的编号。数字间以空格分隔,但最后一个编号后不能有多余的空格。

输入样例:

8 2 1 3 9 4 11 13 15

输出样例:

1 3 2 9 11 4 13 15

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

代码

//题目意思很明显,让练队列

#include <stdio.h>
#include <malloc.h>

//大多数构造思路与前几题一样,不过多赘述
typedef enum bool{true = 1, false = 0}bool;

typedef struct qDataBase{//数据域
    int coNum;
    struct qDataBase* next;
}qDataBase, head, tail;

typedef struct queue{//队列
    double speed;//队列效率,,这个好像没用上
    int size;
    head* hd;
    tail* tl;
}queue;

//数据入队
void enq(queue* q, int coNum){
    qDataBase* dataBase = (qDataBase*)malloc(sizeof(qDataBase));
    dataBase->coNum = coNum;
    q->tl->next = dataBase;
    q->tl = q->tl->next;
    q->tl->next = NULL;
    q->size++;
}

//数据出队
int deq(queue* q){
    if(q->size == 1){//如果队中只剩1个元素,调整尾指针防止尾指针丢失
        q->tl = q->hd;
    }
    qDataBase* t = q->hd->next;
    int coNum = q->hd->next->coNum;
    q->hd->next = q->hd->next->next;
    free(t);
    q->size--;
    return coNum;
}

//获得队首元素
int top(queue* q){
    return q->hd->next->coNum;
}

//判断队是否为空
int isEmpty(queue* q){
    return q->size == 0;
}

//创建队列,type是A队或B队(其实后来想想没啥用)
queue* getQueue(int type){
    queue* tar = (queue*)malloc(sizeof(queue));
    qDataBase* dataBase = (qDataBase*)malloc(sizeof(qDataBase));
    tar->hd = dataBase;
    tar->tl = dataBase;
    tar->size = 0;
    if(!type)
        tar->speed = 2;
    else
        tar->speed = 1;
    return tar;
}

int main(){
    int number, coNum;
    queue* qA = getQueue(0);
    queue* qB = getQueue(1);
    scanf("%d", &coNum);

    //给两个队列添加元素
    while(coNum--){
        scanf("%d", &number);
        if(number % 2)
            enq(qA, number);
        else
            enq(qB, number);
    }
    //timer % 1 == 0 A出(不用算),% 2 == 0 B出
    int timer = 1;
    bool isFirst = true;

    //以A队列为基准,A队出俩B队出1个
    while(!isEmpty(qA)){
        if(isFirst)//为了不多输出空格
            printf("%d", deq(qA));
        else
            printf(" %d", deq(qA));
        if(!timer && !isEmpty(qB))//符合时间且B队不空的话
            printf(" %d", deq(qB));
        timer++;
        timer %= 2;
        isFirst = false;
    }
    //若B队在A队出完后还有剩余,则按队中顺序输出
    while(!isEmpty(qB)){
        if(isFirst)
            printf("%d", deq(qB));
        else
            printf(" %d", deq(qB));
        isFirst = false;
    }
}

猜你喜欢

转载自blog.csdn.net/bairimeng16/article/details/129389016