【数据结构】一元多项式的表示与相加(无序输入 有序输出)

一元多项式的表示与运算——课程设计(无序输入 有序输出)


主要内容:用线性表表示一元多项式。实现一元多项式的相加、求导、求值、相减等运算

相加算法实现:首先确定表示一元多项式的线性表的存储方式----顺序存储结构,链式存储结构均可;

两种存储方式:顺序存储结构链式存储结构(本文采用链式存储方式解题)

  1. 一元多项式的指数很高且相邻的指数相差很大时,宜只存放系数非零项的系数和相应的指数,否则浪费存储,且系数非零项仍按指数升序排列方便运算实现。(存储中根据系数的稀疏性来选择)
  2. 对于次数低的,方便多项式之间的运算,可采用按项顺序存储的形式。

一.例题:(输入无序,指数升序排列的一元多项式)

【问题描述】读入一元多项式中每一项的系数和指数,建立单链表存放输入的一元多项式,写出遍历单链表输出所存放的一元多项式,一元多项式相加,求一元多项式的值,删除一元多项式中指定项等相关操作
【输入形式】x的值,2个一元多项式各项(顺序随意),要删除相加后多项式的指数项

【样例输入1】

2 
-1 0 8 3 10 8 2 20 0 0
1  0 5  3  6  2  2 20 0 0
8

在这里插入图片描述

【样例说明1】 输入: 第1行的2是一元多项式x的值 第2行和第3行是两个一元多项式每一项的系数和指数,不要求有序输入,以0 0结束
第4行是删除的相加后多项式的指数项

输出 第1、2、3行,参照例子 第4行为删除相加后指数项之后的多项式.

【样例输入2】

2
1 2 3 5 4 3 0 0
2 0 -3 5 3 3  2 1 0 0
3

在这里插入图片描述

1. 链表结点定义

/* 链表结点定义 */
typedef struct LNode{
    int exp, coef; //coef为指数, exp为系数
    struct LNode *next;
}LNode, *LinkList;

2. 创建单链表存放一元多项式(将无序的输入有序存放于链表)

