纪念一下,目前写过的最长的程序,比上次作业题airport还长(๑╹◡╹)ノ"""
现在写完了,回想一下也不难,比起难度还是繁琐多一点。
不过做程序员就是要细心啊,再繁琐也不能出错。
所以做完这个感觉自己离成为程序员又近了一步,撒花✿✿ヽ(°▽°)ノ✿

下面进入正题。

题目

写一个程序,功能如下:

输入下列一个指令,实现所描述的功能:
[ ? ] 读入一个多项式,这个多项式包含一个含x的单项式和一个常数项,常数项可以为0。
[ + ] 对栈中最上面的两个多项式做加法,并把结果再压入栈中。
[ - ] 对栈中最上面两个元素做减法,并把结果再压入栈中。
[ * ] 取出栈顶多项式,再输入一个多项式,做乘法,结果压入栈中。
[ = ] 展示栈顶元素。
[ q ] 退出程序。

运行示例:

①功能索引,我选择 [ ? ] —— 读入一个多项式。
②我在这里先输入了 x^2+3 。C语言 多项式计算 链表与栈的综合应用
③ 再选择[ ? ] ,读入了 2x^2 。
C语言 多项式计算 链表与栈的综合应用
④ 选择[ + ], 让刚读入的两个多项式做加法,把结果压入栈。
C语言 多项式计算 链表与栈的综合应用
⑤ 选择[ * ],取出栈顶多项式,与我现在输入的 7x^3 做乘法,把结果压入栈。
C语言 多项式计算 链表与栈的综合应用

代码&思路

一.从大方向上看,多项式的存储用链表。栈中元素类型是链表头指针。

多项式是由一个个单项式组成的,对于同一个未知数而言,单项式特征值只有倍数和指数。
所以链表结点定义如下:

struct xiang{
    double beishu;
    int degree;
    struct xiang * next;
};
二. 实现这个程序所示的功能,我用到了如下函数:

①打印索引,无需赘述。

void print_introductions();
void print_introduction_1();

②创建一个多项式。

struct xiang* creat_a_term();

③打印多项式。

void show_the_term(struct xiang *head);

④做运算的函数,返回值是储存计算结果多项式的链表的头指针。

struct xiang* add_two_terms(struct xiang *head1, struct xiang *head2);
struct xiang* minus_two_terms(struct xiang *head1, struct xiang *head2);
struct xiang* multiply_two_terms(struct xiang *head1, struct xiang *head2);

⑤用于化简多项式的函数,把指数相同的项合并。

void simplify(struct xiang *head);
三.函数具体讲解,以及我遇到的问题。

①创建一个多项式。
(因为题目中输入的多项式最多只有两项,所以这是个只有两个结点的链表)
注意不要忘记把后一个结点的next指针设置成NULL!
我一开始忘记了,结果后面调用show_the_term函数的时候程序会异常退出。找了好久才找到orz…

struct xiang * creat_a_term(){
    struct xiang *head=(struct xiang*)malloc(sizeof(struct xiang));
    printf("coefficient?");
    scanf("%lf",&head->beishu);
    printf("exponent?");
    scanf("%d",&head->degree);

    head->next=(struct xiang*)malloc(sizeof(struct xiang));

    printf("coefficient?");
    scanf("%lf",&head->next->beishu);

    if(head->next->beishu==0)
    {
        head->next->degree=0;
        head->next->next=NULL;	/**这个地方易出错**/
        return head;
    }
    else{
        printf("exponent?");
        scanf("%d",&head->next->degree);
        if((head->next->degree)!=0)
        {
            printf("Bad exponent: Polynomial terminates without its last term.\n");
            head->next->beishu=0;
        }
    }
    head->next->next=NULL;	/**还有这**/
    return head;
};

②打印多项式。
emm怎么说呢,也挺麻烦,要考虑什么时候显示x,什么时候显示x的系数和指数,什么时候显示加号,什么时候显示减号……
不过抛开那些我这里新学了一招:
用%g打印double类型浮点数,会自动去除多余的零,非常简洁。

void show_the_term(struct xiang *head){
    struct xiang *p=head;
    double coefficient;
    int exponent;
    printf("   ");
    while(p!=NULL)
    {
        coefficient=p->beishu;
        exponent=p->degree;
        if(coefficient!=0)
        {
            if((coefficient!=1&&coefficient!=-1)||exponent==0)
            {
                if(coefficient<0)
                    printf("%g",-coefficient);
                else
                    printf("%g",coefficient);
            }
            if(exponent!=0)
                printf("x");
            if(exponent!=0&&exponent!=1)
                printf("^%d",exponent);
        }
        if(p->next!=NULL&&p->next->beishu > 0)
                printf(" + ");
        if(p->next!=NULL&&p->next->beishu < 0)
                printf(" - ");
        p=p->next;
    }
    printf("\n");
}

③实现多项式运算。

加法:
思想很朴素,就是把q链表连到p链表末。因为我们有化简函数,所以即便有可以合并的同类项也不用在这里写。化简函数NB!!(破音

struct xiang* add_two_terms(struct xiang *head1, struct xiang *head2){
    struct xiang *p;
    for(p=head1; p->next!=NULL; p=p->next);
    p->next=head2;
    return head1;
}

减法:
思路与加法相同,把q的每一项的倍数乘以-1,再连接到p链表末。

struct xiang* minus_two_terms(struct xiang *head1, struct xiang *head2){
    struct xiang *p, *q;
    for(q=head2; q!=NULL; q=q->next)
        q->beishu = -1 * (q->beishu);
    for(p=head1; p->next!=NULL; p=p->next);
    p->next=head2;
    return head1;
}

乘法:
思路也非常朴素,两个循环遍历两个链表,使多项式q中的每一项与多项式p的每一项相乘(倍数相乘,指数相加),相乘结果用一个新链表储存。
需要小小注意一下,这里为了循环更好写,新链表的头结点是没有储存我们的计算结果的,所以返回值是新链表的第二个结点。

struct xiang* multiply_two_terms(struct xiang *head1, struct xiang *head2){
    struct xiang *p, *q,*result,*r;
    result=(struct xiang*)malloc(sizeof(struct xiang));
    r=result;
    for(q=head1;q!=NULL;q=q->next)
        for(p=head2;p!=NULL;p=p->next)
        {
            r->next=(struct xiang*)malloc(sizeof(struct xiang));
            r=r->next;
            r->beishu=q->beishu * p->beishu;
            r->degree=q->degree + p->degree;
        }
    r->next=NULL;	//不要忘记哦
    return result->next;
}

④肥肠好用的化简函数。
思路就是两个循环遍历这一个链表,指数相等则倍数相加,相加结果储存在其中一项中,另一项置零。
其实倍数置零就OK,但我保险起见还是都置零好了。

void simplify(struct xiang *head){
    struct xiang *p,*q;
    for(p=head;p!=NULL;p=p->next)
        for(q=head;q!=NULL;q=q->next)
        {
            if(p!=q && q->degree == p->degree)
            {
                p->beishu += q->beishu;
                q->beishu=0;
                q->degree=0;//没有也行
            }
        }
}
四.简单的主函数。
int main(){
    char command;
    stack< struct xiang* > terms;
    struct xiang *p,*q,*r;

    printf("This is a polynomials program.\n");
    print_introductions();
    scanf("%s",&command);
    while(command!='q')
    {
        switch(command)
        {
            case '?':
                print_introduction_1();
                p=creat_a_term();
                simplify(p);
                terms.push(p);
                printf("The following Polynomial has been pushed into the stack:\n");
                show_the_term(p);
                break;

            case '=':
                if(!terms.empty())
                {
                    p=terms.top();
                    show_the_term(p);
                }
                else
                    printf("empty stack!\n");
                break;

            case '+':
                if(!terms.empty())
                {
                    p=terms.top();
                    terms.pop();
                    if(!terms.empty())
                    {
                        q=terms.top();
                        terms.pop();
                        add_two_terms(p,q);
                        simplify(p);
                    }
                    show_the_term(p);
                    terms.push(p);
                }
                else printf("empty stack!\n");
                break;

            case '-':
                if(!terms.empty())
                {
                    p=terms.top();
                    terms.pop();
                    if(!terms.empty())
                    {
                        q=terms.top();
                        terms.pop();
                        minus_two_terms(p,q);
                        simplify(p);
                    }
                    terms.push(p);
                    show_the_term(p);
                }
                else printf("empty stack!\n");
                break;

            case '*':
                if(!terms.empty())
                {
                    p=terms.top();
                    terms.pop();
                }
                else printf("empty stack!\n");
                q=creat_a_term();
                r=multiply_two_terms(p,q);
                simplify(r);
                terms.push(r);
                show_the_term(r);
                break;
            default :
                print_introductions();
        }
        printf("\nSelect command and press <Enter>:\n");
        scanf("%s",&command);
    }
}

我的运行结果

C语言 多项式计算 链表与栈的综合应用
C语言 多项式计算 链表与栈的综合应用

‘’
以上就是我的解答。
今上午以为自己写的足够好了,结果下午在写这篇博客的时候仍是发现了很多不周之处。
也许这就是写博客的好处吧,小黄鸭debug法 (๑╹◡╹)ノ"""

‘’
——2019.3.31 于图书馆

相关文章:

  • 2021-05-24
  • 2022-01-27
  • 2022-12-23
  • 2021-09-28
  • 2021-06-01
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-11-21
  • 2021-11-21
  • 2022-12-23
  • 2021-11-18
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案