数据结构之线性表

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

猜你喜欢

转载自cppbomb.iteye.com/blog/1481219