朝花夕拾:回顾我的数据结构课程设计-基于C/C++/QT一元稀疏多项式计算器

5 篇文章 0 订阅
1 篇文章 0 订阅

1. 选题背景

本文回顾了我在大学期间进行的一个数据结构课程设计,要求设计一个一元稀疏多项式的计算器。这对测试我们的数据结构知识有帮助。
完整文档链接: 基于C/C++/QT的一元稀疏多项式简单计算器系统说明书
Github链接: 基于C/C++/QT的一元稀疏多项式简单计算器系统

在这里插入图片描述

2. 系统设计

2.1 系统需求

  • 输入并建立多项式
  • 输出多项式,按指数降序排列
  • 实现多项式的加减运算
  • 规范格式化地输出结果

2.2 模块设计

  • 界面模块:实现计算器界面,接收输入调用运算模块
  • 运算模块:实现多项式创建、运算、输出等核心功能
  • 数据模块:使用链表存储多项式数据
    在这里插入图片描述

3. 核心算法

3.1 多项式创建

  1. 将输入存储在二维数组
  2. 对数组排序
  3. 存入链表,合并指数相同项

3.2 多项式加减

  1. 遍历两个多项式链表
  2. 指数相同则运算,不同则依次存入结果链表
  3. 按指数降序输出结果链表
    在这里插入图片描述

4. 核心代码

4.1 程序中编写的的头文件

4.1.1 func.h
#ifndef FUNC_H
#define FUNC_H
# include <stdio.h>
# include <malloc.h>
# include <stdlib.h>
# include <string.h>
class func
{
public:
    func();
};
#endif // FUNC_H
4.1.2 widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QStack>
#include <string.h>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void on_pushButton0_clicked();
    void on_pushButton1_clicked();
    void on_pushButton2_clicked();
    void on_pushButton3_clicked();
    void on_pushButton4_clicked();
    void on_pushButton5_clicked();
    void on_pushButton6_clicked();
    void on_pushButton7_clicked();
    void on_pushButton8_clicked();
    void on_pushButton9_clicked();
    void on_pushButton_add_clicked();
    void on_pushButton_sub_clicked();
    void on_pushButton_x_clicked();
    void on_pushButton_more_clicked();
    void on_pushButton_left_clicked();
    void on_pushButton_right_clicked();
    void on_pushButton_clear_clicked();
    void on_pushButton_del_clicked();
    void on_pushButton_equal_clicked();
private:
    Ui::Widget *ui;
    QString expression;
    int Priority(char ch);
};
#endif // WIDGET_H

4.2 程序中调用的头文件、全局变量、程序中通用的符号常量

#include "func.h"
#include "widget.h"
#include <QApplication>
#include "ui_widget.h"
#include <QDebug>
typedef struct  LNode {
    int  coef;//系数
    int  exp;//指数
    struct  LNode *next;
} node;
char s[1280];
int e1[1280][2];
int e2[1280][2];	

4.3 所有代码及函数的原型,功能、参数的意义

