【中国大学MOOC】浙江大学——数据结构(PAT)(持续更新ing)


函数题

01-复杂度3 二分查找 (20 分)

本题要求实现二分查找算法。

函数接口定义:

Position BinarySearch( List L, ElementType X );

其中List结构定义如下:

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

L是用户传入的一个线性表,其中ElementType元素可以通过>、==、<进行比较,并且题目保证传入的数据是递增有序的。函数BinarySearch要查找XData中的位置,即数组下标(注意:元素从下标1开始存储)。找到则返回下标,否则返回一个特殊的失败标记NotFound

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;

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

List ReadInput(); /* 裁判实现,细节不表。元素从下标1开始存储 */
Position BinarySearch( List L, ElementType X );

int main()
{
    List L;
    ElementType X;
    Position P;

    L = ReadInput();
    scanf("%d", &X);
    P = BinarySearch( L, X );
    printf("%d\n", P);

    return 0;
}

/* 你的代码将被嵌在这里 */

代码

Position BinarySearch( List L, ElementType X )
{
    ElementType * dataset = L->Data;
    int end = L->Last;
    int start = 0;

    while(start <= end)
    {
        int mid = (start + end)/2;

        if (dataset[mid] == X)
        {
            return mid;
        }
        else if (dataset[mid] < X)
        {
            start = mid + 1;  	// 避免start 和 end 一直相等,陷入死循环
        }
        else // dataset[mid] > X
        {
            end = mid - 1;
        }
    }

    return NotFound;
}
02-线性结构1 两个有序链表序列的合并 (15 分)

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

函数接口定义:

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

代码:

List  Merge(List L1,List L2)
{
    List bupt=(List)malloc(sizeof(struct Node));
    List L=bupt;
    bupt->Next=NULL;
    List P1=L1->Next;
    List P2=L2->Next;
	while(P1&&P2)
   	{
        if( P1->Data<=P2->Data)
        {
            List newnode=(List)malloc(sizeof(struct Node));
            newnode->Data=P1->Data;
            bupt->Next=newnode;
            P1=P1->Next;
            bupt=newnode;
        }
        else
        {
            List newnode=(List)malloc(sizeof(struct Node));
            newnode->Data=P2->Data;
            bupt->Next=newnode;
            P2=P2->Next;  
            bupt=newnode;  
        }
   }
   bupt->Next= P2?P2:P1;
   L1->Next=NULL; 
   L2->Next=NULL;
   return L;
}

编程题

01-复杂度1 最大子列和问题 (20 分)

给定K个整数组成的序列{ N1, N2, …, NK },“连续子列”被定义为{ Ni, Ni+1, …, Nj },其中 1≤ijK。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:

  • 数据1:与样例等价,测试基本正确性;
  • 数据2:102个随机整数;
  • 数据3:103个随机整数;
  • 数据4:104个随机整数;
  • 数据5:105个随机整数;

输入格式:

输入第1行给出正整数K (≤100000);第2行给出K个整数,其间以空格分隔。

输出格式:

在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。

输入样例:

6
-2 11 -4 13 -5 -2

输出样例:

20

代码

#include<iostream>
using namespace std;

int main()
{
    int n,x;
    cin>>n;
    int this_sum = 0 , max_num = 0;
    for(int i=0;i<n;i++)
    {
        cin>>x;
        this_sum += x;
        if(this_sum > max_num) max_num = this_sum;
        else if(this_sum < 0) this_sum = 0;
    }
    cout<<max_num;
    return 0;
}
01-复杂度2 Maximum Subsequence Sum (25 分)

Given a sequence of K integers { N1, N2, …, NK }. A continuous subsequence is defined to be { Ni, Ni+1, …, Nj } where 1≤ijK. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤10000). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:

10
-10 1 2 3 4 -5 -23 3 7 -21

Sample Output:

10 1 4

代码

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <ctime>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long ll;
#define maxn 100005
#define mod 7654321

