多项式的 加法 与 乘法(C语言 单链表)

  1. 感觉被我写的复杂了,不过还是写出来了;()
  2. 自我感觉合并同类项的函数还是不错滴(因为我改了一下午从o(2^n) -> o(n^2) -> o(n));
  3. 还有就是偷了个懒需要输入两个多项式的项数。
  4. 好好学习,天天向上!Yes

输入

4 5
5 3 4 2 3 1 2 0
6 5 3 4 4 3 7 2 2 1
在这里插入图片描述

/* 单链表 */
#include <stdio.h>
#include <stdlib.h>
struct nape{/* 项 */
	int coefficient;/* 系数 */
	int exponent;/* 指数 */
	struct nape *next;
};
struct nape *creatList();/* 创建表头 */
struct nape *inputNape();/* 输入一项 */
struct nape *attach(struct nape *head, struct nape *p);/* 连接输入项 */
struct nape *search(struct nape *head, int i); /* 寻找第i项 */
int empty(struct nape *head); /* 判断是否为空 */
void delate(struct nape *head, int i);/* 删除第 i 个节点 */

void inSert(struct nape *head, struct nape *p);/* 插入到链表的末尾 */
void sertIn(struct nape *head, int i, struct nape *p); /* 插入到链表中某个节点后面,辅助插入排序 */
struct nape *waitNape(struct nape *head, int i); /* 寻找,删除,并返回第 i 项,辅助插入排序 */
void sort(struct nape *head, int len); /* 按照系数的大小排序,就是传入输入的项数(偷懒了) */
int Max(int a, int b); /* 求两数中的大的那个 */
int count(struct nape *head);/* 计算链表项数 */

struct nape *addList(struct nape *head_1, struct nape *head_2);/* 相加 */
struct nape *multiplyList(struct nape *head_1, struct nape *head_2, int n, int m);/* 相乘 */


void print(struct nape *head) { /* 打印链表 */
	struct nape *p = head->next;
	while(p) {
		printf("%d-%d ", p->coefficient, p->exponent);
		if( p->next ) {
			printf(" ");
		}
		p = p->next;
	}
	printf("\n");
}


int main(void)
{
	int n, m;
	printf("请分别输入第一个多项式和第二个多项式的项数:");
	scanf("%d %d", &n, &m); 
	/* 确定两个多项式的项数,图方便了 */
	
	struct nape *head_1, *head_2, *head_add, *head_mul;
	head_1 = creatList();/* 创建第一个链表的表头 */
	head_2 = creatList();/* 创建第二个链表的表头 */
	
	/* 输入第一个多项式的项 */
	printf("请输入第一个多项式每个项的系数与指数:\n");
	for( int i = 0; i < n; ++i){
		struct nape *p = inputNape();
		head_1 = attach(head_1, p);
	} 	
	/* 输入第二个多项式的项 */
	printf("请输入第二个多项式每个项的系数与指数:\n");
	for( int i = 0; i < m; ++i){
		struct nape *p = inputNape();
		head_2 = attach(head_2, p);
	} 

	/* 排序 */
	sort(head_1, n);
	sort(head_2, m);
	/* 计算 */
	printf("......\n"); 
	head_add = addList(head_1->next, head_2->next);
	head_mul = multiplyList(head_1->next, head_2->next, n, m);

	/* 打印 */
	printf("两式相加等于:\n"); 
	print(head_add);
	printf("两式相乘等于:\n");
	print(head_mul);
	
	return 0;
}

/* 寻找链表中的第 i 项*/ 
struct nape *search(struct nape *head, int i){
	struct nape *tail = head;
	int j = 0;
	while( j != i) {
		tail = tail->next;
		j++;
	}
	return tail;
}

/* 判断链表是否为空 */
int empty(struct nape *head){
	if( head->next == NULL ) {
		return 0;
	}
	return 1;
} 

/* 删除链表中第 i 个节点 */
void delate(struct nape *head, int i){
	if( empty(head) ) {/* 判断是否为空 */
		struct nape *pre = search(head, i - 1);/* 被删除的前一项 */
		struct nape *del = search(head, i);/* 被删除的那一项 */
		pre->next = del->next;
		free(del);
	}
}

