LinearList.h
注意使用 #pragma once 命令
#pragma once #include <iostream> using namespace std; //陈刚的课件里注释有很多的问题,千万不要引入注释。 template <class T> class LinearList{ public: LinearList(){}; ~LinearList(){}; virtual bool IsEmpty() const=0; virtual int Length() const=0; virtual bool Find(int k,T& x) const=0; virtual int Search(const T& x) const=0; virtual bool Insert(int k,const T& x)=0; virtual bool Delete(int k)=0; virtual bool Update(int k, const T& x)=0; virtual void Output(ostream& out)const=0; int a; }; //线性表的顺序表实现 template <class T> class SeqList:public LinearList<T> { public: SeqList(int MaxListSize); ~SeqList() { delete [] elements; };//有意思的地方在这里,如果不指定删除的对象为数组的话,必定会出现内存泄露的问题。 bool IsEmpty() const; int Length() const; bool Find(int k,T& x) const; int Search(const T& x) const; bool Insert(int k,const T& x); bool Delete(int k); bool Update(int k, const T&x); void Output(ostream& out)const ; private: int length; int MaxLength; T *elements; }; template <class T> SeqList<T>::SeqList(int MaxListSize) { MaxLength=MaxListSize; elements=new T[MaxLength]; length=0; } template<class T> bool SeqList<T>::Find(int k,T& x) const { if (k<1 || k>length) { cout<<"Out of Bounds"<<endl; return false; } x=elements[k-1]; return true; } template<class T> bool SeqList<T>::Insert(int k,const T& x) { if(k < 0 || k > length) { cout<< "Out of bound" <<endl; return false; } if (length == MaxLength) { cout<< "OverFlow" <<endl; return false; } for (int i=length-1;i>=k;i--) elements[i+1]=elements[i]; elements[k]=x; length++; return true; } template <class T> bool SeqList<T>::Delete(int k) { if ( !length ) { cout<<"UnderFlow"<<endl; return false; } if ( k<1 || k>length ) { cout<<"Out Of Bounds"<<endl; return false; } for (int i=k;i<length;i++) elements[i-1]=elements[i]; length--; return true; } template <class T> bool SeqList<T>::IsEmpty() const { return length==0; } template <class T> int SeqList<T>::Length() const { return length; } template <class T> void SeqList<T>::Output(ostream& out)const { for (int i=0; i< length; i++) out<<elements[i]<<' '; out<<endl; } template<class T> int SeqList<T>::Search(const T& x) const { for (int i=0;i<length;i++) if (elements[i]==x) return ++i; return 0; } template <class T> bool SeqList<T>::Update(int k, const T& x) { if (k<1|| k>length ) { cout<<"Out Of Bounds"<<endl; return false; } elements[k-1]=x; return true; } //线性表的单链表实现 template <class T> class SingleList; template <class T> class Node { private: T data; Node<T> *link; /*这里的友元类很像Java中的内部类,允许单链表类访问自己的私有成员*/ friend class LinearList<T>; }; template <class T> class SingleList:public LinearList<T> { public: SingleList() { first=NULL; length=0; } ~SingleList(); bool IsEmpty() const; int Length() const; bool Find(int k,T& x) const; int Search(const T& x) const; bool Insert(int k,const T& x); bool Delete(int k); bool Update(int k, const T&x); void Output(ostream& out)const ; private: Node<T>* first; int length; }; template <class T> SingleList<T>::~SingleList() { Node<T> *p; while ( first ) { p=first->link; delete first; first=p; } } template<class T> bool SingleList<T>::Find(int k,T& x)const { if (k<1 || k>length ) { cout<< "Out Of Bounds"; return false; } Node<T> *p=first; /*注意for循环中止的时候, i == k已经成立了。*/ for (int i=1; i<k; i++) p=p->link; x=p->data; return true; } template<class T> bool SingleList<T>::Insert(int k,const T&x) { if ( k<0 || k>length ) { cout<< "Out Of Bounds"; return false; } Node<T> *p=first; for (int i=1; i<k; i++) p=p->link; Node<T> * q=new Node<T>; q->data=x; if(k){ q->link=p->link;p->link=q; /*在p之后插入*/ } else {q->link=first;first=q;/* k=0,在第一个元素之前插入*/ } length++; return true; } template<class T> bool SingleList<T>::Delete(int k) { if ( !length ) { cout<<"UnderFlow"<<endl; return false; } if ( k<1 || k>length ) { cout<< "Out Of Bounds"<<endl; return false; } Node<T> *p=first,*q=first; for (int i=1; i<k-1; i++) q=q->link; /*循环结束时,q指向谁?指向要删除的结点的前驱。有趣的是,如果要删除头结点,则这个语句不会执行*/ if (k==1) first=first->link; /*删除的是第一个结点的情况*/ else { p=q->link; q->link=p->link; } delete p; length--; return true; } //接下来是我自己手写的一个带表头结点的单链表。 template <class T> class HeaderList:public LinearList<T> { public: HeaderList() { first = new ListNode(); length=0;first->link = 0; first -> data = 0; } ~HeaderList(); bool IsEmpty() const; int Length() const; bool Find(int k,T& x) const; int Search(const T& x) const; bool Insert(int k,const T& x); bool Delete(int k); bool Update(int k, const T&x); void Output(ostream& out)const ; private: Node<T>* first; int length; }; template <class T> HeaderList<T>::~HeaderList() { Node<T> *p; while ( first->link ) { /*不能把表头结点删除掉*/ p=first->link; delete first; first=p; } } template<class T> bool HeaderList<T>::Find(int k,T& x)const { if (k<1 || k>length ) { cout<< "Out Of Bounds"; return false; } Node<T> *p=first; /*注意for循环中止的时候, i == k已经成立了。*/ for (int i=1; i<=k; i++) p=p->link; x=p->data; return true; } template<class T>//为什么注释不能成功呢? bool HeaderList<T>::Insert(int k,const T&x) { if ( k<0 || k>length ) { cout<< "Out Of Bounds";//越界提示 return false; } Node<T> *p=first; for (int i=1; i<=k; i++) p=p->link; Node<T> * q=new Node<T>; q->data=x; if(k){ q->link=p->link;p->link=q; /*在p之后插入*/ } else {q->link=first;first=q;/* k=0,在第一个元素之前插入*/ } length++; return true; } template<class T> bool HeaderList<T>::Delete(int k) { if ( !length ) { cout<<"UnderFlow"<<endl; return false; } if ( k<1 || k>length ) { cout<< "Out Of Bounds"<<endl; return false; } Node<T> *p=first,*q=first; for (int i=1; i<k; i++) q=q->link; /*循环结束时,q指向谁?指向要删除的结点的前驱。有趣的是,如果要删除头结点,则这个语句不会执行*/ p = first->link; first->link= p->link; delete p; length--; return true; }
Polynominal.h
#pragma once #include <iostream> using namespace std; //一个多项式运算的好例子。值得学习的是关于iostream的重载和理解部分。 class Term { public: Term(int c,int e); Term(int c,int e,Term* nxt); Term* InsertAfter(int c,int e);//在this指 //针指示的项后插入新项 //为什么会在多项式结点里存在这样一个插入函数呢? private: int coef; int exp; Term *link; friend ostream & operator<<(ostream &, const Term &);//输出项 friend class Polynominal; }; Term::Term(int c,int e):coef(c),exp(e){ link=0; } Term::Term(int c,int e,Term *nxt):coef(c),exp(e){ link=nxt; } //这里巧妙地使用了两个构造函数初始化式,调用其他构造函数来初始化。 Term* Term::InsertAfter(int c,int e) { link=new Term(c,e,link); //相当于this->link=new Term(c,e,this->link); return link;//返回谁的地址?还是本结点的link地址,本结点并没有发生什么变化,只是link指向了一个新结点。 } //<<果然是一个二元运算符。 ostream &operator <<(ostream & out, const Term& val) { if(val.coef==0) return out; out<<val.coef; switch(val.exp){ case 0:break; case 1:out<<"X"; break; default:out<<"X^"<<val.exp; break; } return out; } /*多项式类的成员函数 (1) AddTerms 函数: 通过输入流in,输入多项式的各项构造一个多项式。 (2) Output 函数: 将多项式按降幂方式送输出流。 (3) PolyAdd 函数: 实现将多项式r加到指针this指示的多项式上。*/ class Polynominal { public: Polynominal(); void AddTerms(istream& in); void Output(ostream& out)const; void PolyAdd(Polynominal& r); private: Term* theList; //指向循环链表的头结点 friend ostream & operator << (ostream &, const Polynominal &); friend istream& operator >>(istream&, Polynominal &); friend Polynominal operator +( Polynominal &, Polynominal &); }; Polynominal::Polynominal() { theList=new Term(0,-1); //生成带头结点的空循环链表 theList->link=theList;//注意,要自循环。 } void Polynominal:: AddTerms(istream & in) { Term* q=theList; int c,e; for(;;){ cout<<"Input a term(coef,exp):\n"<<endl; in>>c>>e; if (e<0) break; q=q->InsertAfter(c,e);//注意,此时多项式为乱序的。 } } //根本就没有办法保证它是降幂输出的,除非一开始输入的时候就是按照降幂输入的。 void Polynominal::Output(ostream& out)const { int first=1; Term *p=theList->link;//p指向谁? 多项式的第一个结点 cout<<"The polynominal is:\n"<<endl; for ( ; p!=theList; p=p->link){ if (!first && (p->coef>0)) out<<"+";//此处存疑,为什么first下面要置为 0呢? first=0;//first的含义大概是,是否为头一个结点,在第一个结点以后,就不需要 加上“+”号了。 out<<*p;// 调用Term类上重载的“<<”操作。 } cout<<"\n"<<endl; } /*实现q(x) q(x)+ p(x)即把多项式p(x)和q(x)相加的结果放在q(x) 中 设 p 和 q 分别指向多项式p(x)和q(x)的当前正进行比较的项,初始时分别指向两多项式中最高幂次的项。q1指向q的前驱结点。 (1) p->exp == q->exp 则将q->coef 和p->coef 相加。如果结果不为零,则令q->coef =q->coef + p-> coef,否则从q(x) 中删除q指示的结点 (2) p->exp > q->exp 则复制p所指示的结点,将其插在 q1之后,p指向下一个结点 (3) p->exp < q->exp 则q指示的项应成为结果多项式中的一项,q和q1应向后移动 */ //这个add是有漏洞的。如果有一条链表不是按降幂排列,则移动就变成没有意义。 void Polynominal::PolyAdd(Polynominal& r) //为什么只有一个参数,因为只有一个链表相加。 { Term *q,*q1=theList,*q2,*p; p=r.theList; q=q1->link; p=p->link; //p和q指向两个当前进行比较的项 while (p->exp>=0){ //如果p多项式未结束,则继续 while (p->exp<q->exp){ q1=q;//指向头结点的指针移动到目前最高次幂的结点上 。q1的含义高次幂结点的前驱。 q=q->link;//高次幂结点不断降幂移动。 } if (p->exp==q->exp){ q->coef=q->coef+p->coef; if (q->coef==0){ q2=q;q1->link=q->link;//删除q这个目前最高次幂的结点,也就是删除q2 q=q->link;delete(q2);//q继续降幂移动 p=p->link;//p完成任务,也跟着移动 } else { q1=q; q=q->link; p=p->link;//把当前的q保存下来成为q1,q和p移动 } } //注意,这是一个没有经过if中处理的分支,有点类似finally。 else{ // (p->exp>q->exp) q1=q1->InsertAfter(p->coef,p->exp); //q1用保存下来的位置作一个媒介,进行插入操作。 p=p->link;//p继续移动 } //end else } //end while } //end PolyAdd ostream& operator <<(ostream &out,const Polynominal &x) { x.Output(out); return out; } istream& operator >>(istream& in, Polynominal &x) { x.AddTerms(in); return in; } /* Polynominal& operator +(Polynominal &a, Polynominal &b) { a.PolyAdd(b); return a; }*/
Stack.h
#pragma once #include <assert.h> const int MaxSize=50; template <class T> class Stack { public: Stack(){}; ~Stack(){}; virtual void Push(const T &x)=0; virtual void Pop()=0; virtual T Top()const=0; virtual bool IsEmpty() const=0; virtual bool IsFull() const=0; }; template<class T> class SeqStack:public Stack<T> { public: SeqStack(int MaxSize); ~SeqStack(); bool IsEmpty() const {return (top==-1);}/*只有在顺序栈中才可以这样实现吧。*/ void Push(const T &x); void Pop(); T Top() const; bool IsFull() const {return (top==MaxTop);} void SetNull(){ top=-1; } private: T *s; int MaxTop;/*栈的尺寸大小*/ /*总是指向栈顶元素*/ int top; }; //构造函数 template<class T> SeqStack<T>::SeqStack(int MaxSize) { MaxTop=MaxSize-1; s=new T[MaxSize]; top=-1; } //析构函数 template<class T> SeqStack<T>::~SeqStack() { delete [] s; } /* 在函数的实现中使用了一种断言assert,它是C++提供的一种功能,若断言语句的条 件满足,则继续执行后面的语句;否则出错处理,终止程序执行。assert语句包括在assert.h中。*/ template<class T> void SeqStack<T>::Push(const T &x) { assert(!IsFull()); s[++top]=x; } template<class T> void SeqStack<T>::Pop() {//删除栈顶元素 assert(!IsEmpty()); top--; } template<class T> T SeqStack<T>::Top()const { assert(!IsEmpty()); return s[top]; }
Caculator.h
#pragma once #include <iostream> #include <math.h> #include "Stack.h" class Calculator { private: SeqStack<double> S; /*私有数据成员是一个栈,用于存放操作数*/ void PushOperand(double op); /*操作数进栈*/ bool GetOperands(double &op1, double &op2); /*两个操作数出栈*/ void DoOperator(char optor); /*操作符进行处理(遇到操作符时调用)*/ public: Calculator(int MaxSize):S(MaxSize) { };/*构造函数*/ void Run(); void Clear(); }; void Calculator::PushOperand(double op) {/*操作数进栈*/ S.Push(op); } bool Calculator::GetOperands(double &op1, double & op2) {/*两个操作数出栈*/ if (S.IsEmpty()) { cerr<<"Missing operand!"<<endl; return false;} else /*得到操作数的值,然后出栈*/ { op1=S.Top(); S.Pop(); } if (S.IsEmpty()) /*得到操作数的值,然后出栈*/ { cerr<<"Missing operand!"<<endl; return false; } else { op2= S.Top(); S.Pop(); } return true; } void Calculator::DoOperator(char oper) { bool result; double oper1,oper2; result=GetOperands(oper1,oper2); if (result) switch(oper)/*注意操作数的顺序*/ { case '+': S.Push(oper2+oper1); break; case '-': S.Push(oper2-oper1); break; case '*': S.Push(oper2*oper1); break; case '/': if (oper1==0.0) { cerr<<"Divide by 0!"<<endl; Clear();} else S.Push(oper2/oper1); break; case '^': S.Push(pow(oper2,oper1)); break; } else Clear(); } void Calculator::Run() { char c; double operand; while (cin>>c,c!='#') { switch(c) { case '+': case '-': case '*': case '/': case '^': DoOperator(c); break; /*以上为遇到操作符的情况*/ default: cin.putback(c); /*将字符放回输入流*/ cin>>operand; PushOperand(operand); break; } } if (S.Top()) cout<<S.Top()<<endl;/*输出的是什么?计算结果*/ } void Calculator::Clear() { S.SetNull();}
计算器类的应用程序:
#include “Caculator.h” const int SIZE=20; void main() { Calculator Cal(SIZE); Cal.Run(); }
输入:6 4 2 - / 3 2 * + #
结果:9