要求:
多项式指数按照从大到小顺序排列,计算求和多项式后不会破坏原有输入的两个多项式
1. 思路
1)让用户输入多项式的系数和指数,将最终多项式按指数降序排序,由于输入时可能不是按照顺序,因此需要排序,这里有两种方法:
a. 用单链表,先不排序,所有数据直接插入尾部,最后进行排序。
b. 用双链表,添加一个指向前一节点的指针,每次输入一组数据进行插入排序。
2)要求求和后不破坏原来输入,则重新建立一个新的链表。
2. 程序
单链表
本程序包含四种排序算法:优化的冒泡法,快速排序,插入排序,选择排序
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
struct node;
typedef struct node *ptrtonode;
typedef ptrtonode polynomial;
typedef ptrtonode position;
struct node {
int coef;
int expo;
ptrtonode next;
};
polynomial InitList(void);
void CreatList(polynomial L);
void SortListMenu(void);
char getlet(char *s);
void SortMenu(char ch, polynomial L);
void ShowList(polynomial L);
polynomial AddPolys(polynomial L1, polynomial L2);
void DeleteList(polynomial L);
int main(void)
{
polynomial L1, L2, polysum;
L1 = InitList();
CreatList(L1);
SortListMenu();
char ch = getlet("abcd");
SortMenu(ch, L1);
puts("\nPolynomial1:");
ShowList(L1);
L2 = InitList();
CreatList(L2);
SortListMenu();
ch = getlet("abcd");
SortMenu(ch,L2);
puts("\nPolynomial2:");
ShowList(L2);
puts("\nAdd two polynomials:");
polysum = AddPolys(L1,L2);
ShowList(polysum);
DeleteList(L1);
DeleteList(L2);
DeleteList(polysum);
return 0;
}
polynomial InitList(void)
{
polynomial L;
L = (polynomial)malloc(sizeof(struct node));
if (L == NULL) {
fprintf(stderr, "Out of space!\n");
exit(EXIT_FAILURE);
}
L->next = NULL;
return L;
}
void InsertTail(int co, int ex, position r)
{
polynomial tem = (polynomial)malloc(sizeof(struct node));
tem->coef = co;
tem->expo = ex;
tem->next = r->next;
r->next = tem;
}
void CreatList(polynomial L)
{
printf("\nPlease enter coefficients and exponents (nonumeric values to stop):\n");
int co, ex;
position r = L;
while (scanf("%d %d",&co, &ex) == 2) {
InsertTail(co, ex, r);
r = r->next;
}
while (getchar() != '\n')
continue;
}
//排序算法,从大到小排序
//判断链表是否为空
int IsEmpty(polynomial L)
{
return L->next == NULL;
}
//交换两个节点的值
void SwapNode(position p, position q)
{
int co, ex;
co = q->coef;
ex = q->expo;
q->coef = p->coef;
q->expo = p->expo;
p->coef = co;
p->expo = ex;
}
//冒泡排序,优化版本,添加标志指针判断是否已经排序好
void BubbleSort(polynomial L)//优化后的冒泡排序,有一个标志指针pfalg
{
if (IsEmpty(L))
fprintf(stderr, "Empty linked link\n");
else {
position p = L->next, pflag = NULL, pend = NULL;
//p指向首节点, pflag指向每趟排序最后一次交换的位置
while (pflag != L->next) {
pflag = L->next;//每趟排序开始初始化,无交换
while (p->next != pend) {
if (p->expo < p->next->expo) {
SwapNode(p, p->next);
pflag = p;
}
p = p->next;
}
pend = pflag;//一趟排序玩,pflag指向的节点后面的节点已排序好
}
}
}
//将序列中间一个节点(ptemp 指向节点) 插入到节点(p指向节点)后面,
//节点 pbtemp 为指向待出入节点 ptemp 的前节点的指针
void InsertAfter(position p, position ptemp, position pbtemp)
{
pbtemp->next = ptemp->next;
ptemp->next = p->next;
p->next = ptemp;
}
/*快速排序
采用左闭右开,pfirst 指向排序的第一个节点,pend指向最后节点的后面,不参与排序
ppivot:基准选取第一个节点,首节点
plarge指向大于基准部分最后一个节点
psmall 初始指向ppivot指向的后一个节点,向后遍历,
遇到大于基准的节点,则将plarge后移,再交换plarge值和该节点值
一次划分完成,将基准节点与plarge指向节点值交换,因此需要记录plarge前一个节点
交换后指向plarge前一个节点的指针 ptemp 指向大于基准的最后一个节点
*/
void QuickSort(position pfirst, position pend)
//从大到小排序,pend是排序的最后一个节点的后面,不参与排序
{
if (pfirst == NULL)
return;
//如果pfirst指向的是第一个节点也是最后一个一个节点,不需要再划分
if (pfirst->next == pend)
return;
position plarge = pfirst, psmall = pfirst->next, ppivot = pfirst, ptemp = pfirst;
//ppviot指向第一个节点,第一个节点为基准节点
//psmall指向首节点后面一个节点,从基准开始遍历
while (psmall != pend) {
if (psmall->expo > ppivot->expo) {
ptemp = plarge; //ptemp指向plarge前一个节点
plarge = plarge->next;
if (plarge != psmall)
SwapNode(plarge, psmall);
}
psmall = psmall->next;
}
//一次划分后,plarge指向比基准指数大的最后一个节点
//psmall指向比基准小的最后一个节点的next
//将基准ppivot与plarge交换
SwapNode(plarge, ppivot);
ppivot = plarge;//plarge指向是基准节点
plarge = ptemp;//交换后ptem指向是大于基准的最后一个节点,其后是基准节点
QuickSort(pfirst, plarge->next);
QuickSort(ppivot->next, pend);
}
/*插入排序未将已排序和未排序部分分离,待插入节点 ptem 插入到已排序序列中时,
无法直接交换值,需要将该节点插入,因此要记录该节点前一个节点 pbtemp,
插入时条件是已排序好的节点中的某一比较节点 p 系数小于待插入节点,
因此插入位置在该比较节点前面,因此需要记录比较节点的前一个节点pbefore
*/
void InsertSort(polynomial L) //从大到小排序
{
if (IsEmpty(L)) {
fprintf(stderr, "Empty linked list\n");
return;
}
position p, pbefore, ptemp = L->next->next, pbtemp = L->next;
while (ptemp != NULL) {
p = L->next;//p一开始指向第一个节点,从第一个节点开始比较
pbefore = L;//p指向的的前一个节点
while (p != ptemp && ptemp->expo < p->expo) {
pbefore = p;
p = p->next; //p向后移,往后遍历,直到比较完或者遇到比插入值小的
}
if (p == ptemp) {
pbtemp = ptemp; //pbtemp指向ptemp前一个节点
ptemp = ptemp->next;//前面值全部比ptemp指向大,无需插入
}
else { //否则,p指向值比ptemp小,在p之前,即pbefore后插入ptemp
InsertAfter(pbefore, ptemp, pbtemp);
ptemp = pbtemp->next;
}
}
}
/*
选择排序,将序列分离为两部分:已排序和未排序
已排序部分:p 指向已排序最后一个节点,初始化为指向头节点指针
未排序部分:ptmax指向未排序最大节点,ptmax = p->next
ptemp 指向待遍历的节点,初始化为ptmax->next
未排序序列向后遍历,遇到大于ptmax指向系数值时,将ptmax指向该节点,
一次遍历完成后将p向后移,并将该节点与ptmax指向值交换,pstem也向后移
*/
void SelectSort(polynomial L)
{
position p = L, ptmax, ptemp;
while (p->next != NULL) { //未排序部分不为空
ptmax = p->next;
ptemp = ptmax->next;
while (ptemp != NULL) {
if (ptemp->expo > ptmax->expo)
ptmax = ptemp;
ptemp = ptemp->next;
}
p = p->next;
SwapNode(p, ptmax);
}
}
void eatline(void)
{
while (getchar() != '\n')
continue;
}
char getlet(char *s)
{
char ch;
int ok = 1;
while (ok) {
ch = getchar();
if (getchar() != '\n') {
eatline();
printf("Enter again: ");
continue;
}
ch = tolower(ch);
if (strchr(s, ch) != NULL)
return ch;
else
printf("Enter again: ");
}
}
void SortMenu(char ch, polynomial L)
{
switch(ch) {
case 'a':
BubbleSort(L);
break;
case 'b':
QuickSort(L->next, NULL);
break;
case 'c':
InsertSort(L);
break;
case 'd':
SelectSort(L);
break;
}
}
void SortListMenu(void)
{
puts("\nSelect a sorting algorithm:");
puts("a) BubbleSort b) QuickSort");
puts("c) InsertSort d) SelectSort");
}
void ShowList(polynomial L)
{
position p = L->next;
while (p != NULL) {
if (p->coef)
printf("%dX^%d",p->coef,p->expo);
p = p->next;
if (p && p->coef > 0)
putchar('+');
}
putchar('\n');
}
//多项式相加
int cmp(int p, int q)
{
if (p < q)
return -1;
else if (p == q)
return 0;
else
return 1;
}
//在r指向的节点后面添加节点,节点的数据为p指向节点数据
void AddNode(position r, position p)
{
position tem = (polynomial)malloc(sizeof(struct node));
tem->coef = p->coef;
tem->expo = p->expo;
tem->next = r->next;
r->next = tem;
}
polynomial AddPolys(polynomial L1, polynomial L2)
{
polynomial polysum = InitList();
position r = polysum;
position p1 = L1->next, p2 = L2->next;
int sum;
while (p1 && p2) {
switch(cmp(p1->expo, p2->expo)) {
case -1:
AddNode(r, p2);
r = r->next;
p2 = p2->next;
break;
case 0:
sum = p1->coef + p2->coef;
if (sum) {
position tem = (polynomial)malloc(sizeof(struct node));
tem->coef = sum;
tem->expo = p1->expo;
tem->next = r->next;
r->next = tem;
r = r->next;
}
p1 = p1->next;
p2 = p2->next;
break;
case 1:
AddNode(r, p1);
r = r->next;
p1 = p1->next;
}
}
for (; p1 != NULL; r = r->next, p1 = p1->next)
AddNode(r, p1);
for (; p2 != NULL; r = r->next, p2 = p2->next)
AddNode(r, p2);
return polysum;
}
void DeleteList(polynomial L)
{
position p = L->next, tem;
L->next = NULL;
while (p) {
tem = p->next;
free(p);
p = tem;
}
}
测试四种排序算法:
Please enter coefficients and exponents (nonumeric values to stop):
3 3
4 4
5 2
q
Select a sorting algorithm:
a) BubbleSort b) QuickSort
c) InsertSort d) SelectSort
b
Polynomial1:
4X^4+3X^3+5X^2
Please enter coefficients and exponents (nonumeric values to stop):
6 2
7 3
3 1
q
Select a sorting algorithm:
a) BubbleSort b) QuickSort
c) InsertSort d) SelectSort
c
Polynomial2:
7X^3+6X^2+3X^1
Add two polynomials:
4X^4+10X^3+11X^2+3X^1
Please enter coefficients and exponents (nonumeric values to stop):
3 3
4 4
5 2
q
Select a sorting algorithm:
a) BubbleSort b) QuickSort
c) InsertSort d) SelectSort
a
Polynomial1:
4X^4+3X^3+5X^2
Please enter coefficients and exponents (nonumeric values to stop):
6 2
7 3
3 1
q
Select a sorting algorithm:
a) BubbleSort b) QuickSort
c) InsertSort d) SelectSort
d
Polynomial2:
7X^3+6X^2+3X^1
Add two polynomials:
4X^4+10X^3+11X^2+3X^1
双链表
#include<stdio.h>
#include<stdlib.h>
struct node;
typedef struct node *ptrtonode;
typedef ptrtonode polynomial;
typedef ptrtonode position;
struct node {
ptrtonode prev;
int coef;
int expo;
ptrtonode next;
};
polynomial InitList(polynomial L);
void CreatList(polynomial L);
void ShowList(polynomial L);
polynomial AddPolynomial(polynomial L1, polynomial L2);
void DeleteList(polynomial L);
int main(void)
{
polynomial L1, L2, polysum;
L1 = InitList(L1);//L是头指针,指向头节点
L2 = InitList(L2);
CreatList(L1); //创建多项式链表
puts("\nPolynomial1:");
ShowList(L1);
CreatList(L2);
puts("Polynomial2:");
ShowList(L2);
puts("\nAdd two polynomials:");
polysum = AddPolynomial(L1, L2);
ShowList(polysum);
DeleteList(L1);
DeleteList(L2);
DeleteList(polysum);
return 0;
}
polynomial InitList(polynomial L)
{
L = (polynomial)malloc(sizeof(struct node));//为头节点动态分配空间
L->prev = NULL;
L->next = NULL;
return L;
}
void InsertAfter(position p, position tem) //tem指向的节点插入p指向节点后面
{
tem->prev = p; //注意顺序,第一步
tem->next = p->next;
if (p->next != NULL)
p->next->prev = tem;
p->next = tem;
}
void Insert(int co, int ex, polynomial L, position r)
{
position tem, p;
p = r;
tem = (polynomial)malloc(sizeof(struct node));
if(tem == NULL) {
fprintf(stderr, "Out of space!\n");
exit(EXIT_FAILURE);
}
tem->coef = co;
tem->expo = ex;
while(p != L && ex > p->expo)
p = p->prev;
InsertAfter(p, tem);
}
int IsLast(position r)
{
return r->next == NULL;
}
void CreatList(polynomial L)
{
printf("Please enter coefficients and exponents (nonumeric to stop):\n");
int co, ex;
position r; //r始终指向尾节点
r = L;
while(scanf("%d %d",&co, &ex) == 2) {
Insert(co, ex, L, r);
if(!IsLast(r)) //r不是指向最后节点,说明插入节点位于尾部
r = r->next;
}
while (getchar() != '\n')
continue;
}
void ShowList(polynomial L)
{
position p = L->next; //p指向首节点
while(p != NULL) {
if(p->coef) //系数不为0
printf("%dX^%d",p->coef, p->expo);
p = p->next;
if(p)
if(p->coef > 0) //系数为正数加正号,负数自带负号
printf("+");
}
putchar('\n');
}
void DeleteList(polynomial L)
{
position p, tem;
p = L->next;
L->next = NULL;
while (p != NULL) {
tem = p->next;
free(p);
p = tem;
}
}
int cmp(int a, int b)
{
if (a < b)
return -1;
else if (a == b)
return 0;
else
return 1;
}
void AddNode(position r, position p) {
position tem = (polynomial)malloc(sizeof(struct node));
tem->coef = p->coef;
tem->expo = p->expo;
tem->next = r->next;
tem->prev = r;
r->next = tem;
}
polynomial AddPolynomial(polynomial L1, polynomial L2)
{
polynomial polysum = InitList(polysum);
position r = polysum;
int sum;
position p1 = L1->next, p2 = L2->next;
while(p1&&p2) {
switch(cmp(p1->expo, p2->expo)) {
case -1: //p1的系数小,因为链表从大到小排序,则将p2指向的节点添加到求和链表中
AddNode(r, p2);
r = r->next;
p2 = p2->next;
break;
case 0:
sum = p1->coef + p2->coef;
if (sum) {//系数不为0
position tem = (polynomial)malloc(sizeof(struct node));
tem->coef = sum;
tem->expo = p1->expo;
tem->prev = r;
tem->next = r->next;
r->next = tem;
r = r->next;
}
p1 = p1->next;
p2 = p2->next;
break;
case 1:
AddNode(r, p1);
r = r->next;
p1 = p1->next;
break;
}
}
for (; p1 != NULL; r = r->next, p1 = p1->next)
AddNode(r, p1);
for (; p2 != NULL; r = r->next, p2 = p2->next)
AddNode(r, p2);
return polysum;
}
测试:
Please enter coefficients and exponents (nonumeric to stop):
3 3
4
4
5 2
q
Polynomial1:
4X^4+3X^3+5X^2
Please enter coefficients and exponents (nonumeric to stop):
6 2
7 3
3 1
q
Polynomial2:
7X^3+6X^2+3X^1
Add two polynomials:
4X^4+10X^3+11X^2+3X^1