2009年10月27日 星期二

多項式運算

 
link-list 省空間,但程式繁雜:
int main (/*081116*/)
{
    int i;
    struct List {                 //polynomial list
        struct P {                //polynomial component
            int a, i;             //a= coefficient, i= exponential index
            P*  next;             //pointer to next element
            P() {a=i=0; next=0;}  //init to zero
        } *h, *t;                 //pointer to head and tail

        List() {h = t = new P;}

        void expand() {           //add a new component
            t = (t->next = new P);
        }   
        void release() {
            while (h->next) {
                t=h->next; delete h; h=t;
            }
        }
        P* operator->() {return t;}

        List operator + (const List& L)
        {
            List x;
            P **pp, *p1 = h, *p2 = L.h;
            for (;p1->next || p2->next; x.expand())
                if (p1->next && p2->next && p1->i == p2->i) {  
                                      //if exponential index the same
                    x->i = p1->i;
                    x->a = p1->a + p2->a;
                    p1   = p1->next;
                    p2   = p2->next;
                }
                else {                //overwise select the bigger one
                    pp = &p2;
                    if (!p2->next || (p1->next && p1->i > p2->i)) 
                        pp = &p1;
                    x->i = pp[0]->i;
                    x->a = pp[0]->a;
                    *pp  = pp[0]->next;
                }
                return x;
        }
        List operator * (const List& L)
        {
            List x, y, z;
            P *p1 = h, *p2 = x.h;
            for (; p1 != t; p1 = p1->next) {
                x = x + L;
                for (p2=x.h; p2->next; p2=p2->next) {
                    p2->a *= p1->a;
                    p2->i += p1->i;
                }
                z = x + y;
                y.release();
                x.release();
                y = z;
            }
            return z;
        }
        void show()
        {
            for (P* p=h; p!=t; ) {
                if (p->i > 0) printf ("%dx^%d", p->a, p->i);
                else printf ("%d", p->a );
                p = p->next;
                p!=t? printf(" + "): puts("");
            }
        }
    }
    //================= main program ===================
    p[4];

    for (i=0; i<2; i++)
        while (cin >> p[i]->a && 99 != p[i]->a) {
            cin >> p[i]->i;
            p[i].expand();
        }
    p[0].show();
    p[1].show();

    puts("-----------------------");

    p[2] = p[0] + p[1];    p[2].show();
    p[3] = p[0] * p[1];    p[3].show();

    for (i=0; i<4; i++) p[i].release();       
}
array 的空間使用率一般偏低,係數值域限制較大,但算式簡潔直觀。
底下使用固定大小的 array size,很沒彈性,好處是不用再想東想西:
煩惱是否要加個 Copy-on-Write 加速,檢查是否自我指派,
或是用 Immutable pattern 讓它「多一點」thread-safe:

沒有留言:

張貼留言