/* 创建单链表存放一元多项式*/
void CreateList(LinkList &L)
{ 
    L=(LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    LinkList p;
    LinkList pre=L;//
    LinkList s=L;// 尾插法的尾指针
    L->coef = 0.0;//先初始化一下
    L->exp = 0;
    //一直输入  检测到 输入0 0 的时候截至
    while(true){
        p=(LinkList)malloc(sizeof(LNode));
        p->next=NULL;
        if(p==NULL) return;//是否开辟成功
        scanf("%d",&p->coef);
        scanf("%d",&p->exp);
        if(!p->exp&&!p->coef){
            free(p); //如果输入有误 就把多开辟的空间释放掉
            return;
        }
        if(p->exp>=s->exp){//输入正序的话就尾插
            s->next = p;
            s=p;
        }
        else{//输入比上一个小 说明输入无序 插入
            while(pre->next){  
                pre=pre->next;//从头向后找 插入的位置
                if(pre->next->exp>p->exp && pre->exp <= p->exp){
                    //找到插入的位置
                    p->next = pre->next;//插入
                    pre->next=p;
                    pre = L;//重置pre的指向位置 以便下一次找位置
                    break;//插入完成 退出循环
                }
            }
        }
    }
 }  

3. 输出一元多项式

//遍历单链表,格式化输出一元多项式的每一项
void Display(LinkList L)
{     
    LinkList p = L->next;
    int First_Term = 1; 
    //表示当前处理的项是否是多项式的第一项 第一项前面不需要额外正负号
    while (p != NULL) {
        if (p->exp) {
            if (!First_Term && p->coef > 0) {
                //整数加上+号
                printf("+"); 
            }
            printf("%dx^%d", p->coef, p->exp);
        } else {
            //指数为零 直接打印
            printf("%d", p->coef);
        }
        First_Term = 0; //修改标签
        p = p->next;
    }
}

4. 一元多项式求值

/* 一元多项式求值 */
double Value(LinkList L, int x)
{  
    LinkList p=L->next;
    double function_sum=0.0;
    while(p!=NULL){
        function_sum += p->coef*pow(x,p->exp);
        p=p->next;
    }
    return function_sum;
}/* 一元多项式求值 */

5. 删除一元多项式中的指定项

/*删除一元多项式中的指定项 */
void DeleteElem(LinkList &L, int e)
{     
//在这里插入你的代码
    LinkList p=L->next;//线性表的第一个数据元素
    //p在前面 探路
    LinkList q=L;// q指向 p的前驱结点地址 

    while(p!=NULL){
        if(p->exp==e){//发现指定指数项
            q->next=p->next;//删除该项
            free(p);
            return;
        } 
        else{
        //未发现该指数项 两指针后移 继续探寻
            q=p;
            p=p->next;
        }
    }
}//DeleteElem

6. 实现两个一元多项式相加 ha = ha + hb

//ha = ha + hb 
void  AddPoly(LinkList ha,LinkList hb)
{  
    LinkList pa = ha->next;//探路
    LinkList pb = hb->next;//探路
    LinkList p = ha;// p指向 pa的前继结点 
    while(pa&&pb){
        if(pa->exp<pb->exp){
        //情况一:当ha中该项的指数小时 指针p 和 pa 直接向后移动一位
            p = pa;//后移
            pa=pa->next;//后移
        }
        else if(pa->exp>pb->exp){
        //情况二:当ha中该项的指数大时 需要将hb中该节点 连接进来
        //接入: 指针p 的后继指向pb  pb的后继指向pa  
        //后移: p 、pb均向后移动一位
            hb->next=pb->next;//ha 拿走该pb指向的这个结点

            pb->next=pa;//接入: 指针p 的后继指向pb  pb的后继指向pa  
            p->next=pb;

            p=pb;//后移: p 、pb均向后移动一位
            pb=hb->next;
        }
        else{
        //情况三:相等的时候 需要求和
            pa->coef +=pb->coef;//求和:放入ha中

            hb->next=pb->next;//该pb指向的节点直接删 他的系数已经被ha加上了
            free(pb);//释放空间
            pb=hb->next;//更新pb的指向

            if(pa->coef){
                //不为零时 正常后移
                p = pa;
            }
            else{//删除相加后 系数为0 的项
            //系数为零时
            // 节省储存空间
                p->next = pa->next;
                free(pa);//这个释放的原理 要搞清楚
                //更新pa的指向
            }
            pa=p->next;//更新pa的指向 pa
        }
    }
    p->next = pa?pa:pb;//接入剩余的结点
    free(hb);//释放空间
} 

二.例题:(有序)指数升序排列输出一元多项式

从键盘读入一元多项式中每一项的系数和指数,请编写算法实现(类C语言算法描述,不是完整程序代码):

(1)建立带表头结点的单链表存放一元多项式(按照指数升序排列); void CreatePoly(LinkList &pa)
(2)输出一元多项式的所有数据元素(按照指数升序输出每一系数非0项的系数和指数); void Display(LinkList pa)
(3)输入自变量的值,计算一元多项式的值; int Evaluation(LinkList pa, int
x),pa为头结点,x为自变量,返回值为一元多项式的值 (4)输入两个一元多项式,求一元多项式的和多项式(不是求值)。 void
AddPoly(LinkList ha,LinkList hb),结果放入ha链表

1. 链表结点定义

typedef struct Node{
    float coef_num;//系数的值
    int expn_num;//指数的值
    struct Node *next;
}Term,*LinkList;
//使用链表

2. 创建单链表存放一元多项式(按照指数升序排列)

//(1)建立带表头结点的单链表存放一元多项式(按照指数升序排列);

//循环截至条件 按个数输入 
void CreatePoly(LinkList &pa) 
{
    int m;
    cout<<"请输入 一元多项式的项数"<<endl;
    cin>>m;
    pa=(LinkList)malloc(sizeof(Node));
    pa->next = NULL;
    LinkList p;
    LinkList s=pa;
    pa->coef_num = 0.0;;
    pa->expn_num = 0;
    // 输入到指定 个数停止
    for(int i = 0; i < m; i++){
        p=(LinkList)malloc(sizeof(Node));
        p->next=NULL;
        if(p==NULL) return;
        cin>>p->coef_num;
        cin>>p->expn_num;
        //尾插法
        s->next = p;
        s=p;
    }

}

void CreatePoly1(LinkList &pa) 
{
    cout<<"请输入 一元多项式的系数(系数不为零) 和 指数(输入0 0时停止)"<<endl;
    pa=(LinkList)malloc(sizeof(Node));
    pa->next = NULL;
    LinkList p;
    LinkList s=pa;
    pa->coef_num = 0.0;
    pa->expn_num = 0;
    //一直输入  检测到 输入0 0 的时候截至
    while(true){
        p=(LinkList)malloc(sizeof(Node));
        p->next=NULL;
        if(p==NULL) return;
        cin>>p->coef_num;
        cin>>p->expn_num;
        if(!p->expn_num&&!p->coef_num){
            free(p);
            return;
        }
        //尾插法
        s->next = p;
        s=p;
    }

}

3. 按升序输出一元多项式

//(2)输出一元多项式的所有数据元素(按照指数升序输出每一系数非0项的系数和指数); 
void Display(LinkList pa) {
    LinkList p=pa->next;

    while(p!=NULL){
        cout<< p->coef_num<<" "<<p->expn_num<<endl;//格式
        p=p->next;
    }
}

4. 计算一元多项式的值

//输入自变量的值,计算一元多项式的值; 
float Evaluation(LinkList pa, int x){
//pa为头结点,x为自变量,返回值为一元多项式的值 
    LinkList p=pa->next;
    float function_sum=0.0;
    while(p!=NULL){
        function_sum += p->coef_num*pow(x,p->expn_num);
        p=p->next;
    }
    return function_sum;
}

5. 实现两个一元多项式相加 ha = ha + hb

void AddPoly1(LinkList ha, LinkList hb){
    LinkList pa = ha->next;//探路
    LinkList pb = hb->next;//探路
    LinkList p = ha;// pa的前继结点 //
    while(pa&&pb)
        if(pa->expn_num<pb->expn_num){
            //情况一:当ha中该项的指数小时 指针p 和 pa 直接向后移动一位
            p=pa;
            pa=pa->next;
        }
        else if(pa->expn_num == pb->expn_num){ 
        //情况二:相等的时候 需要求和
            pa->coef_num += pb->coef_num;//求和:放入ha中

            hb->next=pb->next;//该pb指向的节点直接删 他的系数已经被ha加上了
            free(pb);
            pb=hb->next;
            
            if(!pa->coef_num){ //判断加和后系数是否为零
            //系数为零的情况 删除pa指向的这个结点
                p->next=pa->next;
                free(pa);//pa指向的释放了这个地址
                pa=p->next; 
            }
            else{
                //如果不为零 正常后移
                p=pa;
                pa=pa->next;
            }
        }

        else{ 
        //情况三:当ha中该项的指数大时 需要将hb中该节点 连接进来
        //接入: 指针p 的后继指向pb  pb的后继指向pa  
        //后移: p 、pb均向后移动一位
            hb->next=pb->next;//ha 拿走该pb指向的这个结点

            pb->next=pa;//接入: 指针p 的后继指向pb  pb的后继指向pa  
            p->next=pb;

            p=pb;//后移: p 、pb均向后移动一位
            pb=hb->next;
        }

        if(pb) p->next=pb;//接入剩余的结点

        free(hb);
}
  • 28
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Chen_devy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值