1.编写思路及核心
我们的目标是将两个多项式进行合并,所以先要使用两个单链表对这两个多项式进行输入和储存,再依次对每个节点进行“比大小”的操作,按某种顺序对每个节点的次数进行判断,这里我们将结果储存在第一个链表中,当然你也可以在创建一个单链表用于储存新的结果。
2.代码的实现
首先我们先定义要用到的变量
typedef struct LinkNode{
int coefficient;
int exponent;
struct LinkNode *next;
} *LinkList, *NodePtr;
而创建单链表和添加元素的操作与2.2单链表中的操作无异
函数形式分别为
LinkList initLinkList()//建立单链表,返回头指针
void printList(LinkList paraHeader)//打印链表
这里我们还要添加一个用于打印p,q(建立结果链表的函数会用到)所指的节点的函数
void printNode(NodePtr paraPtr, char paraChar){
if (paraPtr == NULL) {
printf("NULL\r\n");
} else {
printf("The element of %c is (%d * 10^%d)\r\n", paraChar, paraPtr->coefficient, paraPtr->exponent);
}// Of while
}// Of printNode
重点:如何实现相加的操作
void add(NodePtr paraList1, NodePtr paraList2){
NodePtr p, q, r, s;
// Step 1. Search to the position.
p = paraList1->next;
printNode(p, 'p');
q = paraList2->next;
printNode(q, 'q');
r = paraList1; // Previous pointer for inserting.
printNode(r, 'r');
free(paraList2); // The second list is destroyed.
while ((p != NULL) && (q != NULL)) {
if (p->exponent < q->exponent) {
//Link the current node of the first list.
printf("case 1\r\n");
r->next = p;//r指向首元节点
r = p;//
printNode(r, 'r');
p = p->next;
printNode(p, 'p');
} else if ((p->exponent > q->exponent)) {
//Link the current node of the second list.
printf("case 2\r\n");
r->next = q;
r = q;
printNode(r, 'r');
q = q->next;
printNode(q, 'q');
} else {
printf("case 3\r\n");
//Change the current node of the first list.
p->coefficient = p->coefficient + q->coefficient;
printf("The coefficient is: %d.\r\n", p->coefficient);
if (p->coefficient == 0) {
printf("case 3.1\r\n");
s = p;
p = p->next;
printNode(p, 'p');
// free(s);
} else {
printf("case 3.2\r\n");
r = p;
printNode(r, 'r');
p = p->next;
printNode(p, 'p');
}// Of if
s = q;
q = q->next;
//printf("q is pointing to (%d, %d)\r\n", q->coefficient, q->exponent);
free(s);
}// Of if
printf("p = %ld, q = %ld \r\n", p, q);
} // Of while
printf("End of while.\r\n");
if (p == NULL) {
r->next = q;
} else {
r->next = p;
} // Of if
printf("Addition ends.\r\n");
}// Of add
简单来说,我们定义p,q用于链表1和链表2的移动,r用于建立新的链表,s用于储存要释放的空间
用(p != NULL) && (q != NULL)这条语句判断是否到达任一链表的表尾,而相加等于0的情况需要释放空间。
3.程序的测试(我这里只对闵老师的test1进行了调试)
void additionTest1(){
// Step 1. Initialize the first polynomial.
LinkList tempList1 = initLinkList();
appendElement(tempList1, 7, 0);
appendElement(tempList1, 3, 1);
appendElement(tempList1, 9, 8);
appendElement(tempList1, 5, 17);
printList(tempList1);
// Step 2. Initialize the second polynomial.
LinkList tempList2 = initLinkList();
appendElement(tempList2, 8, 1);
appendElement(tempList2, 22, 7);
appendElement(tempList2, -9, 8);
printList(tempList2);
// Step 3. Add them to the first.
add(tempList1, tempList2);
printf("The result is: ");
printList(tempList1);
printf("\r\n");
}// Of additionTest1
运行结果
4.感悟及收获
我觉得编写这段代码很好地训练了我的抽象思维能力,在大脑里模仿计算机的思维方式可以说是比较困难,我在纸上画了图才了解add函数是如何运作的,想要将计算方法转化成简洁的程序设计语言确实需要一定动手能力。