4.3.1 func.cpp
4.3.1.1 该程序头文件调用情况;
#include "func.h"
4.3.1.2 node *CCreate(int n, int e[][2])
node *CCreate(int n, int e[][2]) {
    node *head, *p, *q;
    head = (node *)malloc(sizeof(node));
    p = q = head;
    head->next = NULL;
    int i, j, k, t1, t2;
    for (j = 0; j < n - 1; j++) { //冒泡排序
        for (k = 0; k < n - j - 1; k++) {
            if (e[k][1] == e[k + 1][1]) {//当指数相等,系数相加(减)
                e[k][0] += e[k + 1][0];
                e[k + 1][1] = 0;
                e[k + 1][0] = 0;
            } else if (e[k + 1][1] > e[k][1]) {
                t1 = e[k + 1][1];
                t2 = e[k + 1][0];
                e[k + 1][1] = e[k][1];
                e[k + 1][0] = e[k][0];
                e[k][1] = t1;
                e[k][0] = t2;
            }
        }
    }
    for (i = 0; i < n; i++) {
        if (e[i][0] != 0) {
            q = (node *)malloc(sizeof(node));
            if (!q)
                exit(-1);
            q->coef = e[i][0];
            q->exp = e[i][1];
            p->next = q;
            q->next = NULL;
            p = q;
        }
    }return head;
}
4.3.1.3 void Listadd(node *listya, node *listyb)
void Listadd(node *listya, node *listyb) { //ya=a1*x^t1+a2*x^t2;yb=b1*x^n1+b2*x^n2
    node *p, *q, *pre, *temp;
    int  sum = 0;;
    p = listya->next;
    q = listyb->next;
    pre = listya;
    while (p && q) {
        if (p->exp > q->exp) {
            pre->next = p;//确定下一项
            pre = p;//新表尾
            p = p->next;//p继续遍历
        } else if (p->exp < q->exp) {
            pre->next = q;
            pre = q;
            q = q->next;
        } else { //两项系数相等
            sum = p->coef + q->coef;
            if (sum) {//!=0
                p->coef = sum;//存入p(lya)
                pre->next = p;//确定下一项
                pre = p;//新表尾
                p = p->next;//p继续遍历
                temp = q->next;//去尾标记下一项
                free(q);  //将yb链中相应项释放掉,和放到ya链中
                q = temp;//新链接
            } else { //sum==0删除两个空项
                temp = p->next;
                free(p);
                p = temp;
                temp = q->next;
                free(q);
                q = temp;
            }
        }
    }
    pre->next = p ? p : q;
}
4.3.1.4 char *pPrint(node *h, char *s)
char *pPrint(node *h, char *s) {//结果格式化规范输出函数
    node *p = h->next;
    int  L = 0;
    if (!p) {
        sprintf(s + L, "0");
        L = strlen(s);
    }
    if (p && p->exp == 0) {
        sprintf(s + L, "%d", p->coef);
        L = strlen(s);
        p = p->next;
    } else if (p && p->exp != 0) {
        sprintf(s + L, "%d*x^(%d)", p->coef, p->exp);
        L = strlen(s);
        p = p->next;
    }
    while (p) {
        if (p->exp != 0) {
            if (p->coef > 0)
                sprintf(s + L, "+%d*x^(%d)", p->coef, p->exp);
            else if (p->coef < 0)
                sprintf(s + L, "%d*x^(%d)", p->coef, p->exp);
            L = strlen(s);
            p = p->next;
        }
        else if (p->exp == 0) {
            if (p->coef > 0)
                sprintf(s + L, "+%d", p->coef);
            else if (p->coef < 0)
                sprintf(s + L, "%d", p->coef);
            L = strlen(s);
            p = p->next;
        }
    }
    return s;
}
4.3.2 widget.cpp
4.3.2.1 该程序头文件调用情况
#include "func.h"
#include "widget.h"
#include "ui_widget.h"
#include "func.cpp"
#include <QDebug>
4.3.2.2 计算器界面整体设计
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget) {
    ui->setupUi(this);
    this->setMaximumSize(500, 640);
    this->setMinimumSize(500, 640);
    this->setWindowTitle(tr("多项式计算器"));
QFont f("仿宋", 14);}
Widget::~Widget() {
    delete ui;
}
4.3.2.3 计算器数字按键槽函数
void Widget::on_pushButton0_clicked() {
    expression += "0";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton1_clicked() {
    expression += "1";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton2_clicked() {
    expression += "2";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton3_clicked() {
    expression += "3";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton4_clicked() {
    expression += "4";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton5_clicked() {
    expression += "5";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton6_clicked() {
    expression += "6";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton7_clicked() {
    expression += "7";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton8_clicked() {
    expression += "8";
    ui->lineEdit->setText(expression);
}
void Widget::on_pushButton9_clicked() {
    expression += "9";
    ui->lineEdit->setText(expression);
}
4.3.2.4 计算器符号按键函数
void Widget::on_pushButton_add_clicked() {
    QString operatorSignal = "+-*=^"; // 一些操作运算符
    QString laststr =  ui->lineEdit->text().right(1);
    qDebug() << laststr << endl;
//    /* 判断最后一个字符是不是不是下面这些符号 */
    bool iscontains = operatorSignal.contains(laststr, Qt::CaseSensitive); // 大小写敏感
    if (!iscontains) { // 包含
        expression += "+";
        ui->lineEdit->setAlignment(Qt::AlignLeft); // 左对齐
        ui->lineEdit->setText(expression);
    }
}
void Widget::on_pushButton_sub_clicked() {
    QString operatorSignal = "+-="; // 一些操作运算符
    QString laststr =  ui->lineEdit->text().right(1);
    qDebug() << laststr << endl;
//    /* 判断最后一个字符是不是不是下面这些符号 */
    bool iscontains = operatorSignal.contains(laststr, Qt::CaseSensitive); // 大小写敏感
    if (!iscontains || laststr == '\0') { // 包含
        expression += "-";
        ui->lineEdit->setAlignment(Qt::AlignLeft); // 左对齐
        ui->lineEdit->setText(expression);
    }
}
void Widget::on_pushButton_x_clicked() {
    QString operatorSignal = "=x"; // 一些操作运算符
    QString laststr =  ui->lineEdit->text().right(1);
    qDebug() << laststr << endl;
//    /* 判断最后一个字符是不是不是下面这些符号 */
    bool iscontains = operatorSignal.contains(laststr, Qt::CaseSensitive); // 大小写敏感
    if (!iscontains || laststr == '\0') { // 包含
        expression += "x";
        ui->lineEdit->setAlignment(Qt::AlignLeft); // 左对齐
        ui->lineEdit->setText(expression);
    }
}
void Widget::on_pushButton_more_clicked() {
    QString operatorSignal = "+-*/.=^"; // 一些操作运算符
    QString laststr =  ui->lineEdit->text().right(1);
    qDebug() << laststr << endl;
//    /* 判断最后一个字符是不是不是下面这些符号 */
    bool iscontains = operatorSignal.contains(laststr, Qt::CaseSensitive); // 大小写敏感
    if (!iscontains) { // 包含
        expression += "^";
        ui->lineEdit->setAlignment(Qt::AlignLeft); // 左对齐
        ui->lineEdit->setText(expression);
    }
}
void Widget::on_pushButton_left_clicked() {
    QString operatorSignal = "=^"; // 一些操作运算符
    QString laststr =  ui->lineEdit->text().right(1);
    qDebug() << laststr << endl;
//    /* 判断最后一个字符是不是不是下面这些符号 */
    bool iscontains = operatorSignal.contains(laststr, Qt::CaseSensitive); // 大小写敏感
    if (!iscontains || laststr == '\0') { // 包含
        expression += "(";
        ui->lineEdit->setAlignment(Qt::AlignLeft); // 左对齐
        ui->lineEdit->setText(expression);
    }
}
void Widget::on_pushButton_right_clicked() {
    QString operatorSignal = "=x^"; // 一些操作运算符
    QString laststr =  ui->lineEdit->text().right(1);
    qDebug() << laststr << endl;
//    /* 判断最后一个字符是不是不是下面这些符号 */
    bool iscontains = operatorSignal.contains(laststr, Qt::CaseSensitive); // 大小写敏感
    if (!iscontains) { // 包含
        expression += ")";
        ui->lineEdit->setAlignment(Qt::AlignLeft); // 左对齐
        ui->lineEdit->setText(expression);
    }
}
4.3.2.5 计算器清空与退格函数
void Widget::on_pushButton_clear_clicked() {
    expression.clear();
    memset(e1, 0, sizeof(e1));
    memset(e2, 0, sizeof(e2));
    ui->lineEdit->clear();
}
void Widget::on_pushButton_del_clicked() {
    expression.chop(1);
    ui->lineEdit->setText(expression);
}
4.3.2.6 void Widget::on_pushButton_equal_clicked()
void Widget::on_pushButton_equal_clicked() {
    QStack<int>  s_num, s_opt, s_more;
    QString c;
    char equation[1280] = {0};
    int i = 0, sum1 = 0, sum2 = 0;
    int fir = 0, sec = 0;//数组内元素数量
    int sec_arr = 1;
    int fir_arr = 1;
    int xflag = 0;//x前是否有系数标志:1有 0没有
    int exp_minus = 1;
    int fn = 1;
    int tnmp = 0;
    int numflag = 0;
    int errorflag=0;
    node *lista, *listb;
    QByteArray eqt;
    eqt = expression.toLatin1();//把Qstring转换成QByteArray
    strcpy(equation, eqt.data()); //data可以把QByteArray转换成const char *
    while ((equation[i] != '\0' || !s_opt.empty())&&errorflag!=1) {
        //字符串未读取结束或
        //符号栈不为空持续循环
        xflag = 0;
        if (equation[i] == '('&&equation[i-1]=='-') {//负负得正
            if (equation[i + 1] == '-'){
                fn *= -1;
                tnmp++;
                if(tnmp%2==0)
                    fn*=-1;
            }
            else if (equation[i + 1] == '+')
                    equation[i+1]='0';
        }
        if(equation[i]=='0')i++;
        if ((equation[i] >= '0' && equation[i] <= '9') || equation[i] == 'x') { //值0-9或x前无系数
            if (equation[i] != 'x') { //x前有不为1系数
                xflag = 1;
                while (equation[i] >= '0' && equation[i] <= '9') { //下一个字符是数字继续循环
                    sum1 = sum1 * 10 + equation[i] - '0'; //进位
                    i++;
                }
                if (sum1 != 0) {
                    s_num.push(fn * sum1); //入数字栈
                    sum1 = 0;
                    fn = 1;
                    numflag = 1;
                }
            }
            if (equation[i] == 'x') {
                //1: x前系数为1
                //2: 系数已入栈
                if (xflag == 0)
                    s_num.push(1);
                i++;
                if (equation[i] == '^') {
                    if (equation[i + 1] == '-') { //指数为负数
                        exp_minus = -1;
                        i++;
                    }
                    i++;
                    while (equation[i] >= '0' && equation[i] <= '9') {//下一个字符是数字继续循环
                        sum2 = sum2 * 10 + equation[i] - '0'; //进位
                        i++;
                    }
                    if (sum2 != 0) {
                        s_more.push(exp_minus * sum2); //入指数栈
                        sum2 = 0;
                        exp_minus = 1; //重置为正
                    }
                    if(equation[i]=='x'){//3x^-2x^2问题
                        errorflag=1;
                    }
                }
                else if(equation[i]=='+'||equation[i]=='-'||equation[i]=='\0'){//2x+3x
                    s_more.push(1);
                }
                else
                    errorflag=1;
            }
            else if (equation[i] != 'x' && numflag == 1) {//值为常数指数置零
                s_more.push(0);
                numflag = 0;
            }
        }
        else {
            if (s_opt.empty() || (s_opt.top() == '(' && equation[i] != ')') || Priority(equation[i]) > Priority(s_opt.top())) {
                s_opt.push(equation[i]);
                i++;
                continue;
            }
            if (s_opt.top() == '(' && equation[i] == ')') {
                s_opt.pop();
                i++;
                continue;
            }
            if ((equation[i] == ')' && s_opt.top() != '(') || Priority(equation[i]) <= Priority(s_opt.top()) || (equation[i] == '\0'&& !s_opt.empty())) {
               //符号栈内有优先级高的运算符或字符串读取结束且栈不为空
               //进入运算
                char ch = s_opt.top();
                s_opt.pop();
                switch (ch) {
                    case '+':
                    if(s_num.size()!=0){
                        if (s_num.size() == 2) {
                            //1: a+b 入a,b
                            //2: a+b+c+d+……入a,b
                            e1[fir_arr][0] = s_num.top();
                            e1[fir_arr][1] = s_more.top();
                            fir++;
                            s_num.pop();
                            s_more.pop();
                            e1[fir_arr-1][0] = s_num.top();
                            e1[fir_arr-1][1] = s_more.top();
                            fir++;
                            s_num.pop();
                            s_more.pop();
                            fir_arr++;
                            fir_arr++;
                        }else {
                            //1: -a+b入b
                            //2: a+b+c+d+……入c,d……
                            e1[fir_arr-1][0] = s_num.top();
                            e1[fir_arr-1][1] = s_more.top();
                            fir++;
                            s_num.pop();
                            s_more.pop();
                            fir_arr++;
                        }
                    }break;
                    case '-':
                    if(s_num.size()!=0){
                        if (s_num.size()  == 2) {
                            //1: a-b 入a,b
                            //2: a-b-c-d-…… 入 a,b
                            e2[sec_arr - 1][0] = -s_num.top();
                            e2[sec_arr - 1][1] = s_more.top();
                            sec++;
                            s_num.pop();
                            s_more.pop();
                            e1[fir_arr - 1][0] = s_num.top();
                            e1[fir_arr - 1][1] = s_more.top();
                            fir++;
                            s_num.pop();
                            s_more.pop();
                            sec_arr++;
                            fir_arr++;
                        }
                        else {
                            //1: -a+b 入 -a
                            //2: a-b-c-d-…… 入 c,d……
                            //3: -a-b-c-d-…… 入 a,b,c,d……
                            e2[sec_arr - 1][0] = -s_num.top();
                            e2[sec_arr - 1][1] = s_more.top();
                            sec++;
                            s_num.pop();
                            s_more.pop();
                            sec_arr++;
                        }
                    }break;
                }
            }
        }
        if(i>100){
            memset(e1, 0, sizeof(e1));
            memset(e2, 0, sizeof(e2));
            errorflag=1;
            break;
        }
    }
    if(!s_num.empty()&&fir==0&&sec==0){
        e1[fir][0]=s_num.top();
    if(!s_more.empty())
        e1[fir][1]=s_more.top();
    fir++;
    }
    if(errorflag==0){
    lista = CCreate(fir + 1, e1);
    listb = CCreate(sec + 1, e2);
    Listadd(lista, listb);
    c = QString(pPrint(lista, s));
    }
    else c = "输入有误";
    ui->lineEdit->setText(c);
    memset(e1, 0, sizeof(e1));
    memset(e2, 0, sizeof(e2));
    expression.clear();
}
4.3.2.7 int Widget::Priority(char ch)
int Widget::Priority(char ch) {
    switch (ch) {
        case '+':
        case '-':
            return 1;
        case '(':
            return 2;
        default:
            return 0;
    }
}

5. 收获与展望

  • 收获:巩固数据结构知识,提高算法设计能力
  • 展望:可以扩展更多运算,优化算法,增强健壮性

参考文献
[1] 严蔚敏,吴伟民. 数据结构: (C语言版)[M] .北京:清华大学出版社,,2007(2021.1重印)
[2] 啊哈磊. 啊哈C!思考快你一步:用编程轻松提升逻辑力[M]. 北京:电子工业出版社,2013.9
[3] (日)石田保辉,(日)宫崎修著:张贝译. 我的第一本算法书[M]. 北京:人民邮电出版社,2018.11
[4] (美)普拉达(Prata,S.)著;姜佑译. C Primer Plus (第6版)中文版[M]. 北京:人民邮电出版社,2016.4 (2016.6 重印)
[5] 程杰. 大话数据结构[M]. 北京:清华大学出版社,2011.6
[6] 左飞,李召恒. C语言参悟之旅[M]. 中国铁道出版社,2010
[7] 刘涛,叶明全. C语言程序设计学习指导与实践教程[M]. 上海:上海交通大学出版社2017(2021重印)
[8] 钟志水,周鸣争. C语言程序设计[M]. 成都:电子科技大学出版社,2015.5(2021.1重印)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

friklogff

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

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

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

打赏作者

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

抵扣说明:

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

余额充值