思考与理解:
代码补充:老师的结果之后还会有一个“+”不够美观,此处加了判断,消去式子后多余的加号。打印提示改为了中文,便于查看。
老师代码的巧妙:虽然只写了几个测试用例,但是测试用例覆盖了所有方法的所有内容,运用了特殊值,一般值对算法进行检验。相加后进行了判断不会留下0*x^n这样系数为0的无用项。
学习目标:
学习链表,做出题目:多项式的加法是链表的基本应用, 也有助于理解压缩表示.
学习指导:帆神的代码
学习任务:
代码说明:
1.我在写的时候都用了不少时间调拭, 所以将所有的调拭语句保留. 如果不喜欢, 可以将它们删除.
2.对几种情况的分析有一定难度. 特别是相加后系数为 0. 跨越这个障碍就会进阶!
相加后仅剩一个链表, 其它无用空间都被释放. 如果不喜欢这种方式, 可以申请新空间进行相加, 这样的代码其实会更简单.
3.根据同学们的建议将 main 的返回类型定义为 int, 以适用不同版本的编译器.
4.根据刘涛等同学挑的 bug 进行了修改, 并且把测试用例 (用单独的函数) 增加到两个.5.多项式的通式是 pn(x)=a(n)· x^(n) + a(n−1)· x^(n−1) +······+a(1)·x+a(0)
此处设x=10
学习时间:
2022.5.6
1定义结构体
/**
* 创建链表节点结构体
*/
typedef struct LinkNode{
int coefficient; //定义系数
int exponent; //定义指数
struct LinkNode *next;
} *LinkList, *NodePtr;
2操作方法
2.1初始化多项式链表
/**
* @brief 初始化链表
*
* @return 头节点
*/
LinkList initLinkList(){
LinkList tempHeader = (LinkList)malloc(sizeof(struct LinkNode));
tempHeader->coefficient = 0;
tempHeader->exponent = 0;
tempHeader->next = NULL;
return tempHeader;
}
2.2打印多项式链表
/**
* @brief 打印链表
*
* @param paraHeader
*/
void printList(LinkList paraHeader){
NodePtr p = paraHeader->next;
while (p != NULL&&p->next!=NULL) {
printf("%d * 10^%d + ", p->coefficient, p->exponent);
p = p->next;
}
if(p!=NULL){
printf("%d * 10^%d", p->coefficient, p->exponent);
}
printf("\n");
}
2.3打印多项式链表中一个项
/**
* @brief 打印链表其中一个节点
*
* @param paraChar
* @param paraPtr
*/
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);
}
}
2.4尾插法添加项
/**
* @brief 往多项式中添加项
*
* @param paraCoefficient
* @param paraExponent
* @param paraHeader
*/
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;
}
2.5两多项式求和
/**
* @brief 将多项式进行相加
*
* @param paraList1
* @param paraList2
*/
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");
}
3测试
3.1单元测试1
/**
* 单元测试1
*/
void additionTest1(){
printf("----单元测试1开始测试-----\n");
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);
printf("\n****多项式相加的过程****\n");
add(tempList1, tempList2);
printf("\n相加后结果是: ");
printList(tempList1);
printf("\n---- 单元测试1结束 ----\n\n");
}
3.2单元测试2
/**
* 单元测试2
*/
void additionTest2(){
printf("----单元测试2开始测试-----\n");
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);
printf("\n****多项式相加的过程****\n");
add(tempList1, tempList2);
printf("\n相加后结果是: ");
printList(tempList1);
printf("\n---- 单元测试2结束 ----\n");
}
3.3测试结果
----单元测试1开始测试-----
第一个多项式为: 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的地址为-1026746528, q的地址为-1026746400
情况3:链表指数相等
3.2系数和为11,相加成功
r多项式的节点是( 11 * 10^1 )
p多项式的节点是( 9 * 10^8 )
p的地址为-1026746496, q的地址为-1026746368
情况2:链表r的指数较大
r多项式的节点是( 22 * 10^7 )
q多项式的节点是( -9 * 10^8 )
p的地址为-1026746496, q的地址为-1026746336
情况3:链表指数相等
3.1系数和为0,删去该多项式节点
p多项式的节点是( 5 * 10^17 )
p的地址为-1026746464, q的地址为0
****两多项式相加成功****
相加后结果是: 7 * 10^0 + 11 * 10^1 + 22 * 10^7 + 5 * 10^17
---- 单元测试1结束 ----
----单元测试2开始测试-----
第一个多项式为: 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的地址为-1026746336, q的地址为-1026746208
情况3:链表指数相等
3.2系数和为11,相加成功
r多项式的节点是( 11 * 10^1 )
p多项式的节点是( 9 * 10^8 )
p的地址为-1026746304, q的地址为-1026746176
情况2:链表r的指数较大
r多项式的节点是( 22 * 10^7 )
q多项式的节点是( -9 * 10^10 )
p的地址为-1026746304, q的地址为-1026646144
情况1:链表r的指数较小
r多项式的节点是( 9 * 10^8 )
p多项式的节点是( 5 * 10^17 )
p的地址为-1026746272, q的地址为-1026646144
情况2:链表r的指数较大
r多项式的节点是( -9 * 10^10 )
未找到q多项式节点
p的地址为-1026746272, q的地址为0
****两多项式相加成功****
相加后结果是: 7 * 10^0 + 11 * 10^1 + 22 * 10^7 + 9 * 10^8 + -9 * 10^10 + 5 * 10^17
---- 单元测试2结束 ----
--------------------------------
Process exited after 0.07614 seconds with return value 0
Press ANY key to continue...
4全部代码
#include <stdio.h>
#include <malloc.h>
/**
* 创建链表节点结构体
*/
typedef struct LinkNode{
int coefficient; //定义系数
int exponent; //定义指数
struct LinkNode *next;
} *LinkList, *NodePtr;
/**
* @brief 初始化链表
*
* @return 头节点
*/
LinkList initLinkList(){
LinkList tempHeader = (LinkList)malloc(sizeof(struct LinkNode));
tempHeader->coefficient = 0;
tempHeader->exponent = 0;
tempHeader->next = NULL;
return tempHeader;
}
/**
* @brief 打印链表
*
* @param paraHeader
*/
void printList(LinkList paraHeader){
NodePtr p = paraHeader->next;
while (p != NULL&&p->next!=NULL) {
printf("%d * 10^%d + ", p->coefficient, p->exponent);
p = p->next;
}
if(p!=NULL){
printf("%d * 10^%d", p->coefficient, p->exponent);
}
printf("\n");
}
/**
* @brief 打印链表其中一个节点
*
* @param paraChar
* @param paraPtr
*/
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);
}
}
/**
* @brief 往多项式中添加项
*
* @param paraCoefficient
* @param paraExponent
* @param paraHeader
*/
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;
}
/**
* @brief 将多项式进行相加
*
* @param paraList1
* @param paraList2
*/
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");
}
/**
* 单元测试1
*/
void additionTest1(){
printf("----单元测试1开始测试-----\n");
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);
printf("\n****多项式相加的过程****\n");
add(tempList1, tempList2);
printf("\n相加后结果是: ");
printList(tempList1);
printf("\n---- 单元测试1结束 ----\n\n");
}
/**
* 单元测试2
*/
void additionTest2(){
printf("----单元测试2开始测试-----\n");
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);
printf("\n****多项式相加的过程****\n");
add(tempList1, tempList2);
printf("\n相加后结果是: ");
printList(tempList1);
printf("\n---- 单元测试2结束 ----\n");
}
int main(){
additionTest1();
additionTest2();
return 0;
}