c++ 稀疏多项式计算器(可视化操作——鼠标点击型菜单)

写了大作业,来水一贴。这次使用了stl中的双链表管理数据。

 1 功能介绍

  • 输入多项式
  • 多项式加法
  • 多项式减法
  • 多项式乘法
  • 多项式求值
  • 多项式求导

2 分析

(1)定义单项式结构体,包含系数与指数。
(2)多项式频繁增删,应使用链表存储。
(3)多项式加减法:本质上是合并链表,时间复杂度o(m + n)
(4)多项式乘法:用双重循环遍历两个多项式,最后排序,合并同类项,时间复杂度o(n2)
(5)多项式求导、求值:时间复杂度o(n)

3 设计

struct node
{
    double coefficient_;
    int exponent_;
};

class Poly
{
private:
    list<node> ploy_;

public:
    Poly();
    Poly(const string x);
    Poly(const Poly &x);
    Poly(const list<node> &x);

    Poly operator+(const Poly &x) const;
    Poly operator-(const Poly &x) const;
    Poly operator*(const Poly &x) const;
    double value(double x) const;   //求值
    Poly derivative() const;        //求导
    friend ostream &operator<<(ostream &pout, const Poly &x);
};

#endif

4 代码

4.1 poly.hpp

#ifndef POLY_HPP
#define POLY_HPP
#include <list>
#include <iostream>
#include <sstream>
#include <cmath>
using namespace std;
struct node
{
    double coefficient_;
    int exponent_;
    node(double a = 0, int n = 0) : coefficient_(a), exponent_(n){};
    node(const node &x) : coefficient_(x.coefficient_), exponent_(x.exponent_){};
    bool operator<(const node &x) { return exponent_ < x.exponent_; }         //for sort
    bool operator==(const node &x) { return coefficient_ == x.coefficient_; } //for erase
};

void combine(list<node> &x) //合并相邻的同类项
{
    auto p = x.begin();
    auto last = p++;
    while (p != x.end())
    {
        if (last->exponent_ == p->exponent_)
        {
            p->coefficient_ += last->coefficient_;
            if (p->coefficient_ == 0)
                p++;
            x.erase(last, p);
            last = p++;
        }
        else
        {
            last++;
            p++;
        }
    }
};

class Poly
{
private:
    list<node> ploy_;

public:
    Poly(){};
    Poly(const string x) { init(x); }
    Poly(const Poly &x)
    {
        for (auto &p : x.ploy_)
            ploy_.push_back(p);
    };
    Poly(const list<node> &x)
    {
        for (auto p : x)
            ploy_.push_back(p);
    }
    ~Poly(){};

    void init(string x)
    {
        istringstream sin(x);
        double a;
        int n;
        while (sin.peek() != '#' && sin.peek() != EOF)
        {
            sin >> a >> n;
            if (a != 0)
                ploy_.push_back({a, n});
        }
        ploy_.sort();
    };
    Poly operator+(const Poly &x) const
    {
        list<node> left(this->ploy_), right(x.ploy_);
        left.merge(right);
        combine(left);
        return Poly(left);
    };
    Poly operator-(const Poly &x) const
    {
        list<node> left(this->ploy_), right(x.ploy_);
        for (auto &p : right)
            p.coefficient_ = -p.coefficient_;
        left.merge(right);
        combine(left);
        return Poly(left);
    }
    Poly operator*(const Poly &x) const
    {
        list<node> temp;
        for (auto p = ploy_.begin(); p != ploy_.end(); p++)
            for (auto q = x.ploy_.begin(); q != x.ploy_.end(); q++)
                temp.push_back(node(p->coefficient_ * q->coefficient_, p->exponent_ + q->exponent_));
        temp.sort();
        combine(temp);
        return Poly(temp);
    }
    double value(double x) const    //求值
    {
        double temp = 0;
        for (auto p : ploy_)
            temp += p.coefficient_ * pow(x, p.exponent_);
        return temp;
    }
    Poly derivative() const        //求导
    {
        list<node> temp;
        auto p = ploy_.begin();
        if (p->exponent_ == 0)
            p++;
        for (; p != ploy_.end(); p++)
            temp.push_back(node(p->coefficient_ * p->exponent_, p->exponent_ - 1));
        return Poly(temp);
    }
    friend ostream &operator<<(ostream &pout, const Poly &x)
    {
        if (x.ploy_.size())
        {
            auto p = x.ploy_.rbegin();
            cout << p->coefficient_ << "x^" << p->exponent_;
            for (p++; p != x.ploy_.rend(); p++)
            {
                cout << " + ";
                if (p->coefficient_ != 1 || p->exponent_ == 0) //系数不为1 || 常数项
                    cout << p->coefficient_;
                if (p->exponent_) //不为常数项
                {
                    cout << 'x';
                    if (p->exponent_ != 1) //有指数
                        cout << '^' << p->exponent_;
                }
            }
        }
        else
            pout << 0;
        return pout;
    }
};

