1. 程式人生 > >MFC版連結串列實現稀疏多項式相加減

MFC版連結串列實現稀疏多項式相加減

連結串列實現多項式運算(加減)MFC視覺化版

題目

設計一個一元稀疏多項式簡單計算器。

基本要求

(1)輸入並建立兩個多項式;
(2)多項式a與b相加,建立和多項式c;
(3)多項式a與b相減,建立差多項式d;
(4)輸出多項式a, b, c, d。輸出格式:比如多項式a為:A(x)=c1xe1+ c2xe2+…+ cmxem,其中,ci和ei分別為第i項的係數和指數,且各項按指數的升冪排列,即0≤e1<e2<…<em。

實現提示

(1)用帶頭結點的單鏈表儲存多項式。
(2)每個多項式連結串列中都只儲存非零係數項。若多項式a與b中指數相等的兩項相加/減後,係數為零,則在和/差多項式中不儲存該指數項。

思路

其實說真的,看到連結串列就煩,沒辦法了,只能寫了,無奈自己太菜,大部分程式碼還是用的書上的,不過再運算子過載的時候自己改動了一下,因為要MFC視覺化的緣故,就把輸入輸出的過載刪掉了。
大致就和老師說的一樣,重點在於建立多項式類,難點在於MFC視覺化的計算器介面的資料輸入輸出,當然方法肯定很多,程式碼比較糙,將就著看吧,希望有對你有用的部分。
樣子差不多就是這樣:

輸入

輸出

1)輸入資料處理

輸入時,用CString變數存編輯框的內容,同時具備按鈕輸入和鍵盤輸入兩種方法,時間比較急,沒有檢測非法輸入,必須是合法輸入才能運算。不過這個寫起來也不難,完成作業就先這樣吧,到時候要是她還有要求再說。先把所有輸入存在串裡,然後用函式分割開,存進多項式物件裡,在分割時寫了一個函式,感覺蠻好用的,這裡還有一個操作可能比較多於,先用CString存,在取資料的時候又轉換為string,對string熟一點。
按鍵輸入程式碼:

