数据结构与算法分析 C 语言描述第二版第三章——链表实现多项式相加

数据结构与算法分析 C 语言描述第二版第三章——链表实现多项式相加

要求:
多项式指数按照从大到小顺序排列,计算求和多项式后不会破坏原有输入的两个多项式

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
发布了120 篇原创文章 · 获赞 2 · 访问量 5798

猜你喜欢

转载自blog.csdn.net/Lee567/article/details/103551546
今日推荐