#endif

 4.2 console.hpp

#ifndef CONSOLE_HPP
#define CONSOLE_HPP
#include <windows.h>
#include <conio.h>
#include <iostream>
#include <iomanip>
using std::ios_base;
using std::ostream;
//dwButtonState 鼠标按钮状态
#define L_BUTTON 0x1
#define R_BUTTON 0x2

// dwEventFlags 鼠标事件状态
#define MOUSE_CLICK 0x0
#define MOUSE_MOVED 0x1
#define DOUBLE_CLICK 0x2

//颜色
#define COLOR_default SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
#define COLOR_Black_Cyan SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0b);
#define COLOR_Yellow_Blue SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xe9);

// 光标位置
// 移动光标位置
inline void setcursor(short x = 0, short y = 0)
{
    COORD temp = {x, y};
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), temp);
}
inline void setcursor(const COORD &temp)
{
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), temp);
}

// 获得光标位置
inline void getcursor(COORD &other)
{
    CONSOLE_SCREEN_BUFFER_INFO temp;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &temp);
    other = temp.dwCursorPosition;
}
inline COORD getcursor()
{
    CONSOLE_SCREEN_BUFFER_INFO temp;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &temp);
    return temp.dwCursorPosition;
}

//比较坐标
inline bool operator==(COORD a, COORD b)
{
    return a.X == b.X && a.Y == b.Y;
};
inline bool operator!=(COORD a, COORD b)
{
    return !(a == b);
}

//输出光标坐标
ostream &operator<<(ostream &pout, const COORD &temp)
{
    pout.setf(ios_base::fixed);
    pout << "[Cursor Position] X: " << std::setw(2) << temp.X << "  Y: " << std::setw(2) << temp.Y;
    return pout;
}

//是否隐藏光标
void hidecursor(bool hide = true)
{
    CONSOLE_CURSOR_INFO CursorInfo;
    GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &CursorInfo);
    CursorInfo.bVisible = !hide;
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &CursorInfo);
}

// 更改控制台设置,防止控制台属性导致的判定失败
void setmode()
{
    DWORD mode;
    GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
    mode &= ~ENABLE_QUICK_EDIT_MODE; //移除快速编辑模式
    mode &= ~ENABLE_INSERT_MODE;     //移除插入模式
    // mode &= ~ENABLE_MOUSE_INPUT;     //移除鼠标输入
    SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
}

//判断鼠标点击位置是否在指定的有效范围(本行,本列至5列之间)
bool operator<=(const COORD &button, const COORD &click)
{
    if (button.Y == click.Y && button.X <= click.X && click.X <= button.X + 20)
        return true;
    else
        return false;
};
//等待鼠标事件,可排除鼠标移动
MOUSE_EVENT_RECORD waitmouse(bool move = true)
{
    INPUT_RECORD record; //输入事件
    DWORD reg;           //临时寄存
    while (1)
    {
        Sleep(10);
        ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &record, 1, &reg);                                  //将输入事件存入record
        if (record.EventType == MOUSE_EVENT && (move | record.Event.MouseEvent.dwEventFlags != MOUSE_MOVED)) //是鼠标事件 && 移动事件与模式对应
            return record.Event.MouseEvent;
    }
}
// 清屏函数
void clean(int a = 0)
{
    int temp = a ? a : getcursor().Y;
    setcursor(0, 0);
    for (int i = 0; i <= temp; i++)
        std::cout << std::string(100, ' ') << '\n';
    setcursor(0, 0);
}
//暂停
void pause()
{
    std::cout << "请按任意键继续\n";
    std::cin.sync();
    std::cin.get();
}

#endif

4.3 menu.hpp

#ifndef MENU_HPP
#define MENU_HPP
#include "console.hpp"
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;

#define show_real(x) cout << #x ": " << x << '\n'
//button - click
class Menu
{
private:
    struct node
    {
        void (*pfunc_)();
        string display_;
        COORD pos_;
    };
    vector<node> nodes_;
    string title_;

protected:
    void init_pos()
    {
        for (auto p = nodes_.begin(); p != nodes_.end(); p++)
        {
            getcursor(p->pos_);
            cout << p->display_ << "\n\n";
        }
    };

