重拾 ”多项式“ 给我的启示
多项式问题,是编程入门的一个基础题,可以使用数组或是指针来实现。当然使用数组会比较麻烦,因为需要大量的元素移动与删除操作,而这恰恰是链表所擅长的。顺便补充一点,对于删除较频繁的一组数据,使用链表可以省去大量时间以及少写很多代码;对于要求对特定元素进行操作(更新)的数据,我们通常使用数组。今天用链表再次写了一遍多项式,感触很深,同时也使我很无奈,因为指针这东西,好是好,只是它很暴躁!
先来照常贴一下题目吧:
一个多项式可以表达为x的各次幂与系数乘积的和,比如:2x6+3x5+12x3+6x+20。现在,你的程序要读入两个多项式,然后输出这两个多项式的和,也就是把对应的幂上的系数相加然后输出。
代码如下:
1 #include <iostream> 2 using namespace std; 3 typedef struct prim { 4 double factor; 5 double exp; 6 prim* next; 7 }*pprim; 8 9 //清空链表 10 void mydelete(pprim& p) 11 { 12 if (!p) 13 { 14 return; 15 } 16 if (p->next) 17 { 18 mydelete(p->next); 19 } 20 delete p; 21 p = NULL; 22 return; 23 } 24 25 int main(int argc, char* argv[]) 26 { 27 pprim hA, hB, tmp = NULL; 28 29 //使用这些变量给多项式赋值 30 pprim* ppApre = NULL, *ppAcur = NULL; 31 pprim* ppBcur = NULL, *ppBpre = NULL; 32 33 //使用这些变量让多项式相加 34 pprim papre = NULL, pacur = NULL; 35 pprim pbpre = NULL, pbcur = NULL; 36 37 //n、m表示多项式A、B的项数 38 int n, m; 39 cin >> n >> m; 40 hA = new prim; 41 hA->next = NULL; 42 hB = new prim; 43 hB->next = NULL; 44 45 cout << "多项式A:"; 46 while (n) 47 { 48 tmp = new prim; 49 cin >> tmp->factor >> tmp->exp; 50 tmp->next = NULL; 51 52 //升序插入 53 ppApre = &hA; 54 ppAcur = &(hA->next); 55 if (*ppAcur == NULL) 56 { 57 *ppAcur = tmp; 58 } 59 else 60 { 61 while (*ppAcur && tmp->exp >= (*ppAcur)->exp) 62 { 63 ppApre = ppAcur; 64 ppAcur = &((*ppAcur)->next); 65 } 66 tmp->next = *ppAcur; 67 (*ppApre)->next = tmp; 68 } 69 70 --n; 71 } 72 73 cout << "多项式B:"; 74 while (m) 75 { 76 tmp = new prim; 77 cin >> tmp->factor >> tmp->exp; 78 tmp->next = NULL; 79 80 //升序插入 81 ppBpre = &hB; 82 ppBcur = &(hB->next); 83 if (*ppBcur == NULL) 84 { 85 tmp->next = *ppBcur; 86 (*ppBpre)->next = tmp; 87 } 88 else 89 { 90 while (*ppBcur && tmp->exp >= (*ppBcur)->exp) 91 { 92 ppBpre = ppBcur; 93 ppBcur = &((*ppBcur)->next); 94 } 95 tmp->next = *ppBcur; 96 (*ppBpre)->next = tmp; 97 } 98 --m; 99 } 100 101 //相加 102 papre = hA; 103 pacur = hA->next; 104 pbpre = hB; 105 pbcur = hB->next; 106 107 while (pacur && pbcur) 108 { 109 if (pacur->exp == pbcur->exp) 110 { 111 pacur->factor += pbcur->factor; 112 if (pacur->factor == 0.0) 113 { 114 papre->next = pacur->next; 115 delete pacur; 116 pacur = papre->next; 117 } 118 else 119 { 120 papre = pacur; 121 pacur = papre->next; 122 } 123 pbpre->next = pbcur->next; 124 delete pbcur; 125 pbcur = pbpre->next; 126 } 127 else if (pacur->exp > pbcur->exp) 128 { 129 pbpre->next = pbcur->next; 130 131 pbcur->next = pacur; 132 papre->next= pbcur; 133 papre = pacur; 134 pacur = papre->next; 135 136 pbcur = pbpre->next; 137 } 138 else 139 { 140 papre = pacur; 141 pacur = papre->next; 142 } 143 } 144 if (pacur == NULL) 145 { 146 papre->next = pbcur; 147 } 148 149 //输出 150 pprim p = hA->next; 151 while (p) 152 { 153 cout << p->factor << "x(" << p->exp << ")"; 154 p = p->next; 155 if (p) 156 { 157 cout << " + "; 158 } 159 } 160 cout << endl; 161 162 mydelete(hA); 163 return 0; 164 } 165
写这段代码时,让我很头痛的就是怎样定义指针变量。对指针还不熟悉或者想要加强一下的,可以看这里:http://www.cnblogs.com/ggjucheng/archive/2011/12/13/2286391.html 在我的第一版本代码里,用于给多项式赋值的指针我使用了一重指针,然程序每次运行都显示多项式为空(没有项),于是我仔细思索,发现我若要给多项式赋值,需要修改的是内存本身,而不是一个该内存的副本,但是我第一版本里边的一重指针在初始化时,恰恰被赋予了一个将要修改的内存的副本,于是,失败在所难免。解决办法是,你需要把你所要修改的内存地址赋值给一个二重指针,这样通过地址来访问并修改内存的内容是可行的。其实,恨多时候我们都会遇到这样的问题,就是虽然很明确的知道你要修改某个东西的值,可是总会不自觉的修改了它的副本,导致这个东西本身并没有改变。在这写出来警示自己同时也警示给位朋友。不过人非圣贤,孰能无过?不小心落入这个泥沼不要紧,很快反应过来并解决问题才是最要紧的。
最后补充一些可以修改内存本身的方法:①引用,c++特有的操作,它相当于给变量取了别名,对其修改也就相当于对内存本身做了修改。但高级引用的高级用法并不是拿来修改值,而是在参数传递时为了不产生临时变量而设置常量引用;或者是以引用作为函数返回值类型,这样可以进行一些特殊的操作(例如可以给函数赋值)等。②是指针,这就不用多说了,指针能修改内存是很基础的,但是应该提醒一点:如果要修改指针的值,则需要将指针的地址赋给指针的指针(话有点拗口,不过是真理)。
学习路上,大家共勉!