7 有序链表ADT模板简单应用算法设计:一元多项式的加/减法运算

这次的题相比之前有点难,代码有点复杂,大家尽力看明白,我也会在旁边批注。

同学们不要白嫖!                

7 有序链表ADT模板简单应用算法设计:一元多项式的加/减法运算

作者: 冯向阳时间限制: 1S章节: DS:线性表

截止日期: 2022-06-30 23:55:00

问题描述 :

目的:使用C++模板设计单链表的抽象数据类型(ADT)。并在此基础上,稍加改动,针对一元多项式建立相应的稀疏多项式ADT,使用单链表ADT的基本操作,设计并实现稀疏一元多项式的加法计算的算法设计。

内容:(1)请参照单链表的ADT模板,设计稀疏一元多项式的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考网盘中的单链表ADT原型文件,自行设计稀疏一元多项式的ADT。)

(2)ADT的简单应用:使用该ADT设计并实现稀疏一元多项式的加法计算的算法设计。

应用1:假设2个稀疏一元多项式分别由带头结点的有序单链表A和B存储。现要求设计一个算法,实现稀疏一元多项式的加减法计算。要求使用A和B的原存储空间,且计算后B不再单独存在。输入中的单链表的长度不得在计算算法中利用,仅作为建表使用。

假定:系数项的数据类型为double,指数项的数据类型为int,指数项递增有序,多项式至少有1项,系数项均不为0。

注意:加/减法计算后,如某一项的结果系数为0,则该项要从多项式链表中删除。

参考函数原型:

template<class ElemType1,class ElemType2>

void Add_Poly( poly_LinkList<ElemType> &A, poly_LinkList<ElemType> &B, int add_sub );

有序链表模板类原型(用于一元多项式计算)参考如下:

/* 单链表的结点定义 */(用于一元多项式计算)

template<class ElemType1, class ElemType2>
struct LinkNode
{
    ElemType1 factor; //系数
    ElemType2 indice;  //指数
    LinkNode<ElemType1, ElemType2> *next;
    LinkNode(LinkNode<ElemType1, ElemType2> *ptr = NULL){next = ptr;} //构造函数1,用于构造头结点
    LinkNode(const ElemType1 &item1, const ElemType2 &item2, LinkNode<ElemType1, ElemType2> *ptr = NULL) //构造函数2,用于构造其他结点  
    //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
    {
        next = ptr;
        factor = item1;
        indice = item2;
    }
    ElemType1 getFactor(){ return factor;}  //取得结点中的系数
    ElemType2 getIndice(){ return indice;}  //取得结点中的指数
    void SetLink( LinkNode<ElemType1, ElemType2> *link ){ next = link; }  //修改结点的next域
    void SetFactor( ElemType1 value ){ factor = value; }   //修改结点的系数
    void SetIndice( ElemType2 value ){ indice = value; }   //修改结点的指数
};

//带头结点的单链表(用于一元多项式计算)
template<class ElemType1, class ElemType2>
class poly_LinkList{
   private:
      LinkNode<ElemType1, ElemType2> *head;   // 头结点
      LinkNode<ElemType1, ElemType2> *tail;   // 尾结点
   public:
      //无参数的构造函数
      poly_LinkList(){head = new LinkNode<ElemType1, ElemType2>; tail = head;}
      //带参数的构造函数
      poly_LinkList(const ElemType1 &item1, const ElemType2 &item2 ){head = new LinkNode<ElemType1, ElemType2>(item1, item2); tail = head;}
      //拷贝构造函数
      poly_LinkList(poly_LinkList<ElemType1, ElemType2> &List);
      //析构函数
      ~poly_LinkList(){ListDestroy();}
      //销毁链表
      void ListDestroy();
      //清空链表
      void ListClear();
      //返回链表的长度
      int ListLength() const;
      //判断链表是否为空表
      bool ListEmpty() const;
      //在首节点之前插入一个结点
      bool InsFirst( ElemType1 fact, ElemType2 indi );
      //获取链表头结点
      LinkNode<ElemType1,ElemType2>* GetHead() { return head;}
      //设置链表头指针
      void SetHead(LinkNode<ElemType1,ElemType2> *p){ head = p;}     
      //设置链表尾指针
      void SetTail(LinkNode<ElemType1,ElemType2> *p){ tail = p;}      

      //获取链表尾结点
      LinkNode<ElemType1,ElemType2>* GetTail() { return tail;}
      //返回链表的第i个元素的系数值
      ElemType1 GetElem_factor(int pos);
      //返回链表的第i个元素的指数值
      ElemType2 GetElem_indice(int pos);
      //在链表的第pos个位置之前插入e元素
      bool ListInsert_prior(int pos, ElemType1 fact, ElemType2 indi);
      //在链表的第pos个位置之后插入e元素
      bool ListInsert_next(int pos, ElemType1 fact, ElemType2 indi);
      //表头插入法动态生成链表
      void CreateList_Head(vector<ElemType1> &Factor, vector<ElemType2> &Indice);     
      //表尾插入法动态生成链表
      void CreateList_Tail(vector<ElemType1> &Factor, vector<ElemType2> &Indice);    
      //删除链表的第pos个位置的元素
      ElemType2 ListDelete(int pos);
      //按序号查找,从链表的第一个结点开始,判断当前结点是否是第i个,
      //若是,则返回该结点的数据域的值;否则继续后一个,直至表结束。没有第i个结点时返回空。
      bool FindElem( int k, ElemType1 &fact, ElemType2 &indi);
      //bool compare(ElemType a, ElemType *b);
      //按值查找,即定位。从链表的第一个结点开始,判断当前结点值是否等于e。
      //若是,则返回该结点的序号;否则继续后一个,直至表结束。找不到时返回0。
      int SearchElem( const ElemType2 &e) const;
      //返回链表给定数据元素的后继数据元素的值
      bool NextElem(LinkNode<ElemType1, ElemType2> *p, ElemType1 &fact, ElemType2 &indi);
      //遍历链表
      bool ListTraverse() const;
};