/* 创建头结点 */ 
struct nape *creatList() {
	struct nape *head = (struct nape*)malloc(sizeof(struct nape));
	head->coefficient = 0;
	head->exponent = 0;
	head->next = NULL;
	return head;
} 

/* 输入一项 */
struct nape *inputNape() {
	struct nape *p = (struct nape*)malloc(sizeof(struct nape));
	scanf("%d %d", &p->coefficient, &p->exponent);
	p->next = NULL;
	return p;
}

/* 连接输入项,在main函数中用到,返回head。与insert(无返回值)区分 */ 
struct nape *attach(struct nape *head, struct nape *p) {
	struct nape *tail = head;
	while( tail->next ) {
		tail = tail->next;
	}
	tail->next = p;
	p->next = NULL;/* 保证结尾是NULL */
	return head;
}
 
/* 结构体中的数据拷贝 */
struct nape *copy(struct nape *a){
	struct nape *p = (struct nape*)malloc(sizeof(struct nape));
	p->coefficient = a->coefficient;
	p->exponent = a->exponent;
	p->next = NULL;
	return p;
}

/* 插入到链表中某个节点后面,辅助插入排序 */
void sertIn(struct nape *head, int i, struct nape *p) {
	struct nape *tail = search(head, i);/* 要插到这一项后面 */
	p->next = tail->next;
	tail->next = p;
} 

/* 寻找,删除,并返回第 i 项,辅助插入排序 */
struct nape *waitNape(struct nape *head, int i) {
	int t = i;
	struct nape *tail = search(head, t);
	struct nape *p = (struct nape*)malloc(sizeof(struct nape));
	p = copy(tail);/* 拷贝 */
	delate(head, t);/* 删除 */
	return p;
}

/* 这里我用的插入排序 */
void sort(struct nape *head, int len) {
	int i;
	for( i = 2; i <= len; ++i ) {
		struct nape *wait = waitNape(head, i);/* 等待插入的项 */
		for( int j = i - 1; j >= 0; --j ) {
			struct nape *judge = search(head, j);/* 正在与wait比较的那一项 */
			/* 如果找到插入位置,便插在其后面 */ 
			if( (judge->coefficient == 0 && judge->exponent == 0) || wait->exponent < judge->exponent ) {/* 如果在最前面那插入到head后面,或者插在系数第一个比他大的后面 */
				sertIn(head, j, wait);
				break;
			}
		}
	}
}

/* 插入到链表的末尾,与attach(返回插入的头结点)区分 */
void inSert(struct nape *head, struct nape *p) {
	struct nape *tail = head;
	while(tail->next) {
		tail = tail->next; 
	}
	tail->next = p;
	p->next = NULL;
} 

/* 加法运算 ,三个循环*/
struct nape *addList(struct nape *head_1, struct nape *head_2) {
	struct nape *p = head_1, *q = head_2, *head_add, *temp;
	head_add = creatList();/* 创建头结点 */
	while( p && q ) {/* 当 p 或 q 都不等于空时 */
		struct nape *temp = (struct nape*)malloc(sizeof(struct nape));
		if( p->exponent > q->exponent ) {/* 若 p 的指数大则插入 q */
			temp = copy(p);
			inSert(head_add, temp) ;
			p = p->next;
		}
		else if( p->exponent < q->exponent ) {/* 若 p 的指数大则插入 q */
			temp = copy(q);
			inSert(head_add, temp);
			q = q->next;
		}
		else{/* 若相等那么合并后插入 */
			temp->coefficient = q->coefficient + p->coefficient;
			temp->exponent = q->exponent;
			temp->next = NULL;
			inSert(head_add, temp);
			p = p->next;
			q = q->next;
		}
	}
	
	if(p) {/* 如果 p 不为空,把 p 的项全部都插入到后面 */
		while(p) {
			struct nape *temp = (struct nape*)malloc(sizeof(struct nape));
			temp = copy(p);
			inSert(head_add, temp);
			p = p->next;
		}
	}
	else{/* 如果 q 不为空,把 q 的项全部都插入到后面 */
		while(q) {
			struct nape *temp = (struct nape*)malloc(sizeof(struct nape));
			temp = copy(q);
			inSert(head_add, temp);
			q = q->next;
		}		
	}
	return head_add;
}

