本文章代码实现部分参考自(C语言版)链表(一)——实现单向链表创建、插入、删除等简单操作(包含个人理解说明及注释,新手跟着写代码)
前言
整个C语言课程学习中, 第一个难点是指针数组, 第二个遇到的难点就是链表. 同时在学习数据结构过程中知道链表的原理, 却一直没办法实现. 查找了很多博客, 资料, 有幸看到如上真·新手向 教程, 特此分享并记录自己的不足与理解.
引例1 — 多项式加法
设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:
输出1行,以指数递降方式输出和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。
输入样例:
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1
输出样例:
5 20 -4 4 -5 2 9 1 -2 0
分析
如果多项式的指数是较为稠密的, 可通过数组来实现. 而如果出现第一项是X的1000次方, 后一项是X的2次方, 如果仍使用数组会出现空间和时间上的极大浪费, 因此选择用链表实现.
实现方式是先将两个多项式以链表的形式创建好, 之后分别从两多项式最高次项(链表头)开始进行比较
- 如果A多项式当前指数较大, 将该系数和指数存入答案链表中, 并将A多项式的指针后移一位
- 如果B多项式当前指数较大, 将该系数和指数存入答案链表中, 并将B多项式的指针后移一位
- 如果两个多项式当前指数相等, 将系数相加,与当前指数存入答案链表中, 并将二者指针后移一位
- 当其中一个多项式的指针指向了NULL(链表尾节点), 那么将另一多项式所有后继节点接到答案链表的尾部.
代码实现
#include<stdio.h>
#include<stdlib.h>
/*NODE用来告诉malloc函数该结构体的大小, 而pNODE用来定义新建的链表节点(是一个指向该结构体类型的指针)*/
typedef struct number{
int x;
int y;
struct number *pnext;
}NODE, *pNODE;
pNODE CreateLink(int n)
{
/*尾节点只起指向作用, 无需分配空间, 而头节点和临时创建的节点则需要申请空间*/
pNODE temp = NULL, tail = NULL;
pNODE head = (pNODE)malloc(sizeof(NODE));
/*将头节点的后继节点写入NULL,可以检测到链表是否为空*/
head->pnext = NULL;
tail = head;
int i;
for(i=1; i<=n; i++)
{
/*为临时节点申请空间, 并将其后继节点指针指向NULL*/
temp = (pNODE)malloc(sizeof(NODE));
scanf("%d %d", &temp->x, &temp->y);
temp->pnext = NULL;
/*将当前尾结点的后继节点指向temp, 链接起来. 随后将尾结点指向刚刚链接进来的临时节点*/
tail->pnext = temp;
tail = temp;
}
return head;
}
pNODE AddLink(pNODE head1, pNODE head2)
{
//创建新的链表, 用于储存相加的结果.
pNODE head = (pNODE)malloc(sizeof(NODE));
head->pnext = NULL;
//定义三个尾节点指针, 用于指向"多项式A","多项式B","和多项式A+B"的当前(末尾)节点
//对于一个新建的单元,或一个要被删除的单元,最好建立一个临时变量, 因为撤除指针后将不能再引用这个单元.
pNODE tail = head, temp = NULL;
pNODE tail1 = head1->pnext, tail2 = head2->pnext;
while(tail1 != NULL && tail2 != NULL)
{
temp = (pNODE)malloc(sizeof(NODE));
if(tail1->y == tail2->y) //两子多项式指数相等
{
//若两系数相加不为0, 则将相加后的结果储存到结果链表中; 若为零则跳过储存这步
if(tail1->x + tail2->x != 0)
{
temp->x = tail1->x + tail2->x;
temp->y = tail1->y;
temp->pnext = NULL;
}
tail1 = tail1->pnext;
tail2 = tail2->pnext;
}
else if(tail1->y > tail2->y) //两子多项式指数不相同时, 指数大者直接链入结果链表中.
{
temp->x = tail1->x;
temp->y = tail1->y;
temp->pnext = NULL;
tail1 = tail1->pnext;
}
else
{
temp->x = tail2->x;
temp->y = tail2->y;
temp->pnext = NULL;
tail2 = tail2->pnext;
}
tail->pnext = temp;
tail = temp;
}
if(tail1 == NULL) //某一多项式指向NULL后跳出, 将另一多项式后继节点链入结果链表.
{
tail->pnext = tail2;
}
else
{
tail->pnext = tail1;
}
//返回结果多项式头节点.
return head;
}
int main(void)
{
pNODE head1 = (pNODE)malloc(sizeof(NODE));
pNODE head2 = (pNODE)malloc(sizeof(NODE));
// NODE head1, head2; //不是创建结构体, 而是创建拥有所指向结构单元大小的指针.
head1->pnext = NULL;
head2->pnext = NULL;
int len_1, len_2;
scanf("%d", &len_1);
head1 = CreateLink(len_1);
scanf("%d", &len_2);
head2 = CreateLink(len_2);
// printf("in\n"); //仅用于调试
pNODE head = AddLink(head1, head2);
// printf("out\n"); //仅用于调试
pNODE tail = head->pnext;
while(tail!=NULL)
{
if(tail == head->pnext)
{
printf("%d %d", tail->x, tail->y);
}
else
{
printf(" %d %d", tail->x, tail->y);
}
tail = tail->pnext;
}
return 0;
}