用链表存储一元多项式,并实现两个多项式的加法。
存储多项式的数据结构
多项式的通式是(x)=+。n次多项式共有n+1项。直观地,可以定义一个数组来存储这n+1个系数。以多项式为例,存储这个多项式的数组如下图:
可以看出,这种方案适合对某些多项式的处理。但是,在处理一些次数高但项数少的多项式时,存在浪费空间的现象,会有很多闲置的0。
可以使用链表结构存储多项式:链表中的每一个结点是多项式中的一项,结点的数据域包括指数和系数两部分,由指针域连接起多项式中的各项。
1.定义结构体
typedef struct LinkNode{
int coefficient; //定义系数
int exponent; //定义指数
struct LinkNode *next;
} *LinkList, *NodePtr;
多项式加法在链表存储结构下的实现
链表存储结构下,多项式加法的实现 在如上定义的单链表存储结构基础上,讨论实现多项式加法的算法。
两个多项式相加,其规则是对具有相同指数的项,令其系数相加。设两个待相加的多项式的链表的头指针分别为head1(第一个多项式)和head2(第二个多项式),两者的和保存到链表head1中。只需要先将head1和head2链表的首结点作为当前结点(分别用p1和p2指向)开始检测,在遍历链表的过程中,分情况作如下处理:
(1)若两个多项式中当前结点的指数值相同,则它们的系数相加,结果保存到p1结点,并将p2结点删除。如果相加后的系数不为0,p1指向第一个多项式的下一个结点,准备随后的工作,否则,不保存系数为0的项,将当前p1结点删除。
(2)当两个多项式中对应结点的指数值不相等时,若p1指向的结点的指数大,则p1简单地指向下一结点即可;而p2指向的结点大时,需要将p2结点插入到p1前,然后p2再重新指回到第二个多项式中的下一结点,继续进行处理。
(3)检测过程直到其中的任一个链表结束。若p1不为空,第一个多项式中的剩余项已经在链表中,不作处理,如果p2不为空,只需要将p2链接到相加后的第一个多项式末尾。
2.链表初始化
LinkList initLinkList()
{
LinkList tempHeader=(LinkList)malloc(sizeof(struct LinkNode));
tempHeader->coefficient=0;
tempHeader->exponent=0;
tempHeader->next=NULL;
return tempHeader;
}
3.打印链表
void printList(LinkList paraHeader)
{
NodePtr p=paraHeader->next;
while(p!=NULL)
{
printf("%d * 10^%d + ",p->coefficient,p->exponent);
p=p->next;
};
printf("\r\n");
}
4.打印结点(测试)
void printNode(NodePtr paraPtr, char paraChar){
if (paraPtr == NULL) {
printf("\t未找到%c多项式节点\n",paraChar);
} else {
printf("\t%c多项式的节点是( %d * 10^%d )\n", paraChar, paraPtr->coefficient, paraPtr->exponent);
}
}
5.添加元素
void appendElement(LinkList paraHeader, int paraCoefficient, int paraExponent){
NodePtr p, q;
//1申请节点空间
q = (NodePtr)malloc(sizeof(struct LinkNode));
q->coefficient = paraCoefficient;
q->exponent = paraExponent;
q->next = NULL;
//2尾插法,找到链表尾部
p = paraHeader;
while (p->next != NULL) {
p = p->next;
}
//3连接
p->next = q;
}
6.Add函数(核心)
void add(NodePtr paraList1, NodePtr paraList2){
NodePtr p, q, r, s;
//1找到多项式
p = paraList1->next;
printNode(p, 'p');
q = paraList2->next;
printNode(q, 'q');
//加到第一链表中
r = paraList1;
printNode(r, 'r');
//释放第二个多项式链表
free(paraList2);
while ((p != NULL) && (q != NULL)) {
if (p->exponent < q->exponent) {
printf("情况1:链表r的指数较小\n");
r->next = p;
r = p;
printNode(r, 'r');
p = p->next;
printNode(p, 'p');
} else if ((p->exponent > q->exponent)) {
printf("情况2:链表r的指数较大\n");
r->next = q;
r = q;
printNode(r, 'r');
q = q->next;
printNode(q, 'q');
} else {
printf("情况3:链表指数相等\n");
p->coefficient = p->coefficient + q->coefficient;
if (p->coefficient == 0) {
printf("\t3.1系数和为0,删去该多项式节点\n");
s = p;
p = p->next;
printNode(p, 'p');
} else {
printf("\t3.2系数和为%d,相加成功\n",p->coefficient);
r = p;
printNode(r, 'r');
p = p->next;
printNode(p, 'p');
}
s = q;
q = q->next;
free(s);
}
printf("\tp的地址为%ld, q的地址为%ld \n", p, q);
}
if (p == NULL) {
r->next = q;
} else {
r->next = p;
}
printf("****两多项式相加成功****\r\n");
}
7.测试函数
void additionTest1(){
LinkList tempList1 = initLinkList();
appendElement(tempList1, 7, 0);
appendElement(tempList1, 3, 1);
appendElement(tempList1, 9, 8);
appendElement(tempList1, 5, 17);
printf("第一个多项式为: ");
printList(tempList1);
LinkList tempList2 = initLinkList();
appendElement(tempList2, 8, 1);
appendElement(tempList2, 22, 7);
appendElement(tempList2, -9, 8);
printf("第二个多项式为: ");
printList(tempList2);
add(tempList1, tempList2);
printf("\n相加后结果是: ");
printList(tempList1);
}
void additionTest2(){
LinkList tempList1 = initLinkList();
appendElement(tempList1, 7, 0);
appendElement(tempList1, 3, 1);
appendElement(tempList1, 9, 8);
appendElement(tempList1, 5, 17);
printf("第一个多项式为: ");
printList(tempList1);
LinkList tempList2 = initLinkList();
appendElement(tempList2, 8, 1);
appendElement(tempList2, 22, 7);
appendElement(tempList2, -9, 10);
printf("第二个多项式为: ");
printList(tempList2);
add(tempList1, tempList2);
printf("\n相加后结果是: ");
printList(tempList1);
}
第一个多项式为: 7 * 10^0 + 3 * 10^1 + 9 * 10^8 + 5 * 10^17
第二个多项式为: 8 * 10^1 + 22 * 10^7 + -9 * 10^8
p多项式的节点是( 7 * 10^0 )
q多项式的节点是( 8 * 10^1 )
r多项式的节点是( 0 * 10^0 )
情况1:链表r的指数较小
r多项式的节点是( 7 * 10^0 )
p多项式的节点是( 3 * 10^1 )
p的地址为7345216, q的地址为7345344
情况3:链表指数相等
3.2系数和为11,相加成功
r多项式的节点是( 11 * 10^1 )
p多项式的节点是( 9 * 10^8 )
p的地址为7345248, q的地址为7345376
情况2:链表r的指数较大
r多项式的节点是( 22 * 10^7 )
q多项式的节点是( -9 * 10^8 )
p的地址为7345248, q的地址为7345408
情况3:链表指数相等
3.1系数和为0,删去该多项式节点
p多项式的节点是( 5 * 10^17 )
p的地址为7345280, q的地址为0
两多项式相加成功
相加后结果是: 7 * 10^0 + 11 * 10^1 + 22 * 10^7 + 5 * 10^17
第一个多项式为: 7 * 10^0 + 3 * 10^1 + 9 * 10^8 + 5 * 10^17
第二个多项式为: 8 * 10^1 + 22 * 10^7 + -9 * 10^10
p多项式的节点是( 7 * 10^0 )
q多项式的节点是( 8 * 10^1 )
r多项式的节点是( 0 * 10^0 )
情况1:链表r的指数较小
r多项式的节点是( 7 * 10^0 )
p多项式的节点是( 3 * 10^1 )
p的地址为7345408, q的地址为7345536
情况3:链表指数相等
3.2系数和为11,相加成功
r多项式的节点是( 11 * 10^1 )
p多项式的节点是( 9 * 10^8 )
p的地址为7345440, q的地址为7345568
情况2:链表r的指数较大
r多项式的节点是( 22 * 10^7 )
q多项式的节点是( -9 * 10^10 )
p的地址为7345440, q的地址为7345600
情况1:链表r的指数较小
r多项式的节点是( 9 * 10^8 )
p多项式的节点是( 5 * 10^17 )
p的地址为7345472, q的地址为7345600
情况2:链表r的指数较大
r多项式的节点是( -9 * 10^10 )
未找到q多项式节点
p的地址为7345472, q的地址为0
两多项式相加成功
相加后结果是: 7 * 10^0 + 11 * 10^1 + 22 * 10^7 + 9 * 10^8 + -9 * 10^10 + 5 * 10^17