    bool implement(COORD clickpos)
    {
        waitmouse(false); //过滤鼠标松开
        for (auto p = nodes_.begin(); p != nodes_.end(); p++)
        {
            if (p->pos_ <= clickpos) //点击成功
            {
                hidecursor(0);
                clean();
                p->pfunc_();
                hidecursor(1);
                cout << "\n\n鼠标点击任意位置以继续\n";
                waitmouse(false);
                highlight({0, 0});
                return true;
            }
        }
        return false;
    };
    void highlight(COORD hang)
    {
        clean();
        cout << title_ << endl //显示内容
             << "========================================" << endl;
        for (auto p = nodes_.begin(); p != nodes_.end(); p++)
        {
            if (p->pos_ <= hang) //悬停点
            {
                COLOR_Black_Cyan;
                cout << p->display_ << "\n\n";
                COLOR_default;
            }
            else
                cout << p->display_ << "\n\n";
        }
    }

public:
    //constructor
    Menu(){};
    ~Menu(){};
    //methods
    Menu &settitle(string s)
    {
        title_ = s;
        return *this;
    }

    Menu &add(void (*p)() = nullptr, string d = "Unkown.")
    {
        nodes_.push_back({p, d});
        return *this;
    };

    void start()
    {
        MOUSE_EVENT_RECORD mouse;
        setmode();
        hidecursor(1);
        clean();
        cout << title_ << endl //显示内容
             << "========================================" << endl;
        init_pos(); //记录位置
        do
        {
            Sleep(10); //减少次数
            mouse = waitmouse();
            if (mouse.dwEventFlags == MOUSE_MOVED)
                highlight(mouse.dwMousePosition);
            else if (mouse.dwButtonState == L_BUTTON)
                implement(mouse.dwMousePosition);
        } while (mouse.dwButtonState != R_BUTTON);
        Sleep(100); //过滤
    };
};
#endif

4.4 主函数

#include "poly.hpp"
#include "menu.hpp"
#include <iostream>
using namespace std;
void show1();
void show2();
void show11(); //+
void show12(); //-
void show13(); //*
void show14(); //`
void show15(); //求值
int main()
{
    Menu loop;
    loop.settitle("多项式计算器(右键退出)");
    loop.add(show1, "开始计算").add(show2, "功能演示");
    loop.start();
}
void show2()
{
    cout << "输入格式:\n"
            "先输入系数,再输入指数,使用空格分隔开;输入完按回车\n"
            "如:\n"
            "输入: 1.1 2 3.3 4\n"
            "表示: 1.1x^2 + 3.3x^4\n"
            "你并不需要降次输入,程序会完成整理过程\n";
    Sleep(1000);
}

void show1()
{
    Menu cal;
    cal.settitle("请选择功能");
    cal.add(show11, "多项式加法").add(show12, "多项式减法").add(show13, "多项式乘法");
    cal.add(show14, "多项式求导").add(show15, "多项式求值");
    cal.start();
}

void show11() //+
{
    Poly left, right;
    {
        char temp[101];
        cout << "请输入左多项式:";
        cin.getline(temp, 100);
        left.init(temp);
        cout << "请输入右多项式:";
        cin.getline(temp, 100);
        right.init(temp);
    }
    show_real(left);
    show_real(right);
    show_real(left + right);
}
void show12() //-
{
    Poly left, right;
    {
        char temp[101];
        cout << "请输入左多项式:";
        cin.getline(temp, 100);
        left.init(temp);
        cout << "请输入右多项式:";
        cin.getline(temp, 100);
        right.init(temp);
    }
    show_real(left);
    show_real(right);
    show_real(left - right);
};
void show13() //*
{
    Poly left, right;
    {
        char temp[101];
        cout << "请输入左多项式:";
        cin.getline(temp, 100);
        left.init(temp);
        cout << "请输入右多项式:";
        cin.getline(temp, 100);
        right.init(temp);
    }
    show_real(left);
    show_real(right);
    show_real(left * right);
}
void show14() //`
{
    Poly polynomial;
    {
        char temp[101];
        cout << "请输入多项式:";
        cin.getline(temp, 100);
        polynomial.init(temp);
    }
    show_real(polynomial);
    cout << "导数为:" << polynomial.derivative() << '\n';
}
void show15() //求值
{
    Poly polynomial;
    double x;
    {
        char temp[101];
        cout << "请输入多项式:";
        cin.getline(temp, 100);
        polynomial.init(temp);
        cout << "请输入x的值:";
        cin >> x;
    }
    show_real(polynomial);
    printf("当x的值为%f时,多项式的值为: %f", x, polynomial.value(x));
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

岚花落_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值