数据结构(二)
学习数据结构与算法过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
—— 多项式加法 ——
1.题目描述
我们经常遇到两多项式相加的情况,在这里,我们就需要用程序来模拟实现把两个多项式相加到一起。首先,我们会有两个多项式,每个多项式是独立的一行,每个多项式由系数、幂数这样的多个整数对来表示。
如多项式2x20- x17+ 5x9- 7x7+ 16x5+ 10x4 + 22x2- 15
对应的表达式为:2 20 -1 17 5 9 - 7 7 16 5 10 4 22 2 -15 0。
为了标记每行多项式的结束,在表达式后面加上了一个幂数为负数的整数对。
同时输入表达式的幂数大小顺序是随机的。 我们需要做的就是把所给的两个多项式加起来。
1.1输入
输入包括多行。 第一行整数n,表示有多少组的多项式需要求和。(1 < n < 100)下面为2n行整数,每一行都是一个多项式的表达式。表示n组需要相加的多项式。 每行长度小于300。
1.2输出
输出包括n行,每行为1组多项式相加的结果。 在每一行的输出结果中,多项式的每一项用“[x y]”形式的字符串表示,x是该项的系数、y是该项的幂数。要求按照每一项的幂从高到低排列,即先输出幂数高的项、再输出幂数低的项。 系数为零的项不要输出。
1.3样例输入和输出
样例输入
2
-1 17 2 20 5 9 -7 7 10 4 22 2 -15 0 16 5 0 -1
2 19 7 7 3 17 4 4 15 10 -10 5 13 2 -7 0 8 -8
-1 17 2 23 22 2 6 8 -4 7 -18 0 1 5 21 4 0 -1
12 7 -7 5 3 17 23 4 15 10 -10 5 13 5 2 19 9 -7
样例输出
[ 2 20 ] [ 2 19 ] [ 2 17 ] [ 15 10 ] [ 5 9 ] [ 6 5 ] [ 14 4 ] [ 35 2 ] [ -22 0 ]
[ 2 23 ] [ 2 19 ] [ 2 17 ] [ 15 10 ] [ 6 8 ] [ 8 7 ] [ -3 5 ] [ 44 4 ] [ 22 2 ] [ -18 0 ]
1.4提示
第一组样例数据的第二行末尾的8 -8,因为幂次-8为负数,所以这一行数据结束,8 -8不要参与计算。
2.代码实现
c
#include <stdio.h>
#include <stdlib.h>
//定义节点结构体
typedef struct polynomial
{
int coe;//系数
int index;//指数
struct polynomial*next;//指向写一个节点的指针
}pol;
//创建头节点
pol*create()
{
pol*head=NULL;
head=(pol*)malloc(sizeof(pol));
head->next=NULL;
return head;
}
//按大小插入节点
void insert(pol*head,int coe_insert,int index_insert)
{
pol*t=(pol*)malloc(sizeof(pol));
pol*n=head->next,*m=head;
//插入第一个节点的操作
if(head->next==NULL)
{
head->next=t;
t->next=NULL;
t->coe=coe_insert;
t->index=index_insert;
}
//插入其余节点的操作
else
while(1)
{
//当插入节点的指数比当前指针指向的节点的指数小或者已无后续节点时
if(n->next==NULL&&n->index>index_insert)
{
n->next=t;
t->next=NULL;
t->coe=coe_insert;
t->index=index_insert;
break;
}
if(n->index<index_insert)
{
m->next=t;
t->next=n;
t->coe=coe_insert;
t->index=index_insert;
break;
}
//当插入节点的指数和当前指针指向的节点的指数相等(虽然题目中没有提示这种情况,但是以防万一)
if(n->index==index_insert)
{
n->coe=n->coe+coe_insert;
break;
}
//当插入节点的指数比当前指针指向的节点的指数大,则指针继续后延
else
{
m=n;
n=n->next;
}
}
}
//将2个链表比较,按照要求进行整合,我选择直接整合到第一个链表中
void compare(pol*headA,pol*headB)
{
pol*n=headA,*x,*m=headB->next;
//具体比较和插入的逻辑大家可以看一下
while(1)
{
x=m;
if(m==NULL)
break;
else if(n->index==m->index)
{
n->coe=n->coe+m->coe;
m=m->next;
continue;
}
else if(n->next->index<m->index||n->next==NULL)
{
m=m->next;
x->next=n->next;
n->next=x;
continue;
}
else
n=n->next;
}
}
//输出第一个链表,当系数为0时,自动跳过
void output(pol*head)
{
pol*y=head->next;
while(1)
{
if(y ->coe == 0)
y = y ->next;
if(y==NULL)
break;
printf("[ %d %d ] ",y->coe,y->index);
y=y->next;
}
printf("\n");
}
int main()
{
int num;
scanf("%d",&num);
for(int i=0;i<num;i++)
{
pol*headA=NULL;
pol*headB=NULL;
headA=create();
headB=create();
while(1)
{
int a,b;
scanf("%d%d",&a,&b);
if(b<0)
break;
insert(headA,a,b);
}
while(1)
{
int a,b;
scanf("%d%d",&a,&b);
if(b<0)
break;
insert(headB,a,b);
}
compare(headA,headB);
output(headA);
}
return 0;
}
3.代码说明
其实不难发现,上述代码不仅浪费了很多空间(第二个链表的空间)而且运行起来应该会很慢,容错率极低,所以我们经过简化和修改,并使用C++进行了第二版修改,如下:
c++
# include<iostream>
# include<algorithm>
using namespace std;
typedef struct polynomial
{
int coe;
int index;
struct polynomial * next;
}pol;
bool cmp(pol a,pol b)
{
return a.index>b.index;
}
void creat(pol *Head,int a,int b)
{
pol *p=new pol;
p->coe=a;
p->index=b;
p->next=Head->next;
Head->next=p;
}
pol *insert(pol *Head,int b)
{
pol *p=Head->next;
while(p&&p->index!=b)
{
p=p->next;
}
return p;
}
void compare(pol *Head)
{
pol *p,*q;
int ta,tb;
for(p=Head->next; p!=NULL; p=p->next)
for(q=Head->next; q->next!=NULL; q=q->next)
{
if(q->index<q->next->index)
{
ta=q->coe;
tb=q->index;
q->coe=q->next->coe;
q->index=q->next->index;
q->next->coe=ta;
q->next->index=tb;
}
}
}
int main(void)
{
pol *Head=NULL, *p, *q;
int n,t,a,b,i;
cin>>n;
for(i=0; i<n;i++)
{
Head new pol;
Head->next=NULL;
t=1;
while(t<=2)
{
while(cin>>a>>b)
{
if(b<0)
break;
if((p=insert(Head, b))!=NULL)
{
p->coe+=a;
}
else
creat(Head,a,b);
}
t++;
}
compare(Head);
p=Head->next;
while(p!=NULL)
{
if(p->coe==0)
{
p=p->next;
continue;
}
cout<<"[ "<<p->coe<<" "<<p->index<<" ]"<<" ";
p=p->next;
}
cout<<endl;
p=Head->next;
while(!p)
{
q=p;
p=p->next;
delete q;
}
}
return 0;
}
当然还有一种更简便的办法,但是涉及到c++的map函数,大家可以直接百度一下。