void CCalculatorDlg::OnBnClickedButton1()
{
    UpdateData(TRUE);
    m_Str += "1";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton0()
{
    UpdateData(TRUE);
    m_Str += "0";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButtonNod()
{
    UpdateData(TRUE);
    m_Str += ".";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton2()
{
    m_Str += "2";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton3()
{
    UpdateData(TRUE);
    m_Str += "3";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton4()
{
    UpdateData(TRUE);
    m_Str += "4";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton5()
{
    m_Str += "5";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton6()
{
    UpdateData(TRUE);
    m_Str += "6";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton7()
{
    UpdateData(TRUE);
    m_Str += "7";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton8()
{
    UpdateData(TRUE);
    m_Str += "8";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButton9()
{
    m_Str += "9";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButtonadd()
{
    UpdateData(TRUE);
    m_Str += "+";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButtonsub()
{
    UpdateData(TRUE);
    m_Str += "-";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButtonx()
{
    m_Str += "X";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButtonleft()
{
    UpdateData(TRUE);
    m_Str += "(";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButtonright()
{
    UpdateData(TRUE);
    m_Str += ")";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButtonmul()
{
    UpdateData(TRUE);
    m_Str += "^";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}


void CCalculatorDlg::OnBnClickedButtonClear()
{
    m_Str = "";
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}

分割係數和指數函式:pos是開始時的串陣列下標,exp是指數,返回係數

float Search_Num(string a,int &pos,int&exp) {
    float num = 0;
    int cap = 0;
    for (int i(pos); i < a.size(); i++) {
        if (a[i] >= '0'&&a[i] <= '9') {
            if (cap == 0)
                num = num * 10 + a[i] - '0';
            else num = num + (a[i] - '0')*pow(0.1, cap++);
        }
        else if (a[i] == '.') {
            cap = 1;
        }
        else {
            pos = i;
            break;
        }
    }
    exp = 0;
    int tag = 1;
    if (num == 0)
        num = 1;
    if (a[pos] == 'X') {
        if (pos > a.size() -1||a[pos+1]=='-'||a[pos+1]=='+') {
            exp = 1;
            pos++;
            return num;
        }
        if (a[pos + 2] == '-') {
            tag = -1;
            pos++;
        }
        for (int i(pos + 2); i < a.size(); i++) {
            if (a[i] >= '0'&&a[i] <= '9') {
                exp= exp* 10 + a[i] - '0';
            }
            else { 
                pos = i;
                exp *= tag;
                return num;
            }
        }
    }
    else {
        exp = 0;
        return num;
    }
}

2)存進多項式物件中

類實現:

#include<iostream>
#include<string>
#include<cmath>
const double EXP = 1e-4;
using namespace std;
struct Term {
    float coef;
    int exp;
    Term *link;
    Term(float a, int b, Term* c = NULL) {
        coef = a;
        exp = b;
        link = c;
    }
    Term *insertAfter(float a, int b);
};
Term *Term::insertAfter(float a, int b) {
    link = new Term(a, b, link);
    return link;
}
class Poly {
private:
    Term *first;
    
public:
    Poly() {
        first = new Term(0, -1);
    }
    Poly(Poly&R);
    int maxOrder();
    Term *GetHead() {
        return first;
    }
    string GetString();
    Poly operator+(Poly&);
    Poly operator-(Poly&);
};
Poly::Poly(Poly &R) {
    first = new Term(0, -1);
    Term *destptr = first, *srcptr = R.GetHead()->link;
    while (srcptr != NULL) {
        destptr->insertAfter(srcptr->coef, srcptr->exp);
        srcptr = srcptr->link;
        destptr = destptr->link;
    }
}
int Poly::maxOrder() {
    Term *current = first;
    while (current->link != NULL) {
        current = current->link;
    }
    return current->exp;
}
string Poly::GetString()
{
    string s;
    CString str;
    Term *p = GetHead()->link;
    bool flag = false;
    while (p != NULL) {
        str.Format(_T("%.5lf"), p->coef);
        if (flag == true) {
            if (p->coef >0) {
                s += '+';
            }
        }
        flag = true;
        while (str[str.GetLength() - 1] == '0') {
            str.Delete(str.GetLength() - 1, 1);
        }
        if (str[str.GetLength() - 1] == '.') {
            str.Delete(str.GetLength() - 1, 1);
        }
        if(p->exp==0||(str!=_T("1")&&str!=(_T("-1"))))
            s += (CT2A)str;
        else if (str == _T("-1")) {
            s += '-';
        }
        if (p->exp == 1) {
            s += 'X';
        }
        else if(abs(p->exp)>1)
            s += "X^";
        str.Format(_T("%d"), p->exp);
        if (abs(p->exp) > 1) {
            s += (CT2A)str;
        }
        p = p->link;
    }
    return s;
}
Poly Poly::operator+(Poly&R) {
    Term*pa, *pb, *pc, *p;
    Poly C;
    float temp;
    pc = C.first;
    pa = GetHead()->link;
    pb = R.GetHead()->link;
    while (pa != NULL && pb != NULL) {
        if (pa->exp == pb->exp) {
            temp = pa->coef + pb->coef;
            if (abs(temp) > EXP) {
                pc = pc->insertAfter(temp, pa->exp);
            }
            pa = pa->link;
            pb = pb->link;
        }
        else if (pa->exp < pb->exp) {
            pc = pc->insertAfter(pa->coef, pa->exp);
            pa = pa->link;
        }
        else {
            pc = pc->insertAfter(pb->coef, pb->exp);
            pb = pb->link;
        }
    }
    p = pa == NULL ? pb : pa;
    while (p != NULL) {
        pc = pc->insertAfter(p->coef, p->exp);
        p = p->link;
    }
    return C;
}
Poly Poly::operator-(Poly&R) {
    Term*pa, *pb, *pc, *p;
    Poly C;
    float temp;
    pc = C.first;
    pa = GetHead()->link;
    pb = R.GetHead()->link;
    while (pa != NULL && pb != NULL) {
        if (pa->exp == pb->exp) {
            temp = pa->coef - pb->coef;
            if (abs(temp) > EXP) {
                pc = pc->insertAfter(temp, pa->exp);
            }
            pa = pa->link;
            pb = pb->link;
        }
        else if (pa->exp < pb->exp) {
            pc = pc->insertAfter(pa->coef, pa->exp);
            pa = pa->link;
        }
        else {
            pc = pc->insertAfter(-pb->coef, pb->exp);
            pb = pb->link;
        }
    }
    p = pa == NULL ? pb : pa;
    int flag = pa == NULL ? -1 : 1;
    while (p != NULL) {
        pc = pc->insertAfter(flag*p->coef, p->exp);
        p = p->link;
    }
    return C;
}

按等於按鈕開始讀資料存進多項式A,B中:

void CCalculatorDlg::OnBnClickedButtonCal()
{
    UpdateData(TRUE);
    string s = (CT2A)m_Str;
    if (s.empty()) {
        AfxMessageBox(_T("請輸入表示式!"));
        return;
    }
    Poly A, B,C;
    bool flag = false;
    float num = 0;
    int cap = 0;
    int v = 1;
    int pos_B;
    for (int i(0); i < s.size(); i++) {
        if (s[i] == ')') {
            pos_B = i;
            break;
        }
    }
    int p = 0;
    if (s[0] == '(')p++;
    bool real = true;
    Term *rear = A.GetHead();
    while (p < pos_B) {
        real = true;
        if (s[p] == '+') {
            real = true;
            p++;
        }
        else if (s[p] == '-'){
            real = false;
            p++;
        }
        int temp_e;
        num=Search_Num(s, p,temp_e);
        v = real == true ? 1 : -1;
        rear = rear->insertAfter(v*num, temp_e);
    }
    p += 3;
    rear = B.GetHead();
    while (p < s.size()-1) {
        real = true;
        if (s[p] == '+') {
            real = true;
            p++;
        }
        else if (s[p] == '-') {
            real = false;
            p++;
        }
        int temp_e;
        num = Search_Num(s, p, temp_e);
        v = real == true ? 1 : -1;
        rear = rear->insertAfter(v*num, temp_e);
    }
    if (s[pos_B + 1] == '+') {
        C = A + B;
    }
    else {
        C = A - B;
    }
    string temp = C.GetString();
    m_Str = temp.c_str();
    UpdateData(FALSE);
    // TODO: 在此新增控制元件通知處理程式程式碼
}

3)結果轉換位字串更新到Edit框中

轉字串的函式就在類定義裡面,也費了不少功夫,因為樣例給的情況太全面了,剛開始沒考慮到負指數,不過不要緊,還是改好了。面向物件的特點體現以後更改程式碼也比較方便~

後記

程式碼沒有寫註釋,故意的。對,故意的。能理解的小夥伴應該能看懂,完全不懂的就有點困難了,相比不視覺化,視覺化對於輸入和輸出需要轉化一下,其他的和不普通的差不多,當然寫按鈕也比較煩,,,
介面很醜,之後可能會美化,再說吧,今天先睡了。
2018/11/13 23:42:48