1、创建结点类型
用链表存储一个多项式,那么该链表的每一个结点就代表多项式的某一项。所以我们的每一个结点必须包含三个信息:多项式的系数、多项式的指数以及指向下一个结点的指针。
typedef int data_t;//指数、系数类型
typedef struct node {
data_t xishu;//系数
data_t zhishu;//指数
struct node *next;//用于存放下一个结点的地址
}node_t;
2、初始化链表
链表初始化,实质是实现头结点的创建和初始化设置。
node_t * CreateLinkList(void)
{
node_t *head;
/* 动态开辟头结点存储空间 */
head = malloc(sizeof(node_t));
if(head == NULL)
return NULL;
memset(head,0,sizeof(node_t)); /* 将头结点空间数据清零 */
head->next = NULL; /* 头结点next域没有指向表示为空链表 */
return head;
}
3、打印多项式
传入一个指向多项式链表的指针p,遍历该链表依次打印链表内容。(一次打印一个结点)
需将第一项拿出来单独打印,因为我们不希望第一项系数的正号被打印出来,然后还要考虑到指数为0,只有常数的情况
void DisplayLinkList(node_t *head)
{
node_t *p = head->next;
if(p != NULL)
{
if(p->zhishu == 0) //打印第一项
{
printf("%d",p->xishu);
p = p->next;
}
else
{
printf("%dx^%d",p->xishu,p->zhishu);
p = p->next;
}
}
while(p != NULL) //遍历后面的结点
{
if(p->zhishu == 0)
{
printf("+%d",p->xishu);
p = p->next;
}
else
{
if(p->xishu < 0)
{
printf("%dx^%d",p->xishu,p->zhishu);
p = p->next;
}
else
{
printf("+%dx^%d",p->xishu,p->zhishu);
p = p->next;
}
}
}
printf("\n");
}
4、插入结点
本文的输入主要采用的是插入结点,从第0个结点开始,后面两个参数为系数和指数
如果想从键盘输入或者输入完整多项式,只需要在main函数改动即可
int InsertLinkList(node_t *head,int local,data_t myxishu,data_t myzhishu)
{
int i;
node_t *p = head;
node_t *q;
/* 判断链表是否存在 */
if(head == NULL)
return -1;
/* 找到需要插入结点的前一个结点p */
for(i=0;i<local;i++)
{
p = p->next;
if(p == NULL)
return -1;
}
/* 创建需要插入结点q,并初始化数据 */
q = malloc(sizeof(node_t));
if(q == NULL)
return -1;
q->xishu = myxishu;
q->zhishu = myzhishu;
/* p结点插入结点q */
q->next = p->next;
p->next = q;
return 0;
}
5 、排序
输入的多项式可能并不是有序的,这时我们需要将多项式按指数降序排列(或按指数升序排列),以简化后续多项式的相加操作,这里我们选用插入排序算法。
void SortLinkList(node_t *head)
{
node_t *p;
node_t *q;
node_t *r;
if(head == NULL)
return ;
if(head->next == NULL)
return ;
p = head->next->next;/* 从链表第1个结点开始遍历 */
head->next->next = NULL;
while(p != NULL)
{
q = p;
p = p->next;
/* 顺序链表中找到需要插入结点的前一个结点 */
r = head;
while(r->next != NULL)
{
if(r->next->zhishu < q->zhishu)
break;
r = r->next;
}
/* 在结点r后插入结点q */
q->next = r->next;
r->next = q;
}
}
6 、合并多项式
从两个待相加的多项式的表头开始,比较两个结点的指数大小,若相同,则将两个结点的系数相加得到新的系数,申请一个新结点(结点的系数为新得到的系数,指数与这两个结点的指数相同)尾插到新链表的后面即可。若两个结点的指数不相同,则申请一个新结点(新结点的系数和指数与两个结点中指数较大的结点相同)尾插到新链表后面即可
node_t *ConnectLinkList(node_t **head1,node_t **head2)
{
node_t *r;
node_t *t;
/* 选择head1作为新链表的头结点 */
node_t *p = (*head1)->next;
(*head1)->next = NULL;
node_t *q = (*head2)->next;
free(*head2);
*head2 = NULL;
t = *head1;
while(p != NULL && q != NULL)
{
if(p->zhishu > q->zhishu)
{
r = p;
p = p->next;
}
else if(p->zhishu < q->zhishu)
{
r = q;
q = q->next;
}
else
{
/* 将指数相同的两个结点系数相加,系数存储到其中一共结点中,而另外一个结点释放 */
r = p;
p = p->next;
r->xishu += q->xishu;
node_t *f = q;
q = q->next;
free(f);
}
/* 结点t后插入结点r */
r->next = NULL;
t->next = r;
t = r;
}
/* 余下结点的处理 */
if(p == NULL)
{
t->next = q;
}
else
{
t->next = p;
}
return *head1;
}
7、完整代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef int data_t;//指数、系数类型
typedef struct node {
data_t xishu;//系数
data_t zhishu;//指数
struct node *next;//用于存放下一个结点的地址
}node_t;
node_t * CreateLinkList(void)
{
node_t *head;
/* 动态开辟头结点存储空间 */
head = malloc(sizeof(node_t));
if(head == NULL)
return NULL;
memset(head,0,sizeof(node_t)); /* 将头结点空间数据清零 */
head->next = NULL; /* 头结点next域没有指向表示为空链表 */
return head;
}
void DisplayLinkList(node_t *head)
{
node_t *p = head->next;
if(p != NULL)
{
if(p->zhishu == 0) //打印第一项
{
printf("%d",p->xishu);
p = p->next;
}
else
{
printf("%dx^%d",p->xishu,p->zhishu);
p = p->next;
}
}
while(p != NULL) //遍历后面的结点
{
if(p->zhishu == 0)
{
printf("+%d",p->xishu);
p = p->next;
}
else
{
if(p->xishu < 0)
{
printf("%dx^%d",p->xishu,p->zhishu);
p = p->next;
}
else
{
printf("+%dx^%d",p->xishu,p->zhishu);
p = p->next;
}
}
}
printf("\n");
}
int InsertLinkList(node_t *head,int local,data_t myxishu,data_t myzhishu)
{
int i;
node_t *p = head;
node_t *q;
/* 判断链表是否存在 */
if(head == NULL)
return -1;
/* 找到需要插入结点的前一个结点p */
for(i=0;i<local;i++)
{
p = p->next;
if(p == NULL)
return -1;
}
/* 创建需要插入结点q,并初始化数据 */
q = malloc(sizeof(node_t));
if(q == NULL)
return -1;
q->xishu = myxishu;
q->zhishu = myzhishu;
/* p结点插入结点q */
q->next = p->next;
p->next = q;
return 0;
}
void SortLinkList(node_t *head)
{
node_t *p;
node_t *q;
node_t *r;
if(head == NULL)
return ;
if(head->next == NULL)
return ;
p = head->next->next;/* 从链表第1个结点开始遍历 */
head->next->next = NULL;
while(p != NULL)
{
q = p;
p = p->next;
/* 顺序链表中找到需要插入结点的前一个结点 */
r = head;
while(r->next != NULL)
{
if(r->next->zhishu < q->zhishu)
break;
r = r->next;
}
/* 在结点r后插入结点q */
q->next = r->next;
r->next = q;
}
}
node_t *ConnectLinkList(node_t **head1,node_t **head2)
{
node_t *r;
node_t *t;
/* 选择head1作为新链表的头结点 */
node_t *p = (*head1)->next;
(*head1)->next = NULL;
node_t *q = (*head2)->next;
free(*head2);
*head2 = NULL;
t = *head1;
while(p != NULL && q != NULL)
{
if(p->zhishu > q->zhishu)
{
r = p;
p = p->next;
}
else if(p->zhishu < q->zhishu)
{
r = q;
q = q->next;
}
else
{
/* 将指数相同的两个结点系数相加,系数存储到其中一共结点中,而另外一个结点释放 */
r = p;
p = p->next;
r->xishu += q->xishu;
node_t *f = q;
q = q->next;
free(f);
}
/* 结点t后插入结点r */
r->next = NULL;
t->next = r;
t = r;
}
/* 余下结点的处理 */
if(p == NULL)
{
t->next = q;
}
else
{
t->next = p;
}
return *head1;
}
int main()
{
data_t myxishu;
data_t myzhishu;
node_t *head1;
node_t *head2;
head1 = CreateLinkList();
InsertLinkList(head1,0,3,0);
InsertLinkList(head1,1,2,2);
InsertLinkList(head1,2,4,5);
InsertLinkList(head1,3,6,4);
DisplayLinkList(head1);
SortLinkList(head1);
head2 = CreateLinkList();
InsertLinkList(head2,0,5,5);
InsertLinkList(head2,1,4,0);
InsertLinkList(head2,2,-2,7);
InsertLinkList(head2,3,4,3);
DisplayLinkList(head2);
SortLinkList(head2);
head1 = ConnectLinkList(&head1,&head2);
DisplayLinkList(head1);
}
8、运行结果: