PAT线性结构_一元多项式求导、按给定步长反转链表、出栈序列存在性判断
2015-06-15 16:51 星星之火✨🔥 阅读(596) 评论(0) 编辑 收藏 举报02-线性结构1. 一元多项式求导 (25)
设计函数求一元多项式的导数。(注:xn(n为整数)的一阶导数为n*xn-1。)
输入格式:以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是0,但是表示为“0 0”。
输入样例:
3 4 -5 2 6 1 -2 0
输出样例:
12 3 -10 1 6 0
最简单的方式是用数组模拟,但是毕竟处在学习数据结构阶段,所以还是写了个链表的,如下:
#include<stdio.h>
#include<malloc.h>
typedef struct Node
{
int coef; // 系数
int exp; // 指数
struct Node * next;
}NODE, *PNODE;
int main(void)
{
int coef, exp;
PNODE pHead, pTail, pTemp;
pHead = (PNODE)malloc(sizeof(NODE)); // 创建头节点
pTail = pHead;
while(scanf("%d%d", &coef, &exp) != EOF)
{
pTemp = (PNODE)malloc(sizeof(NODE));
pTemp->coef = coef;
pTemp->exp = exp; // 注: 因为有尾指针,所以省略了next设为NULL这一步
pTail->next = pTemp;
pTail = pTemp;
}
pTail->next = NULL;
// 扫描、求值并输出
pTemp = pHead->next; // 定位到首元素
if(pTemp->exp == 0) // 首元素指数为零,其求导比较特殊因此单独处理
{
printf("0 0");
}
else
{
while(pTemp)
{
if(pTemp->exp > 0) // 指数为零的项求导直接为零,不进行输出
{
if(pTemp != pHead->next) //如果不是第一个元素输出空格
putchar(' ');
printf("%d %d", pTemp->coef * pTemp->exp, pTemp->exp -1);
pTemp = pTemp->next;
}
else
break;
}
}
// 注:申请内存没有判断是否成功,内存用完了也没释放,懒le:~
return 0;
}
02-线性结构2. 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<stdio.h> // 大数组模拟
#define MAXN 100000
typedef struct Node
{
int address;
int data;
int next;
}NODE, *PNODE;
NODE node[MAXN+10];
void Swap(NODE node[], int, int);
void Swap2(NODE node[], int, int);
void Reverse(NODE node[], int, int);
int main(void)
{
int firstAddress, n, k; // 首地址、节点个数、反转长度
int i, j, address;
scanf("%d%d%d", &firstAddress, &n, &k);
for(i = 1; i <= n; i++)
{
scanf("%d%d%d", &node[i].address, &node[i].data, &node[i].next);
if(node[i].address == firstAddress)
j = i;
}
// 交换第一个元素与应当排在首位的元素,如果多次使用的话应该编写一个函数,传递适当的参数给它完成数据的交换
Swap(node, 1, j);
// 首先根据节点地址信息进行排序
for(i = 2; i <= n; i++)
{
address = node[i-1].next;
if(address == -1)
{
n = i - 1; // 修改n的值达到排除输入数据中无效节点的目的
break;
}
for(j = i; j <= n; j++)
if(address == node[j].address)
{
Swap(node, i, j);
break;
}
}
// printf("n: %d\n", n); // test
Reverse(node, n, k);
for(i = 1; i < n; i++)
printf("%05d %d %05d\n", node[i].address, node[i].data, node[i].next); // 0n表示宽度至少为n位,不足以左边0填充
printf("%05d %d %d\n", node[i].address, node[i].data, node[i].next);
return 0;
}
void Swap(NODE node[], int i, int j)
{
int temp;
temp = node[i].address;
node[i].address = node[j].address;
node[j].address = temp;
temp = node[i].data;
node[i].data = node[j].data;
node[j].data = temp;
temp = node[i].next;
node[i].next = node[j].next;
node[j].next = temp;
}
void Swap2(NODE node[], int i, int j) // 作为反转操作的一个子函数来使用,注意与Swap函数的不同点,即它不关心next变量
{
int temp;
temp = node[i].address;
node[i].address = node[j].address;
node[j].address = temp;
temp = node[i].data;
node[i].data = node[j].data;
node[j].data = temp;
}
void Reverse(NODE node[], int n, int k)
{
int i, j, step;
int totalReverNum = n / k;
for(i = 1; i <= totalReverNum; i++)
{
step = 0;
for(j = 0; j < k/2; j++)
{
Swap2(node, (k*(i-1)+1)+step, k*i-step); // 如果想提速,可以把乘法在调用Swap2之前算出来,但是这样会增加变量的个数,权衡之下如果不超时的话就不做修改了:~
step++;
}
}
//遍历,修改next
for(i = 1; i < n; i++)
{
node[i].next = node[i+1].address;
}
node[i].next = -1;
}
下面给出经典的利用三个指针变量进行反转的思路:
Ptr Reverse(Ptr head, int K) // head是一个无用的头节点
{
cnt = 1;
new = head->next;
old = new->next;
while(cnt < K)
{
tmp = old->next;
old->next = new;
new = old;
old = tmp;
cnt++;
}
head->next->next = old;
return new;
}
02-线性结构3. 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>
#define MAXN 1000
int stack[MAXN+10];
int arr[MAXN+10];
int main(void)
{
int m, n, k, i, j;
int x, y, top; // x模拟进栈序列,y模拟出栈序列,top代表栈顶
scanf("%d%d%d", &m, &n, &k);
for(i = 1; i <= k; i++)
{
for(j = 1; j <= n; j++)
scanf("%d", &arr[j]);
y = 1;
top = 0;
for(x = 1; x <= n; x++) // n个数字逐个入栈
{
stack[++top] = x;
if(top > m)
break;
while(top > 0 && arr[y] == stack[top])
{
y++;
top--;
}
}
if(x <= n || top > 0)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
上面是数组模拟的,下面我写了一个真实版的栈模拟:
#include<stdio.h>
#include<malloc.h>
typedef struct Node
{
int data;
struct Node * next;
}NODE, *PNODE;
typedef struct Stack
{
PNODE pHead;
int sumItem;
}STACK, *PSTACK;
void MakeStack(PSTACK pS);
int IsEmpty(PSTACK pS);
void Push(PSTACK pS, int value);
int Pop(PSTACK pS);
int Peek(PSTACK pS);
int SumItem(PSTACK pS);
void Clear(PSTACK pS);
int arr[1010];
int main(void)
{
int m, n, k, i, j;
int x, y; // x模拟进栈序列,arr[y]模拟出栈序列
STACK S;
scanf("%d%d%d", &m, &n, &k);
MakeStack(&S);
for(i = 1; i <= k; i++)
{
for(j = 1; j <= n; j++)
scanf("%d", &arr[j]);
y = 1;
Clear(&S);
for(x = 1; x <= n; x++) // n个数字逐个入栈
{
Push(&S, x);
if(SumItem(&S) > m)
break;
while(!IsEmpty(&S) && arr[y] == Peek(&S))
{
// printf("haha, I am here.\n"); // test
y++;
Pop(&S);
}
}
if(x <= n || !IsEmpty(&S))
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
void MakeStack(PSTACK pS)
{
pS->pHead = NULL;
pS->sumItem = 0;
}
int IsEmpty(PSTACK pS)
{
if(pS->pHead == NULL)
return 1;
else
return 0;
}
void Push(PSTACK pS, int value)
{
PNODE pTemp;
pTemp = pS->pHead;
pS->pHead = (PNODE)malloc(sizeof(NODE));
pS->pHead->data = value;
pS->pHead->next = pTemp;
pS->sumItem++;
}
int Pop(PSTACK pS) // 调用前需要调用IsEmpty来判断栈是否为空,在主程序中的短路原则体现了这一点,因此Pop函数中省略了判空这一步
{
int value;
PNODE pTemp;
value = pS->pHead->data;
pTemp = pS->pHead;
pS->pHead = pS->pHead->next;
pS->sumItem--;
free(pTemp);
return value;
}
int Peek(PSTACK pS) // 调用前需要调用IsEmpty来判断栈是否为空,没有判空的原因同上
{
return pS->pHead->data;
}
int SumItem(PSTACK pS)
{
return pS->sumItem;
}
void Clear(PSTACK pS)
{
while(!IsEmpty(pS))
Pop(pS);
}
(END_XPJIANG)