目录
前言
总结用单链表完成的数据结构的第一题。(每一步都要把思想分析清楚)
一、问题的描述
一元多项式Poly声明如下,定义一个结点结构体,里面包含系数,指数,下一节点三个数据成员。再定义一个一元多项式类,其中包括创造链表,重载两个链表+以及打印多项式三个功能函数。
二、代码分析
1.结构体的定义
在运用单链表时,往往先要定义一个结构体(LinkNode),里面包含数据域和指针域。
2.定义功能类
首先定义一个首元结点,为头节点的接入以及遍历指针的接入提供位置,要时刻注意,定义一个新结点需要为其开辟一个新的空间,即new一块空间出来,否则会出错。开辟的同时要为其指针域赋值为NULL。以上为该类构造函数所实现的内容
创建链表函数定义。使用单链表时要永远记住该功能需要两个指针,一个为头指针current,一个为遍历指针p。头指针current一开始赋值为首元结点first指针相当于遍历指针的前驱指针,也即将其接入在链表之中。遍历指针p的初始化首先为NULL,其次每加入一个新的元素之前,就为其开辟一个新的空间,要注意每对一个新的指针开辟一个空间就要判断其内存分配的正确性。将数据域元素输入进去之后,就要更新两个结点的指针域。p结点的后继地址为空,前驱节点current接入p结点。
重载两个链表+的操作函数。同样运用链表要定义两个结点,前驱指针pre,qre,以及向后遍历的指针p,q。前去指针的接入不变,仍让其变为首结点。遍历指针的接入为前去指针的下一地址(应该很好理解p=pre->next)。此时分为三种情况1.主链的系数小于副链2.主链的系数大于副链3.主链的系数等于副链。
重载的核心就是将指数相同项系数相加,指数不同项按照顺序排列,也就是说要将副链的结点接入主链当中。副链元素接入主链后,一定要将副链结点的空间一一释放,否则程序会出现错误的析构。(这一步时一定要做的)
在分情况讨论之前,要知道每次操作只能对一个结点进行操作,所以最开始要加入循环while(p&&q)。
1.若小于,则主链的两个指针直接向后遍历(pre=p;p=p->next;)
2.若大于,则要将副链的的结点接入主链当中,即相当于实现插入操作。先用一个临时变量存储q的下一位置地址,因为q接入主链后后续会改变其地址值,而副链的指针仍还要将q向后移动,所以要先临时封存。(q->next=temp;q->next=p;pre->next=q->next;pre=q;q=temp;qre->next=q;)
3.若等于,则两个系数直接相加。此时若系数相加得0,则在主链中将该结点删除,主要仍要重新拉链:(pre->next=p->next;delete p;p=pre->next;);若系数和不为0,则将主链指针p向后移动。
情况分类完成过后,要将副链结点删除。(qre->next=q->next;delete q;q=qre->next;)
以上步骤完成后循环结束,若主链为空,副链仍然存在,则直接将两链连接起来(pre->next=q;)副链为空则在循环中主链仍然会继续,所以跳出循环后不讨论。再循环过程中,副链的结点被一一的释放,但还有一个首元结点并未释放,则(l.first->next=NULL;)最后返回的是*this指针,即为p这一条链。
打印函数。定义两个指针然后接入遍历。
总结
-
#include <iostream> using namespace std; struct LinkNode //首先建立结点域包括数据域(数据若有具体类型则用具体类型)和指针域 { double coef; //数据域 int xepe; LinkNode * next; //指针域 }; class Poly { private: LinkNode* first; public: Poly(); //构造函数 void CreatePoly(int n); //创建一元多项式 Poly operator+(Poly& l); void Print(); }; Poly::Poly() { first = new LinkNode; first->next = NULL; } void Poly::CreatePoly(int n) //形参n为输入的个数 { LinkNode* current = first; LinkNode* p=NULL; for (int i = 1; i <= n; i++) { p = new LinkNode(); if (p == NULL) { cerr << "存储空间分配错误!\n"; exit(1); } cout << "请输入系数和指数:"; cin >> p->coef >> p->xepe; //为新建的临时结点p的数据域进行赋值 p->next = NULL; //同时也要为p的结点域进行赋值,新增的数据始终在末尾,因此其指针域为空 current->next = p; //不断的移动指针然后像后遍历 current = p; } } Poly Poly::operator+(Poly&l) { LinkNode* pre = first, * p = pre->next; //对pre先进行初始化,然后再将p接入到链表中 LinkNode* qre = l.first, * q = qre->next; //q同上 LinkNode* temp; while(p!=NULL&&q!=NULL) { if (p->xepe < q->xepe) { pre = p; p = p->next; } else if (p->xepe > q->xepe) //充型“拉链”的一个过程 { temp = q->next; //先存储q的下一个地址,因为后续过程会将q接入到主链p中,会改变q的地址值 pre->next = q; q->next = p; //此时q已经成为主链中的一员,因此下一步要将pre作为q的前驱节点 pre = q; q = temp; qre->next = q; } else if(p->xepe==q->xepe) { p->coef = p->coef + q->coef; if (p->coef == 0) { pre->next = p->next; delete p; p = pre->next; } else { pre = p; p = p->next; } qre->next = q->next; delete q; q = qre->next; } } if (p == NULL) pre->next = q; l.first->next = NULL; //上述步骤将副链的后继元素节点全部删除,还需将首结点的后继节点置空 return *this; //*this代表着主链p的操作,返回*this即可 } void Poly::Print() { LinkNode* pt = first->next; if (pt != NULL) cout << pt->coef << "x^" << pt->xepe; pt = pt->next; while (pt != NULL) { if (pt->coef > 0) cout << " + " << pt->coef << "x^" << pt->xepe; else cout << pt->coef << "x^" << pt->xepe; pt = pt->next; } cout << endl; } int main() { Poly L1,L2; L1.CreatePoly(5); L1.Print(); L2.CreatePoly(5); L2.Print(); cout << "多项式的和是:\n"; L1 = L1 + L2; L1.Print(); return 0; }