#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct PNode
{
	int index;			// 指数
	int coe;			// 系数
	struct PNode *next; // 指针域
} PNode, *Polynomial;

void chushihua(Polynomial &L, Polynomial &M, Polynomial &N)
{
	// todo list
	L = (Polynomial)malloc(sizeof(PNode));
	M = (Polynomial)malloc(sizeof(PNode));
	N = (Polynomial)malloc(sizeof(PNode));
	L->next = NULL;
	M->next = NULL;
	N->next = NULL;
}
void Emp(Polynomial &L)
{
	if (L->next == NULL)
		printf("链表为空表。\n");
	else
		printf("链表为非空表。\n");
}

void Length(Polynomial &L)
{
	PNode *p;
	int length = 0;
	// todo list  //while循环，不断往后移动p指针，并让length++
	p = L;
	while (p->next != NULL)
	{
		p = p->next;
		length++;
	}

	printf("链表长度为：%d\n", length);
}

// 1、构造两个按指数递增的有序链表：插入节点，创建一元多项式
void charu_1(Polynomial &L)
{
	PNode *q, *p;
	int n;
	printf("请输入你要创建的一元多项式的项数：\n");
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		p = L;
		q = (Polynomial)malloc(sizeof(PNode));
		printf("请输入第%d项的系数和指数：", i);
		scanf("%d%d", &q->coe, &q->index);
		q->next = NULL;
		while (p->next != NULL && p->next->index < q->index)
		{
			// todo list  p指针移动到最后一个结点位置
			p = p->next;
		}
		// todo list  将*q结点插入到*p结点后
		q->next = p->next;
		p->next = q;
	}
}

void xianshi(Polynomial &L)
{
	PNode *p;
	p = L;
	while (p->next != NULL)
	{
		printf("%4d", p->next->coe); // 系数
		printf("H");
		printf("%d", p->next->index); // 指数
		p = p->next;
	}
}

// 2、两个一元多项式相加
void hebiao(Polynomial &J, Polynomial &O, Polynomial &H)
{
	PNode *p = J->next, *q = O->next, *r = H, *s; // r是尾指针
	while (p != NULL && q != NULL)
	{
		if (p->index < q->index)
		{
			s = (Polynomial)malloc(sizeof(PNode));
			// todo list   //保存p指向结点的系数和指数到s所指向结点中的系数和指数中
			s->coe = p->coe;
			s->index = p->index;
			// todo list   //插入s所指向结点到r所指向结点的后面
			s->next = NULL;
			r->next = s;

			r = s;		 // 更新尾指针
			p = p->next; // 更新p指针
		}
		else if (p->index > q->index)
		{
			s = (Polynomial)malloc(sizeof(PNode));
			// todo list   //保存q指向结点的系数和指数到s所指向结点中的系数和指数中
			s->coe = q->coe;
			s->index = q->index;
			// todo list   //插入s所指向结点到r所指向结点的后面
			s->next = NULL;
			r->next = s;

			r = s;		 // 更新尾指针
			q = q->next; // 更新q指针
		}
		else
		{ // 指数相等的情况
			int sum = p->coe + q->coe;
			if (sum != 0)
			{
				s = (Polynomial)malloc(sizeof(PNode));
				// todo list   //保存p指向结点的指数到s所指向结点中的指数中
				s->index = p->index;
				// todo list   //保存sum到s所指向结点中的系数中
				s->coe = sum;
				// todo list   //插入s所指向结点到r所指向结点的后面
				s->next = NULL;
				r->next = s;
				
				r = s; // 更新尾指针
			}
			p = p->next; // 更新p指针
			q = q->next; // 更新q指针
		}
	}
	while (p != NULL)
	{ // J链表非空，还剩余有元素，把其剩余的元素插入到合表H链表后面
		s = (Polynomial)malloc(sizeof(PNode));
		// todo list  尾插
		s->coe = p->coe;
		s->index = p->index;
		s->next = NULL;
		r->next = s;
		r = s;

		p = p->next; // 更新p指针
	}
	while (q != NULL)
	{ // O链表非空，还剩余有元素，把其剩余的元素插入到合表H链表后面
		s = (Polynomial)malloc(sizeof(PNode));
		// todo list  尾插
		s->coe = q->coe;
		s->index = q->index;
		s->next = NULL;
		r->next = s;
		r = s;

		q = q->next; // 更新q指针
	}
	xianshi(H); // 新增
}

int main()
{
	Polynomial head[3];
	int i;
	for (i = 0; i < 3; i++)
	{
		head[i] = (Polynomial)malloc(sizeof(PNode)); // head[0]表示第一个一元多项式链表，head[1]为第二个一元多项式链表
	}

	int choose = -1, n;
	printf("*********************************************************\n");
	printf("**********            实验二                      *******\n");
	printf("*********************************************\n");
	printf("**********     1.初始化单链表                     *******\n");
	printf("**********     2.建立递增链表(按指数递增)         *******\n");
	printf("**********     3.显示单链表整体                   *******\n");
	printf("**********     4.求单链表长度                     *******\n");
	printf("**********     5.判断单链表是否为空               *******\n");
	printf("**********     6.求一元多项式的和                 *******\n");
	printf("**********     0.退出                             *******\n");
	printf("*********************************************************\n");
	while (choose)
	{
		printf("请输入你的选择项：\n");
		scanf("%d", &choose);
		switch (choose)
		{
		case 1:
			chushihua(head[0], head[1], head[2]);
			printf("链表已经初始化。\n");
			break;
		case 2:
			for (i = 0; i < 2; i++)
			{
				printf("创建的第%d个一元多项式：\n", i + 1);
				charu_1(head[i]); // 插入节点到指定链表
			}
			break;
		case 3:
			printf("显示第1个链表：");
			xianshi(head[0]); // 显示第1个链表
			printf("\n");
			printf("显示第2个链表：");
			xianshi(head[1]); // 显示第2个链表
			printf("\n");
			//			xianshi(head[2]); // 显示第3个链表
			//			printf("\n");
			break;
		case 4:
			printf("计算第1个链表的长度：");
			Length(head[0]); // 计算 第1个链表的长度
			printf("计算第2个链表的长度：");
			Length(head[1]); // 计算 第2个链表的长度
			//			Length(head[2]); //计算 第3个链表的长度
			break;
		case 5:
			printf("判断第1个链表是否为空：");
			Emp(head[0]); // 判断第1个链表是否为空
			printf("判断第2个链表是否为空：");
			Emp(head[1]); // 判断第2个链表是否为空
						  //			Emp(head[2]); // 判断第3个链表是否为空
			break;
		case 6:
			hebiao(head[0], head[1], head[2]);
			break;
		case 0:
			exit(0);
			break;
		}
	}
	return 0; // 程序正常退出时返回0
}