int main()
{
    int a[maxn];
    int n,maxx=0,fushu=1,ling=0,pos0;
    int start,end;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        if(a[i]>0)
        {
            fushu=0;
            break;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(a[i]==0)
        {
            ling=1;
            pos0=i;
            break;
        }
    }

    if(fushu&&ling==0)
    {
        cout<<0<<" "<<a[1]<<" "<<a[n]<<endl;
    }
    else if(fushu&&ling)
    {
        cout<<0<<" "<<a[pos0]<<" "<<a[pos0]<<endl;
    }
    else
    {
        for(int i=1;i<=n;i++)//左端点
        {
            int sum=0;
            for(int j=i;j<=n;j++)//右端点
            {
                sum+=a[j];//从i到j其实每次就加了一项eg:0~1 0~2....只比钱一个区间的和多加了一项
                if(maxx<sum)
                    maxx=sum,start=i,end=j;
            }
        }
        cout<<maxx<<" "<<a[start]<<" "<<a[end]<<endl;
    }

    return 0;
}
02-线性结构2 一元多项式的乘法与加法运算 (20 分)

设计函数分别求两个一元多项式的乘积与和。

输入格式:

输入分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>
typedef struct Node *PtrToNode;
struct Node{
	int coe;
	int exp;
	PtrToNode Next;
};
typedef PtrToNode List;
List read();//读入线性表
void Print(List L);//遍历线性表
List add(List L1,List L2);
List mul(List L1,List L2);
int main()
{
	List L1,L2,LA,LM;
	//L1,L2就是用户想要输入的链表
	//LA就是用户的一元多项式加法
	//LB就是用户的一元多项式乘法,代码分明
	L1 = read();
	L2 = read();
	LA = add(L1,L2);
	LM = mul(L1,L2);
	Print(LM);
	Print(LA);
	
}
//一共是四个函数要实现
//第一个函数输入 第二个函数 遍历 
//第三个函数 加法 第三个函数乘法
List read()
{
	int n;
	List s = (List)malloc(sizeof(struct Node));//s是最后要甩出去的链表
	s->Next = NULL;//带头结点的链表
	scanf("%d",&n);
	if(n){
		List m = s;
		for(int i=0;i<n;i++){
			List p =(List)malloc(sizeof(struct Node));
			scanf("%d%d",&(p->coe),&(p->exp));
			m->Next = p;
			m = p;
		}
		m->Next = NULL;
	}
	return s;	
}
//第二个函数
void Print(List L){
	List r = L->Next;
	if(r){
		List p = (List)malloc(sizeof(struct Node));
		p = L;
		if(p->Next){
			p = p->Next;
			printf("%d %d",p->coe,p->exp);//题目格式要求
			while(p->Next){
				p = p->Next;
				printf(" %d %d",p->coe,p->exp);
			}
		}
	}else{
		printf("0 0");
	}
	printf("\n");
}
List add(List L1,List L2){
	List pa,pb,pc,L;
	L = (List)malloc(sizeof(struct Node));
	L->Next = NULL;
	pa = L1->Next;
	pb = L2->Next;
	pc = L;
	while(pa && pb)
	{
		if(pa->exp<pb->exp){
			List temp = (List)malloc(sizeof(struct Node));
			temp->Next = NULL;
			temp->coe = pb->coe;
			temp->exp = pb->exp;
			pc->Next = temp;
			pc = temp;
			pb = pb->Next;
		}
		else if(pa->exp == pb->exp){
			int a = pa->coe+pb->coe;
			if(a!=0){
				List temp = (List)malloc(sizeof(struct Node));
				temp->Next = NULL;
				temp->coe = a;
				temp->exp = pa->exp;//当连个指数才能相加时,你指向谁其实都一样
				pc->Next = temp;
				pc = temp;				
			}
			pb=pb->Next;
			pa=pa->Next;
		}else{
			List temp = (List)malloc(sizeof(struct Node));
			temp->Next = NULL;
			temp->coe = pa->coe;
			temp->exp = pa->exp;
			pc->Next = temp;
			pc = temp;
			pa = pa->Next;			
		}
		
	}
	if(pa){
		while(pa){
			List temp = (List)malloc(sizeof(struct Node));
			temp->Next = NULL;
			temp->coe = pa->coe;
			temp->exp = pa->exp;
			pc->Next = temp;
			pc = temp;
			pa = pa->Next;	
		}
	}else{
		while(pb){
			List temp = (List)malloc(sizeof(struct Node));
			temp->Next = NULL;
			temp->coe = pb->coe;
			temp->exp = pb->exp;
			pc->Next = temp;
			pc = temp;
			pb = pb->Next;			
		}
	}
	pc->Next = NULL;
	return L;
}
List mul(List L1,List L2){
	List p1,p2,p3,L,Lm;
	L = (List)malloc(sizeof(struct Node));
	p1 = L1->Next;
	p2 = L2->Next;
	L->Next = NULL;
	if(p1&&p2){
		for(p1=L1->Next;p1;p1=p1->Next){
			Lm = (List)malloc(sizeof(struct Node));
			Lm->Next = NULL;
			p3 = Lm;
			for(p2=L2->Next;p2;p2=p2->Next){
				List p4=(List)malloc(sizeof(struct Node));
				p4->coe = p1->coe*p2->coe;
				p4->exp = p1->exp+p2->exp;
				p3->Next = p4;
				p3=p4;
			}
			p3->Next = NULL;
			L=add(L,Lm);
			free(Lm);
		}
	}
	return L;
}
02-线性结构3 Reversing Linked List (25 分)

Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤105) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