输入说明 :

第一行:加/减法选择(0:加法  1:减法)

第二行:一元多项式A的各项的系数(系数之间以空格分隔)

第三行:一元多项式A的各项的指数(指数之间以空格分隔)

第四行:一元多项式B的各项的系数(系数之间以空格分隔)

第五行:一元多项式B的各项的指数(指数之间以空格分隔)

输出说明 :

见测试数据样例

输入范例 :

0
7.1 3.2 -22.3 9 5 -8
0 1 7 8 17 100
-3.2 22 -9
1 7 18

输出范例 :

7.1+3.2x-22.3x^7+9x^8+5x^17-8x^100
-3.2x+22x^7-9x^18

7.1-0.3x^7+9x^8+5x^17-9x^18-8x^100

-------------------------------------------------------------------------

Donghua University Online Judge 1.0

Copyright © 2015-2016 . All Rights Reserved.

技术支持:Turbo Email:11249242@qq.com

-------------------------------------------------------------------------

        代码有点长但是 思路比较简单,请同学们耐心看完.

#include<iostream>
using namespace std;
struct student
{
	double coe;//coe是coefficient的简称,coefficient中文是系数的意思
	int power;//power是次方的意思
	student* next = NULL;
};//每个节点的名字

void creat(student& a)
{
	student* p = &a;
	double j = 0;
	while (cin >> j)
	{
		student* r = new student;
		r->coe = j;
		p->next = r;
		p = r;
		if (cin.get() == '\n')
		{
			break;
		}
	}//识别到回车 停止输入系数
	int i;
	p = a.next;
	while (cin >> i)
	{
		p->power = i;
		p = p->next;
		if (cin.get() == '\n')//
		{
			break;
		}//识别到回车 停止输入次方
	}
}//创建一个线性表(单链表)

void display(student& a)
{
	student* p = a.next;
	int h = 0;
	while (p != NULL)
	{
		if (p->coe > 0)
		{
			if (h != 0)
			{
				cout << "+";
			}//若输出的开头的一个数是个正数,那就不能在前面输出+号 +号需要被省略
			
			if (p->coe != 1)//系数不是1的时候可直接输出
			{
				cout << p->coe;
			}
			else if (p->coe == 1 && p->power == 0)//如果是1,但次方为0,直接输出数字,若次方不为0直接输出后面的x项,例如你输出1x^2是错误的  而是输出x^2
			{
				cout << p->coe;
			}
			if (p->power != 0 && p->power != 1)
			{
				cout << "x^";
				cout << p->power;
			}
			else if (p->power == 1)
			{
				cout << 'x';
			}


			h++;
		}
		else if (p->coe < 0)
		{
			if (p->coe != -1)//除了-1 都可以正常输出
			{
				cout << p->coe;
			}
			else if (p->coe == -1 && p->power != 0)//若系数是-1但次方不是0的话 直接输出-号比如 -x正确 但-1x错误
			{
				cout << "-";
			}
			else if (p->coe == -1 && p->power == 0)//同理
			{
				cout << "-1";
			}

			if (p->power != 0 && p->power != 1)
			{
				cout << "x^";
				cout << p->power;
			}
			else if (p->power == 1)
			{
				cout << 'x';
			}
			h++;
		}
		else if (p->next == NULL && p->coe == 0)
		{
			cout << 0;
		}
		p = p->next;
	}

}

void merge_plus(student& a, student& b, student& c)
{
	student* p = a.next;
	student* q = b.next;
	student* key = &c;

	while (p != NULL && q != NULL)
	{
		if (p->power < q->power)
		{
			key->next = p;
			key = p;
			p = p->next;

		}
		else if (p->power > q->power)
		{
			key->next = q;
			key = q;
			q = q->next;

		}
		else if (p->power == q->power)
		{
			p->coe = p->coe + q->coe;
			key->next = p;
			key = p;
			q = q->next;
			p = p->next;

		}
	}
	if (q != NULL)
	{
		key->next = q;
	}
	else if (p != NULL)
	{
		key->next = p;
	}
}//plus 是加法的意思

void merge_subtract(student& a, student& b, student& c)
{
	student* p = a.next;
	student* q = b.next;
	student* key = &c;

	while (p != NULL && q != NULL)
	{
		if (p->power < q->power)
		{
			key->next = p;
			key = p;
			p = p->next;

		}
		else if (p->power > q->power)
		{
			key->next = q;
			q->coe = -(q->coe);
			key = q;
			q = q->next;

		}
		else if (p->power == q->power)
		{
			p->coe = p->coe - q->coe;
			key->next = p;
			key = p;
			q = q->next;
			p = p->next;

		}
	}
	if (q != NULL)
	{
		key->next = q;
	}
	else if (p != NULL)
	{
		key->next = p;
	}
}//subtract是减法的意思

int main()
{
	int judge;
	cin >> judge;
	if (judge == 0)
	{
		student a;
		creat(a);
		student b;
		creat(b);
		display(a);
		cout << endl;
		display(b);
		cout << endl;

		student c;


		merge_plus(a, b, c);//
		cout << endl;

		display(c);
	}
	else if (judge == 1)
	{
		student a;
		creat(a);
		student b;
		creat(b);
		display(a);
		cout << endl;
		display(b);
		cout << endl;

		student c;


		merge_subtract(a, b, c);//
		cout << endl;

		display(c);
	}
	return 0;

}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨骅麟(Patrick Young)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值