题目来源:3-2-3 链表 一元多项式的乘法与加法运算 (20 分)
这个题目第二次写了,应该没问题了,第一次写最后两个点一直没过,今天才发现当add或者mul为空表(零多项式)应输出“0 0”。行吧,总算是过了。
上(第二次的)(个人感觉比第一次写的好看)代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct dec* LinkList;
struct dec {
int coef;//系数
int expon;//指数
LinkList next;
};
LinkList Read();
void Attach(int c, int e, LinkList* head, LinkList* tail);//尾巴接上
void Insert(int c, int e, LinkList* head, LinkList* tail);//中间接上
void print(LinkList L);
void Renew(LinkList* head);//把系数为0的清除,其实也可以边计算边清除去,但是感觉有个费时间,每次清楚都要从头遍历,不如一次性清除。
LinkList Add(LinkList L1, LinkList L2);//加法
LinkList Mul(LinkList L1, LinkList L2);//乘法
int main()
{
LinkList L1, L2,add,mul;
L1 = Read();
L2 = Read();
add = Add(L1, L2);
mul = Mul(L1, L2);
print(mul);
printf("\n");
print(add);
return 0;
}
void Renew(LinkList* head)//更新,把所有系数为0的清楚干净
{
while (*head&&(*head)->coef== 0) *head = (*head)->next;
if (*head == NULL) return;
LinkList front = *head,tail=front->next;//开始的front的系数肯定不为0;
while (tail)
{
if (tail->coef == 0) {//删除节点
front->next = tail->next;
free(tail);
}
front = front->next;
tail = front->next;
}
}
LinkList Mul(LinkList L1, LinkList L2)
{
if (L1 == NULL || L2 == NULL)return NULL;//***这个没加导致第四个点一直过不去
LinkList head = NULL, tail = NULL;
LinkList point2 = L2 ,point1 = L1;
int c, e;
while (point2)//先将L1的一个元素和L2上的每一个元素相乘,构成一条链表
{
c = (point1 ->coef)* (point2->coef);
e = (point1->expon) + (point2->expon);
Attach(c, e, &head, &tail);
point2 = point2->next;
}
point1 = point1->next;//这一步不能漏,第一条链表的第一个节点已与第二条链表每一个节点相乘,所以第一条链表的节点要后移
while (point1)
{
point2 = L2;
while (point2)//链表一的每一个节点与链表二的每一个节点相乘插入已经构成的链表
{
int c = point1->coef * point2->coef;
int e = point1->expon + point2->expon;
Insert(c, e, &head, &tail);
point2 = point2->next;
}
point1 = point1->next;
}
Renew(&head);
return head;
}
void Insert(int c, int e, LinkList* head, LinkList* tail)
{
LinkList point = *head;
if (e > point->expon) {//头部插入
//其实是用不到的,因为两条链表(指数降序)的第一个节点相乘一定是最大的
LinkList temp = (LinkList)malloc(sizeof(struct dec));
temp->expon = e;
temp->coef = c;
temp->next = *head;
*head = temp;
return;
}
else if (e < (*tail)->expon)//尾部插入
{
Attach(c, e, &*head, &*tail);
return;
}
while (point)//不能用head,会改变head的指向的,因为传入Insert函数的是head的二级指针
{
if (point->expon == e) {
point->coef += c;//指数相同,系数相加
return;
}
else if (e<point->expon && e>(point->next)->expon)//中间插入
{
LinkList temp = (LinkList)malloc(sizeof(struct dec));
temp->expon = e;
temp->coef = c;
temp->next = point->next;
point->next = temp;
return;
}
point = point->next;
}
}
LinkList Add(LinkList L1, LinkList L2)
{
if (L1 == NULL && L2 == NULL) return NULL;//***这个没加导致第四个点一直过不去
LinkList head = NULL, tail = NULL;
int c, e;
while (L1 && L2)
{
if (L1->expon == L2->expon)//指数相同,系数相加
{
c = L1->coef + L2->coef;
e = L1->expon;
if(c) Attach(c, e, &head, &tail);//系数不为0才保存
L1 = L1->next,L2=L2->next;
}
else if (L1->expon > L2->expon)
{
if(L1->coef)Attach(L1->coef,L1->expon,&head, &tail);
L1 = L1->next;
}
else
{
if(L2->coef)Attach(L2->coef, L2->expon, &head, &tail);
L2 = L2->next;
}
}
while (L1)
{
if(L1->coef)Attach(L1->coef, L1->expon, &head, &tail);
L1 = L1->next;
}
while (L2)
{
if(L2->coef)Attach(L2->coef, L2->expon, &head, &tail);
L2 = L2->next;
}
return head;
}
LinkList Read()
{
LinkList head=NULL, tail=NULL;
int n,c,e;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d %d", &c, &e);
Attach(c, e, &head, &tail);
}
return head;
}
void Attach(int c, int e, LinkList* head, LinkList* tail)
{
LinkList temp = (LinkList)malloc(sizeof(struct dec));
temp->next = NULL;
temp->coef = c;
temp->expon = e;
if (*head == NULL) *head = temp;
else (*tail)->next = temp;
*tail = temp;
}
void print(LinkList L)
{
if (L == NULL)
{
printf("0 0");
return;
}
int flag = 0;
while (L) {
if (flag != 0) printf(" ");
flag = 1;
printf("%d %d", L->coef, L->expon);
L = L->next;
}
}