Output Specification:

For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

Sample Output:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>    ///使用到reverse 翻转函数
using namespace std;
 
#define MAXSIZE 1000010   ///最大为五位数的地址
 
struct node    ///使用顺序表存储data和下一地址next
{
   int data;   
   int next;
}node[MAXSIZE];
 
int List[MAXSIZE];   ///存储可以连接上的顺序表
int main()
{
    int First, n, k;  
    cin>>First>>n>>k;   ///输入头地址 和 n,k;
    int Address,Data,Next;
    for(int i=0;i<n;i++)
    {
        cin>>Address>>Data>>Next;
        node[Address].data=Data;
        node[Address].next=Next;
    }
 
    int j=0;  ///j用来存储能够首尾相连的节点数
    int p=First;   ///p指示当前结点
    while(p!=-1)
    {
        List[j++]=p;
        p=node[p].next;
    }
    int i=0;
    while(i+k<=j)   ///每k个节点做一次翻转
    {
        reverse(&List[i],&List[i+k]);
        i=i+k;
    }
    for(i=0;i<j-1;i++)
        printf("%05d %d %05d\n",List[i],node[List[i]].data,List[i+1]);
    printf("%05d %d -1\n",List[i],node[List[i]].data);
    return 0;
}
02-线性结构4 Pop Sequence (25 分)

Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, …, N and pop randomly. You are supposed to tell if a given sequence of numbers is a possible pop sequence of the stack. For example, if M is 5 and N is 7, we can obtain 1, 2, 3, 4, 5, 6, 7 from the stack, but not 3, 2, 1, 7, 5, 6, 4.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 numbers (all no more than 1000): M (the maximum capacity of the stack), N (the length of push sequence), and K (the number of pop sequences to be checked). Then K lines follow, each contains a pop sequence of N numbers. All the numbers in a line are separated by a space.

Output Specification:

For each pop sequence, print in one line “YES” if it is indeed a possible pop sequence of the stack, or “NO” if not.

Sample Input:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

Sample Output:

YES
NO
NO
YES
NO

代码:

#include<stdio.h>
 
int main() 
{
	int N,M,K;
	int i,j,a[1000];
	scanf("%d %d %d",&M,&N,&K);
	for(i=0;i<K;i++){
		for(j=0;j<N;j++)scanf("%d",&a[j]);
		int stack[1000]={0},top=0;//创建一个栈 
		int num=1;
		j=0,stack[0]=num;
		while(j<N){
			if(a[j]<stack[top])break;//比栈顶元素小 
			while(a[j]>stack[top]){  //需要继续压入数据 
				stack[++top]=++num;
			}
			if(top>=M)break; 
			if(a[j]==stack[top]){
				top--;
			}
			if(top<0)stack[++top]=++num;
			j++;
		}
		if(j==N)printf("YES\n");
		else printf("NO\n"); 
	}
	return 0;
}
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小天才才

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值