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

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

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

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

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

注意:加/减法计算后,如某一项的结果系数为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 ElemType1 &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>;}
      //带参数的构造函数
      poly_LinkList(const ElemType1 &item1, const ElemType2 &item2 ){head = new LinkNode<ElemType1, ElemType2>(item1, item2);}
      //拷贝构造函数
      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;}     
      //获取链表尾结点
      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(int n, ElemType1 *fact, ElemType2 *indi);     
      //表尾插入法动态生成链表
      void CreateList_Tail(int n, ElemType1 *fact, ElemType2 *indi);    
      //删除链表的第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的各项的系数(系数之间以空格分隔)

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

第五行:一元多项式B的项数

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

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

输出说明 :

第一行:多项式A的第一项的系数、指数(以空格分隔)

第一行:多项式A的第二项的系数、指数(以空格分隔)

...

第n行:多项式A的第n项的系数、指数(以空格分隔) (假设多项式A的项数为n)

第一行:多项式B的第一项的系数、指数(以空格分隔)

第一行:多项式B的第二项的系数、指数(以空格分隔)

...

第m行:多项式B的第m项的系数、指数(以空格分隔) (假设多项式B的项数为m)

第一行:加/减法计算后,结果多项式A的第一项的系数、指数(以空格分隔)

第一行:加/减法计算后,结果多项式A的第二项的系数、指数(以空格分隔)

...

第p行:加/减法计算后,结果多项式A的第n项的系数、指数(以空格分隔) (假设结果多项式的项数为p)

(输入与输出之间以空行分隔,多项式之间以空行分割)

输入范例 :

1
6
7 3 -22 9 5 -8
0 1 7 8 17 100
3
8 22 -9
1 7 8
输出范例 :

7 0
3 1
-22 7
9 8
5 17
-8 100

8 1
22 7
-9 8

7 0
-5 1
-44 7
18 8
5 17
-8 100

#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;

/* 单链表的结点定义 */

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( ElemType1& item1,  ElemType1& 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 = NULL;   // 头结点
    LinkNode<ElemType1, ElemType2>* tail = NULL;   // 尾结点
public:
    //无参数的构造函数
    poly_LinkList() { head = new LinkNode<ElemType1, ElemType2>; }
    //带参数的构造函数
    poly_LinkList( ElemType1& item1,  ElemType2& item2) { head = new LinkNode<ElemType1, ElemType2>(item1, item2); }
    //拷贝构造函数
    poly_LinkList(poly_LinkList<ElemType1, ElemType2>& List);
    //析构函数
    ~poly_LinkList() { ListDestroy(); }
    //销毁链表
    void ListDestroy()
    {
        LinkNode<ElemType1, ElemType2>* p = head;
        while (p != NULL)
        {
            head = p;
            p = p->next;
            delete head;
        }
    }
    //清空链表
    void ListClear();
    //返回链表的长度
    int ListLength() ;
    //判断链表是否为空表
    bool ListEmpty() ;
    //在首节点之前插入一个结点
    bool InsFirst(ElemType1 fact, ElemType2 indi);
    //获取链表头结点
    LinkNode<ElemType1, ElemType2>* GetHead() { return head; }
    //设置链表头结点
    void SetHead(LinkNode<ElemType1, ElemType2>* p) { head = 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(int n, ElemType1* fact, ElemType2* indi);
    //表尾插入法动态生成链表
    void CreateList_Tail(int n, ElemType1* fact, ElemType2* indi)
    {
        LinkNode<ElemType1, ElemType2>* p = head;
        for (int i = 0;i < n;i++)
        {
            tail = new LinkNode<ElemType1, ElemType2>;
            tail->factor = fact[i];
            tail->indice = indi[i];
            p->next = tail;
            p = p->next;
        }
    }
    //删除链表的第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( ElemType2& e) ;
    //返回链表给定数据元素的后继数据元素的值
    bool NextElem(LinkNode<ElemType1, ElemType2>* p, ElemType1& fact, ElemType2& indi);
    //遍历链表
    bool ListTraverse()
    {
        LinkNode<ElemType1, ElemType2>* p = head->next;
        if (p == NULL)return false;
        while (p)
        {
            cout << p->factor << " " << p->indice << endl;
            p = p->next;
        }
        return true;
    }
};

template<class ElemType1,class ElemType2>
void Add_Poly(poly_LinkList<ElemType1,ElemType2>& A, poly_LinkList<ElemType1, ElemType2> & B, int add_sub)
{
    if (add_sub == 0)add_sub = 1;
    else add_sub = -1;
    LinkNode<ElemType1, ElemType2>* pre1 = A.GetHead(), * pre2 = B.GetHead();
    LinkNode<ElemType1, ElemType2>* p = A.GetHead()->next, * q = B.GetHead()->next;
    while (q != NULL)
    {
        if (q->getIndice() == p->getIndice())
        {
            p->SetFactor(p->getFactor() + add_sub * q->getFactor());
            delete pre2;
            pre2 = q;
            q = q->next;
        }
        else if (q->getIndice() < p->getIndice()) 
        {
            delete pre2;
            pre2 = q;
            q = q->next;
            pre1->next = pre2;
            pre2->SetFactor(pre2->getFactor() * add_sub);
            pre2->next = p;
            pre1 = pre2;
        }
        else 
        {
            pre1 = p;
            p = p->next;
        }
    }
    for (pre1 = A.GetHead(), p = pre1->next;p != NULL;)
    {
        if (p->getFactor() == 0)
        {
            pre1->next = p->next;
            delete p;
            p = pre1->next;
            continue;
        }
        pre1 = p, p = p->next;
    }
    B.SetHead(NULL);
}

template<class ElemType1, class ElemType2>
void input(int& n, ElemType1* fact, ElemType2* indi)
{
    cin >> n;
    for (int i = 0;i < n;i++)
        cin >> fact[i];
    for (int i = 0;i < n;i++)
        cin >> indi[i];
}

int main()
{
    typedef int ElemType1;
    typedef int ElemType2;
    int add_sub;
    int n = 0;
    ElemType1 fact[1000];
    ElemType2 indi[1000];
    cin >> add_sub;
    poly_LinkList<ElemType1, ElemType2>A, B;
    input(n, fact, indi);
    A.CreateList_Tail(n, fact, indi);
    input(n, fact, indi);
    B.CreateList_Tail(n, fact, indi);

    A.ListTraverse();
    cout << endl;
    B.ListTraverse();
    cout << endl;
    Add_Poly(A, B, add_sub);
    A.ListTraverse();
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348