/* 合并同类项,有点像用在线处理 */
struct nape *mergeSimilarItems(struct nape *head){
	int counts = count(head) - 1;/* 计算链表项数 */
	sort(head, counts);/* 排序 */
	struct nape *head_merge = creatList(), 
				*p = head->next, 
				*temp = (struct nape*)malloc(sizeof(struct nape)),
				*toFree = head, 
				*pre = toFree->next;
	int c;/* 用于判断下一个与这一个是否为同类项 */
	
	/* 初始化temp,与c */
	temp->coefficient = p->coefficient;
	temp->exponent = p->exponent;
	temp->next ==NULL;
	while(counts--) {
		c = p->next->exponent;
		if(counts != 1) {/* 解决循环结束的问题 */
			if( c == p->exponent ) { /* 判断下一个是否与这一个的指数相同 */
				temp->coefficient += p->next->coefficient;	/* 相同则相加 */	
				temp->exponent = temp->exponent;
			}
			else{/* 不同则插入并创建新的结点 */
				inSert(head_merge, temp);
				temp = (struct nape*)malloc(sizeof(struct nape));
				temp->coefficient = p->next->coefficient;
				temp->exponent = p->next->exponent;
				temp->next ==NULL;
			}
		}
		else{/* 若遍历到倒数第二个 */
			if( c == p->exponent ) {/* 如果最后一个的指数等于倒数第二个,那么系数相加后插入 */
				temp->coefficient += p->next->coefficient;		
				temp->exponent = temp->exponent;
				temp->next = NULL;
				inSert(head_merge, temp);
			}
			else{/* 否则说明最后一个是单独的一项,需要单独的插入 */
				inSert(head_merge, temp);/* 先把跟倒数第二项的指数相同的项相加后插入 */
				temp = (struct nape*)malloc(sizeof(struct nape));			
				temp->coefficient = p->next->coefficient;
				temp->exponent = p->next->exponent;
				temp->next = NULL;
				inSert(head_merge, temp);/* 将最后一个单独插入 */
			}
			break; 
		}
		p = p->next;
	}
	
	/* 将原先的空间释放掉,避免内存泄漏 */
	while(toFree) {
		pre = toFree->next;
		free(toFree);
		toFree = pre;
	}
	return head_merge;/* 返回新的头结点 */
}

/* 计算链表项数,算头结点 */
int count(struct nape *head) {
	int count=0;
	struct nape *p = head;
	while(p) {
		count++;
		p = p->next;
	}
	return count;
}

/* 乘法运算 */
struct nape *multiplyList(struct nape *head_1, struct nape *head_2, int n, int m) {
	struct nape *p, *q, *head_less, *head_more, *head_mul, *temp;
	head_mul = creatList();
	
	if( n < m ) {/* 让项数少的在外层循环,提高性能 */
		head_less = head_1;
		head_more = head_2;
	}
	else{
		head_less = head_2;
		head_more = head_1;
	}
	p = head_less;
	q = head_more;
	int min = n<m?n:m;
	int max = n>m?n:m;
	
	for( int i = 0; i < min; i++ ) {/* 有头结点,让项数少的在外层循环 */
		struct nape *nape_i = search(head_less, i);/* 寻找项少的链表的第i项 */
		for( int j = 0; j < max; j++ ) {
			temp = (struct nape*)malloc(sizeof(struct nape));
			struct nape *nape_j = search(head_more, j);/* 寻找项多的链表的第j项 */
			temp->coefficient = nape_i->coefficient * nape_j->coefficient;/* 系数相乘 */
			temp->exponent = nape_i->exponent + nape_j->exponent;/* 指数相加 */
			temp->next = NULL;
			inSert(head_mul, temp);/* 插入 */
		}
	}
	head_mul = mergeSimilarItems(head_mul);/* 合并同类项 */
	return head_mul; 	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值