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