编程作业实战:
1. 两个有序链表序列的合并 这是一道C语言函数填空题,训练最基本的链表操作。如果会用C编程的话,一定要做;
2. 一元多项式的乘法与加法运算 在“小白专场”里,我们会详细讨论C语言实现的方法。对于不会C语言而不能做第1题的同学,本题一定要做;
3. Reversing Linked List 根据某大公司笔试题改编的2014年春季PAT真题,不难,可以尝试;
4. Pop Sequence 是2013年PAT春季考试真题,考察队堆栈的基本概念的掌握,应可以一试。
01.两个有序链表序列的合并
List Merge(List L1, List L2)
{
List P, prear, temp;
P = (List)malloc(sizeof(struct Node));
P->Next = NULL;
prear = P; //链表的末尾
while (L1->Next && L2->Next)
{
if (L1->Next->Data < L2->Next->Data) //若L1数据>L2数据,将该节点连接到结果链表P上,并使L1继续指向该节点的下一节点
{
temp = L1->Next;
L1->Next = temp->Next;
prear->Next = temp;
prear = temp;
}
else if (L1->Next->Data > L2->Next->Data) //若L1数据<L2数据,情况同上,对L2进行操作。
{
temp = L2->Next;
L2->Next = temp->Next;
prear->Next = temp;
prear = temp;
}
else //若L1数据=L2数据,同时对L1和L2进行操作
{
temp = L1->Next;
L1->Next = temp->Next;
prear->Next = temp;
prear = temp;
temp = L2->Next;
L2->Next = temp->Next;
prear->Next = temp;
prear = temp;
}
}
//将L1或L2的剩余部分全部连接到结果末尾
while (L1->Next)
{
temp = L1->Next;
L1->Next = temp->Next;
prear->Next = temp;
prear = temp;
}
while (L2->Next)
{
temp = L2->Next;
L2->Next = temp->Next;
prear->Next = temp;
prear = temp;
}
return P;
}
02.一元多项式的乘法与加法运算
//设计函数分别求两个一元多项式的乘积与和
//已知两个多项式:(1) 3x4 - 5x2 + 6x - 2,(2) 5x20 - 7x4 + 3x;
//多项式和:5x20 - 4x4- 5x2 + 9x - 2
//多项式乘积:15x24-25x22+30x21-10x20-21x8+35x6-33x5+14x4-15x3+18x2-6x
/*设计思路*/
// 1多项式表示:采用链表进行设计,每个节点包含:系数值coef,指数值expon,下一节点指针
// 2程序框架:读入多项式1和2,加法运算并输出,乘法运算并输出
// 3读入多项式:创建新节点,存入信息,并连接到已有节点后,返回头节点指针。这里创建的是不带头节点的线性表。
// 4两个多项式相加:创建结果头节点,依次判断两个多项式指数是否相同。输入和输出均为不带头结点的线性表,
// 若相同则相加结果不为零时创建节点连接到已有多项式后,若不同将高次项连接到结果多项式,继续比较,
// 当有一多项式链表指向空时停止比较,将零一多项式剩余部分连接到结果多项式后,并返回结果多项式链表的头节点指针。
// 5两个多项式的乘法1:将P1的每一项与P2相乘,并加入结果多项式中;
// 对于P1一项与P2相乘的每一步,要先申请空间存入相乘结果,并将结果与输出结果P相加,再释放掉P2的空间。
// 6两个多项式的乘法2:逐项插入,将P1第i项与P2第j项相乘,并插入到结果多项式。对于初始结果多项式,可由P1第1项与P2相乘得到。
// 插入时,需要考虑结果多项式是否为空;若不为空,需要判断插入位置,末尾,中间或前面,注意释放空间;
// 若插入中间,需要判断是否存在指数相等的项;若存在指数相等的项,需要判断是否会导致该项系数为零
#include <stdio.h>
#include <stdlib.h>
typedef struct PolyNode *Polynomial;
struct PolyNode
{
int coef; //系数
int expon; //指数
struct PolyNode *link; //指向下一个节点的指针
};
Polynomial PolyRead(); //读入多项式
Polynomial Mult1(Polynomial P1, Polynomial P2); //乘法1实现
Polynomial Mult2(Polynomial P1, Polynomial P2); //乘法2实现
Polynomial PolyAdd(Polynomial P1, Polynomial P2); //加法实现
void PrintPoly(Polynomial P); //显示多项式
void Attach(int coef, int expon, Polynomial *prear); //连接
int compare(int e1, int e2); //比较
Polynomial CopyPoly(Polynomial P1); //复制多项式
void InsertNode(int coef, int expon, Polynomial *prear); //将结果项插入到结果多项式合适位置
int main(void)
{
Polynomial P1, P2, PP2, PS;
P1 = PolyRead();
P2 = PolyRead();
if(P1==NULL)
{
printf("0 0\n");
PrintPoly(P2);
return 0;
}
else if(P2==NULL)
{
printf("0 0\n");
PrintPoly(P1);
return 0;
}
// printf("乘法1>>>\n");
// PP1 = Mult1(P1, P2); //按照方法1相乘的结果
// printf("乘法2>>>\n");
PP2 = Mult2(P1, P2); //按照方法2相乘的结果
// printf("运算结果>>>\n");
// printf("乘法一运算结果:");
// PrintPoly(PP1);
// printf("乘法二运算结果:");
PrintPoly(PP2);
PS = PolyAdd(P1, P2);
// printf("加法运算结果:");
PrintPoly(PS);
// while (1);
return 0;
}
Polynomial PolyRead()
{
int N, c, e;
Polynomial rear, temp, P;
P = (Polynomial)malloc(sizeof(struct PolyNode));
rear = P;
scanf("%d", &N);
if (N == 0)
{
P->link = NULL;
}
else
while (N--)
{
scanf("%d %d", &c, &e);
Attach(c, e, &rear);
// temp = (Polynomial)malloc(sizeof(struct PolyNode));
// temp->expon = e;
// temp->coef = c;
// temp->link = NULL;
// PP->link = temp;
// PP = temp;
}
temp = P;
P = P->link;
free(temp);
//这里最好输出一下,进行一下检查
// printf("输入多项式:");
// PrintPoly(P);
return P;
}
Polynomial PolyAdd(Polynomial P1, Polynomial P2)
{
Polynomial front, rear, temp;
int sum;
rear = (Polynomial)malloc(sizeof(struct PolyNode)); //定义了一个临时空节点,作为结果多项式的表头
front = rear;
while (P1 && P2) //判断指针是否为空指针,空指针表示多项式结束
{
switch (compare(P1->expon, P2->expon))
{
case 1: // P1中的数据项指数大
Attach(P1->coef, P1->expon, &rear);
P1 = P1->link;
break;
case -1: // P2中的数据项指数大
Attach(P2->coef, P2->expon, &rear);
P2 = P2->link;
break;
case 0: //数据项指相同
sum = P1->coef + P2->coef;
if (sum) //判断系数和是否为零
Attach(sum, P1->expon, &rear);
P1 = P1->link;
P2 = P2->link;
break;
}
}
/*将未处理完的另一个多项式的所有节点依次连接到结果多项式中*/
for (; P1; P1 = P1->link)
Attach(P1->coef, P1->expon, &rear);
for (; P2; P2 = P2->link)
Attach(P2->coef, P2->expon, &rear);
rear->link = NULL;
temp = front;
front = front->link;
free(temp); //释放空白头节点的空间
return front;
}
void Attach(int coef, int expon, Polynomial *prear)
{ //这里prear是一个指针变量,传递的是PolyAdd函数中结果多项式尾节点指针变量rear的地址
//函数功能:将新节点添加到(*prear)节点后
Polynomial P;
P = (Polynomial)malloc(sizeof(struct PolyNode)); //创建新节点用于存储结果的系数和指数值,函数结束该内存不会被回收。
P->coef = coef;
P->expon = expon;
P->link = NULL;
(*prear)->link = P;
*prear = P; //使尾节点指针变量指向新节点
}
int compare(int e1, int e2)
{
if (e1 == e2)
return 0;
if (e1 > e2)
return 1;
if (e1 < e2)
return -1;
}
// Polynomial Mult1(Polynomial P1, Polynomial P2)
// {
// Polynomial P, prear, P0, t1, t2;
// t1 = P1;
// int i = 1;
// P0 = (Polynomial)malloc(sizeof(struct PolyNode)); //创建一个空节点,存放P1第i项与P2相乘的结果
// P0->link = NULL;
// while (P1)
// {
// t2 = P2;
// P0 = (Polynomial)malloc(sizeof(struct PolyNode)); //创建一个空节点,存放P1第i项与P2相乘的结果
// P0->link = NULL;
// prear = P0; //存放计算的临时结果,每次计算产生的临时结果链表空间一定是一样长的。
// while (t2)
// {
// Attach(P1->coef * t2->coef, P1->expon + t2->expon, &prear); //多项式系数一定不为0
// t2 = t2->link;
// }
// printf("P1_%d * P2=",i);
// PrintPoly(P0->link);
// if (i == 1) //第一次运算,直接将临时结果P0的值赋给P
// {
// P = CopyPoly(P0->link);
// }
// else //不是第一次运算,可以使用多项式相加函数,注意临时结果P0的头节点为空
// {
// P = PolyAdd(P, P0->link);
// }
// P1 = P1->link;
// i++;
// while (P0) //释放掉临时结果的链表空间,每次计算产生的临时结果链表空间一定是一样长的。
// {
// Polynomial temp;
// temp = P0;
// P0 = P0->link;
// free(temp);
// }
// }
// return P;
// }
Polynomial Mult2(Polynomial P1, Polynomial P2)
{
Polynomial t1, t2, P, prear, temp;
int coef, expon, i, j;
t1 = P1;
t2 = P2;
P = (Polynomial)malloc(sizeof(struct PolyNode)); //创建一个空节点,存放计算结果。
P->link = NULL;
prear = P; //表示P的尾节点
while (t2)
{
Attach(P1->coef * t2->coef, P1->expon + t2->expon, &prear); //多项式系数一定不为0
t2 = t2->link;
}
t1 = t1->link;
// printf("P1_1 * P2=");
// PrintPoly(P->link);
i = 2;
while (t1)
{
t2 = P2;
j = 1;
while (t2)
{
coef = t1->coef * t2->coef;
expon = t1->expon + t2->expon;
InsertNode(coef, expon, &P); //将结果项插入到结果多项式中
t2 = t2->link;
// printf("P1_%d * P2_%d=%dX^%d,结果多项式:", i, j, coef, expon);
// PrintPoly(P->link);
j++;
}
i++;
t1 = t1->link;
}
temp = P;
P = P->link;
free(temp);
return P;
}
void PrintPoly(Polynomial P)
{
if (!P)
{
printf("0 0");
return;
}
while (P)
{
printf("%d %d", P->coef, P->expon);
P = P->link;
if (P)
printf(" ");
}
printf("\n");
return;
}
Polynomial CopyPoly(Polynomial P0)
{
Polynomial P, temp;
P = (Polynomial)malloc(sizeof(struct PolyNode));
temp = P;
while (P0)
{
Attach(P0->coef, P0->expon, &temp);
P0 = P0->link;
}
temp = P;
P = P->link;
free(temp);
return P;
}
void InsertNode(int coef, int expon, Polynomial *prear)
{ //将结果项插入到结果多项式合适位置
Polynomial temp1, temp2, NewNode;
int sum;
temp1 = (*prear)->link;
if (!temp1) //结果多项式为空
{
// printf("临时结果多项式为空,插入前:");
// PrintPoly(temp1);
temp1 = NewNode;
temp1->coef = coef;
temp1->expon = expon;
temp1->link = NULL;
// printf("插入后:");
// PrintPoly(temp1);
}
else //结果多项式不为空
{
NewNode = (Polynomial)malloc(sizeof(struct PolyNode));
NewNode->coef = coef;
NewNode->expon = expon;
while (temp1 && temp1->expon > expon) //若结果多项式非空,筛选出temp2>NewNode>=temp1
{
temp2 = temp1;
temp1 = temp1->link;
}
if (temp1 == NULL) //情况1:插入在结果末尾
{
temp2->link = NewNode;
NewNode->link = NULL;
}
else if (temp1->expon == expon) //情况2:存在一项temp1,指数相同
{
sum = temp1->coef + coef;
if (sum) //指数相同,且和不为零
{
temp1->coef = sum;
free(NewNode);
}
else //指数相同,且和为零
{
temp2->link = temp1->link;
free(temp1);
free(NewNode);
}
}
else //情况3:指数在temp2和temp1之间
{
temp2->link = NewNode;
NewNode->link = temp1;
}
}
}
03.Reversing Linked List
#include <stdio.h>
#include <stdlib.h>
#define NULL -1
#define MaxSize 100000
// typedef struct ListNode *LNode;
struct ListNode
{
int Address;
int Data;
int NextAddress;
} L[MaxSize]; //定义一个数组链表
int main(void)
{
//输入链表
int i, j, FirstAdd, N, K, Knum;
scanf("%d%d%d", &FirstAdd, &N, &K);
for (i = 0; i < N; i++)
{
scanf("%d%d%d", &L[i].Address, &L[i].Data, &L[i].NextAddress);
}
L[N].Address = NULL;
//按照所输入的数据地址对链表进行排序
struct ListNode t1, t2; //
for (i = 0; i < N; i++)
{
for (j = i; j < N; j++)
{
if (L[j].Address == FirstAdd)
{
FirstAdd = L[j].NextAddress;
t1 = L[i];
L[i] = L[j];
L[j] = t1;
break;
}
}
if (FirstAdd == NULL) //判断是否到链表结尾,已排除有多余结点不在链表上的情况
{
N = i + 1;
}
}
//按照K个间隔进行倒序处理
Knum = N / K;
// printf("%d", Knum);
for (i = 0; i < Knum; i++)
{
for (j = 0; j < (K / 2); j++)
{
t1 = L[i * K + j];
L[i * K + j] = L[i * K + K - j - 1];
L[i * K + K - j - 1] = t1;
}
}
//更新前N-1个结点的NextAddress值,并输出
for (i = 0; i < N - 1; i++)
{
L[i].NextAddress = L[i + 1].Address;
printf("%05d %d %05d\n", L[i].Address, L[i].Data, L[i].NextAddress);
}
L[i].NextAddress = -1; //更新最后一个结点的NextAddress值
printf("%05d %d %d\n", L[i].Address, L[i].Data, L[i].NextAddress);
return 0;
}
04.Pop Sequence
//检查方法:数123...i,输入序列L;
//如果堆栈为空,向堆栈Push一个数i;
//比较堆栈顶元素和L[j]的大小:相等,则堆栈Pop,j++;如果不相等,(检查堆栈是否满),Push数i,i++
//如果堆栈已满,而L还未到末尾值,输出NO;如果堆栈未满,继续Push,若外面没有剩余的i,输出NO;
//如果L末尾值与堆栈栈顶元素匹配,即i==j,输出YES
#include <stdio.h>
#include <stdlib.h>
#define ElementType int
typedef struct SNode *Stack;
struct SNode
{
ElementType Data, NodeNum;
Stack Next;
};
Stack CreateSnack();
int IsEmpty(Stack S);
void Push(Stack S, ElementType t);
ElementType Pop(Stack S);
int main(void)
{
Stack S;
S = CreateSnack();
ElementType StackSize, Length, Num, i, j, k, w;
scanf("%d %d %d", &StackSize, &Length, &Num);
S->NodeNum = 0;
int L[Num][Length], Result[Num];
for (k = 0; k < Num; k++)
{
for (i = 0; i < Length; i++) //输入一行数据,存入数组L[];
scanf("%d", &L[k][i]);
}
for (k = 0; k < Num; k++)
{
w = 0; //数组L[k][w]
i = 1; //顺序数123...Length
while(!IsEmpty(S))
{
Pop(S);
}
while (1)
{
if (IsEmpty(S))
{
if (i <= Length)
{
// printf("空堆栈,Push操作");
Push(S, i);
i++;
}
}
//比较栈顶元素与序列数L[i]
if (S->Next->Data == L[k][w]) //相等,堆栈Pop,j++
{
Pop(S);
w++;
}
else //不相等,(检查堆栈满没满),继续Push
{
if (S->NodeNum == StackSize)
{
Result[k] = 0;
break;
;
}
else
{
Push(S, i);
i++;
}
}
//判断是否到达数123的末尾
if (i > Length + 1) //数123已经全部送进堆栈,NO
{
Result[k] = 0;
break;
;
}
if (i == Length + 1 && w == Length) //数123和L[k]匹配,YES
{
Result[k] = 1;
break;
}
}
}
//输出判断结果
for (i = 0; i < Num; i++)
{
if (Result[i])
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
Stack CreateSnack()
{ //创建空堆栈,带头结点形式,返回堆栈头节点地址
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
int IsEmpty(Stack S)
{ //判断堆栈是否为空,空返回1,非空返回0
if (S->Next == NULL)
return 1;
else
return 0;
}
void Push(Stack S, ElementType t)
{ //入栈
Stack temp;
temp = (Stack)malloc(sizeof(struct SNode));
temp->Data = t;
temp->Next = S->Next;
S->Next = temp;
S->NodeNum++;
}
ElementType Pop(Stack S)
{ //出栈
Stack FirstCell;
ElementType TopElem;
if (S->Next == NULL)
{
printf("堆栈空");
return -1;
}
else
{
FirstCell = S->Next;
S->Next = FirstCell->Next;
TopElem = FirstCell->Data;
free(FirstCell);
S->NodeNum--;
return TopElem;
}
}
结束
课程来源:浙江大学数据结构慕课MOOC