这篇文章是关于严蔚敏清华版《数据结构》教材的代码,包括书上大纲规定的线性表,链表,栈,队列,二叉树,图,排序,

查找等基本算法的编码,还包括循环链表,广义表,两栈共享空间,字符串模式匹配等非常规,较难数据结构的编码,除此之外书本

后面大量的思考题,例如约瑟夫环,括号匹配,迷宫问题,八皇后,火车厢重排,斐波那契查找等一些列经典问题也有代码。文章中

的代码,均已调试通过,并附有程序运行结果,读者可以自行复制运行。

   这是我用一个假期重学数据结构的劳动结果,希望此篇文章,能给初学数据局结构的同学以帮助,代码若有什么问题,可以

直接用QQ与我联系,感谢赐教。

   由于整个篇幅较长,相关内容按照数据结构课本章节内容组织。下面是第二章,其他章节请参照其他博客。

            第二章  栈,队列,串

 

顺序栈

#include <iostream>

using namespace std;

const int StackSize=100;

template <class T>

class SeqStack

{

private:

T data[StackSize];

int top;

public:

SeqStack();

~SeqStack();

T GetTop();

bool Empty();

void  Push(T x);

T Pop();

};

template <class T>

SeqStack<T>::SeqStack()

{

top=-1;

}

template <class T>

SeqStack<T>::~SeqStack()

{

top=-1;

}

template <class T>

T SeqStack<T>::GetTop()

{

 

if(top==-1)throw"栈为空";

return data[top];

}

template <class T>

bool SeqStack<T>::Empty ()

{

if(top==-1)

return true;

else 

return false;

}

template <class T>

void  SeqStack<T>::Push(T x)

{

if(top==StackSize-1)

throw"栈上溢";

top++;

data[top]=x;

}

template <class T>

T SeqStack<T>::Pop ()

{

if(top==-1)

throw"栈下溢";

T value=data[top];

top--;

return value;

}

void main()

{

cout<<"**********顺序栈的基本操作*********"<<endl;

SeqStack <int> S1;

for(int i=0;i<50;i++)

S1.Push(i);

cout<<S1.GetTop()<<endl;

int count=0;

for(i=0;i<50;i++)

{

count++;

cout<<S1.Pop()<<" ";

if(count%10==0)

cout<<endl; 

}

cout<<S1.Empty()<<endl;

}

两栈共享空间

#include <iostream>

using namespace std;

const int StackSize=100;

template <class T>

class BothStack

{

private:

T Data[StackSize];

int top1;

int top2;

public: 

BothStack(){top1=-1;top2=StackSize;}

~BothStack(){top1=-1;top2=StackSize;}

T GetTop(int i);

bool Empty(int i);

void Push(int i,T x);

T Pop(int i);

};

template <class T>

T BothStack<T>::GetTop (int i)

{

if(i==1)

{

if(top1==-1)

throw "栈1为空!";

return Data[top1];

}

else 

{

if(top2==StackSize)

throw"栈2为空!";

return Data[top2];

}

}

template <class T>

bool BothStack<T>::Empty (int i)

{

if(i==1)

{

if(top1==-1)

return true;

else 

return false;

}

else 

{

if(top2==StackSize)

return true;

else 

return false;

}

}

template <class T>

void BothStack<T>::Push(int i,T x)

{

if(top2==top1+1)

throw"栈上溢!";

if(i==1)

{

top1++;

Data[top1]=x;

}

if(i==2)

{

top2--;

Data[top2]=x;

}

}

template <class T>

T BothStack<T>::Pop (int i)

{

if(i==1)

{

if(top1==-1)

throw"栈1下溢";

return Data[top1--];

}

if(i==2)

{

if(top2==StackSize)

throw"栈2下溢";

return Data[top2++];

}

}

void main()

{

cout<<"**********两栈共享空间操作***********"<<endl;

BothStack<int> Bs1,Bs2;

for(int i=-30;i<=-1;i++)

Bs1.Push (1,i);

for(int j=1;j<=30;j++)

Bs2.Push (2,j);

cout<<Bs1.GetTop(1)<<endl;

int count1=0;

for(i=0;i<30;i++ )

{

cout<<Bs1.Pop(1)<<" ";

count1++;

if(count1%10==0)

cout<<endl;

}

cout<<Bs1.Empty(1)<<endl;

cout<<"************************"<<endl;

cout<<Bs2.GetTop(2)<<endl;

int count2=0;

for(i=0;i<30;i++ )

{

cout<<Bs2.Pop(2)<<" ";

count2++;

if(count2%10==0)

cout<<endl;

}

cout<<Bs2.Empty(2)<<endl;

}

链栈

#include <iostream>

using namespace std;

template <class T>

struct Node

{

T data;

Node<T> *next;

};

template <class T>

class LinkStack

{

private:

Node<T> *top;

public:

LinkStack()

{top=NULL;}

~LinkStack();

T GetTop()

{

if(top!=NULL)

return top->data;

else

throw"链栈为空!";

}

void Push(T x);

T Pop();

bool Empty()

{

if(top==NULL)

return true;

else

return false;

}

};

template <class T>

LinkStack<T>::~LinkStack ()

{

Node <T> *p;

while(top)

{

p=top->next ;

delete top;

top=p;

}

}

template <class T>

void LinkStack<T>::Push(T x)

{

Node <T> *s;

s=new Node<T>;

s->data=x;

s->next=top;

top=s;

}

template <class T>

T LinkStack<T>::Pop ()

{

if(top==NULL)

throw"链栈为空!";

T x=top->data;

Node<T> *p=top;

top=top->next;

delete p;

return x;

}

void main()

{

cout<<"***********链栈基本操作************"<<endl;

LinkStack<int> L;

for(int i=0;i<9;i++)

L.Push(i);

cout<<L.GetTop ()<<endl;

for(i=0;i<9;i++)

cout<<L.Pop()<<" ";

cout<<endl;

cout<<L.Empty ()<<endl;

}

循环队列

#include <iostream>

using namespace std;

const int QueueSize=10;

template <class T>

class CirQueue

{

private :

T data[QueueSize];

int front,rear;

public:

CirQueue();

~CirQueue(){}

T GetQueue();

bool Empty();

bool Full();

int Length();

void Insert(T x);

T Delete();

void Print();

};

template <class T>

CirQueue<T>::CirQueue()

{

front=rear=0;

}

template <class T>

T CirQueue<T>::GetQueue()

{

if(front==rear)

throw"队列为空!";

int i=(front+1)%QueueSize;

return this->data[i];

}

template <class T>

bool CirQueue<T>::Empty ()

{

if(rear==front)

return true;

else 

return false;

}

template <class T>

bool CirQueue<T>::Full ()

{

if((rear+1)%QueueSize==front)

return true;

else 

return false;

}

template <class T>

int CirQueue<T>::Length ()

{

return (this->rear-this->front+QueueSize)%QueueSize;

}

template <class T>

void CirQueue<T>::Insert(T x)

{

if((rear+1)%QueueSize==front)

throw "队列上溢!";

rear=(rear+1)%QueueSize;

data[rear]=x;

}

template <class T>

T CirQueue<T>::Delete ()

{

if(rear==front)

throw"队列下溢!";

front=(front+1)%QueueSize;

return data[front];

}

template <class T>

void CirQueue<T>::Print ()

{

if(rear==front)

cout<<"队列为空"<<endl;

else

{

cout<<"***********************************"<<endl;

int length=(rear-front+QueueSize)%QueueSize;

int count=0;

for(int i=(front+1)%QueueSize;;i=(i+1)%QueueSize)

{

if(count>=length)

break;

cout<<"data["<<i<<"]="<<data[i]<<" ";

count++;

if(count%5==0)

cout<<endl;

}

cout<<endl;

}

}

void main()

{

cout<<"************循环队列实验************"<<endl;

CirQueue <int>Cq;

for(int i=1;i<=9;i++)

Cq.Insert (i);

Cq.Print();

Cq.Delete();Cq.Delete();Cq.Delete();

Cq.Insert(-1);Cq.Insert(-2);Cq.Insert(-3);

Cq.Print();

cout<<endl<<Cq.GetQueue()<<endl;

cout<<endl<<Cq.Empty()<<endl;

cout<<endl<<Cq.Full()<<endl;

}

关于串的学习:

#include <iostream>

using namespace std;

const int StrSize=100;

class Str

{

public://迫不得已,因为在类外不能引用类的私有成员

char Data[StrSize];

public:

Str(){}

Str(char a[],int Length);

~Str(){};

int  BF(char S[],char T[]);

void Print();

};

Str::Str(char a[],int Length)

{

    Data[0]=Length+'0';//数字转化为字符

for(int i=1;i<=Length;i++)

Data[i]=a[i-1];

}

void Str::Print ()

{

int Length=Data[0]-'0';//字符转化为整型数

for(int i=1;i<=Length;i++)

cout<<Data[i]<<" ";

cout<<endl;

}

int  Str::BF(char S[],char T[])

{

int i=1; int j=1;

while((i<=S[0]-'0') && (j<=T[0]-'0'))

{

if(S[i]==T[j])

{

i++;

j++;

}

else

{

i=(i-j+1)+1;

j=1;

}

}

if(j>(T[0]-'0'))

return (i-j+1);

else 

return -1;

}

void main()

{

Str master("abcdeidfdfafafa",15);

master.Print ();

Str sub("dfa",3);

sub.Print ();

cout<<endl<<master.BF(master.Data ,sub.Data )<<endl;

}

没有解决的问题:

#include <iostream>

using namespace std;

 

void main()

{

int Len=5;

const int Size=(const)Len;

int next[Size];

cout<<Size<<endl;

}

错误:

#include <iostream>

using namespace std;

const int StrSize=100;

class Str

{

public://迫不得已,因为在类外不能引用类的私有成员

char Data[StrSize];

public:

Str(){this->Data[0]=0+'0';}

Str(char a[],int Length);

~Str(){};

int  BF(char S[],char T[]);

void Print();

void Insert(char x);//每次在尾部插入一个字符

Str Next(char a[],int Len);

};

Str::Str(char a[],int Length)

{

    Data[0]=Length+'0';//数字转化为字符

for(int i=1;i<=Length;i++)

Data[i]=a[i-1];

}

void Str::Print ()

{

int Length=Data[0]-'0';//字符转化为整型数

for(int i=1;i<=Length;i++)

cout<<Data[i]<<" ";

cout<<endl;

}

int  Str::BF(char S[],char T[])

{

int i=1; int j=1;

while((i<=S[0]-'0') && (j<=T[0]-'0'))

{

if(S[i]==T[j])

{

i++;

j++;

}

else

{

i=(i-j+1)+1;

j=1;

}

}

if(j>(T[0]-'0'))

return (i-j+1);

else 

return -1;

}

void Str::Insert (char x)

{

int Len=(Data[0]-'0')+1;

Data[0]=Len+'0';

Data[Len]=x;

}

Str Str::Next (char T[], int Len)

{

Str next("",Len);

int k=0;

for(int j=1;j<=T[0]-'0';j++)

{

if(j==1)

next.Data[j]=0+'0';

if(j>=2)

{

next.Data[j]=1+'0';

for(k=2;k<j;k++)

{

Str sub1;

for(int m=1;m<=k-1;m++)

sub1.Insert(T[m]);

Str sub2;

for(int n=j-k+1;n<=j-1;n++)

sub2.Insert(T[n]);

//这是为了调试程序设置的

//cout<<j<<":";sub1.Print ();cout<<"** ";sub2.Print ();cout<<" k="<<k<<endl; 

//特别注意sub1.Data与sub2.Data的长度均为100,在这里只在存储

//了一些元素,后面很大一部分元素是未知的,故而二者永远不相等

/*if(sub1.Data==sub2.Data)

if(k>next.Data[j]-'0')next.Data[j]=k+'0';*/

for(int i=1;i<=sub1.Data[0]-'0';i++)

{

 if(sub1.Data[i]==sub2.Data[i])

 continue;

 else 

 break;

}

if(i>sub1.Data[0]-'0')//判断是否已经比较到两个字符串的结尾

if(k>next.Data[j]-'0')next.Data[j]=k+'0';

}

}

}

return next;

}

void main()

{

cout<<"*************串的基本操作实验*****************"<<endl;

Str master("abcdeidfdfafafa",15);

cout<<"master:"; master.Print ();

Str sub("dfa",3);

cout<<"sub:"; sub.Print ();

cout<<"location:";

cout<<master.BF(master.Data ,sub.Data )<<endl;

cout<<"*****求一个字符串的特征数组next[]:"<<endl;

Str next=sub.Next ("5abcac" ,5);//特别注意此处传递子字符串的技巧

next.Print ();

}

#include <iostream>

using namespace std;

const int StrSize=100;

class Str

{

public://迫不得已,因为在类外不能引用类的私有成员

char Data[StrSize];

public:

Str(){this->Data[0]=0+'0';}

Str(char a[],int Length);

~Str(){};

int  BF(char S[],char T[]);

void Print();

void Insert(char x);//每次在尾部插入一个字符

Str Next(char a[],int Len);

int KMP(char S[],char T[],char next[]);

};

Str::Str(char a[],int Length)

{

    Data[0]=Length+'0';//数字转化为字符

for(int i=1;i<=Length;i++)

Data[i]=a[i-1];

}

void Str::Print ()

{

int Length=Data[0]-'0';//字符转化为整型数

for(int i=1;i<=Length;i++)

cout<<Data[i]<<" ";

cout<<endl;

}

int  Str::BF(char S[],char T[])

{

int i=1; int j=1;

while((i<=S[0]-'0') && (j<=T[0]-'0'))

{

if(S[i]==T[j])

{

i++;

j++;

}

else

{

i=(i-j+1)+1;

j=1;

}

}

if(j>(T[0]-'0'))

return (i-j+1);

else 

return -1;

}

void Str::Insert (char x)

{

int Len=(Data[0]-'0')+1;

Data[0]=Len+'0';

Data[Len]=x;

}

Str Str::Next (char T[], int Len)

{

Str next("",Len);

int k=0;

for(int j=1;j<=T[0]-'0';j++)

{

if(j==1)

next.Data[j]=0+'0';

if(j>=2)

{

next.Data[j]=1+'0';

for(k=2;k<j;k++)

{

Str sub1;

for(int m=1;m<=k-1;m++)

sub1.Insert(T[m]);

Str sub2;

for(int n=j-k+1;n<=j-1;n++)

sub2.Insert(T[n]);

for(int i=1;i<=sub1.Data[0]-'0';i++)//比较两个字符串前面有限部分是否相等

{

if(sub1.Data[i]==sub2.Data[i])

continue;

else 

break;

}

if(i>sub1.Data[0]-'0')//判断是否已经比较到两个字符串的结尾

if(k>next.Data[j]-'0')next.Data[j]=k+'0';

}

}

}

return next;

}

int Str::KMP (char S[],char T[],char next[])

{

int i=1,j=1;

while(i<=S[0]-'0' && j<=T[0]-'0')

{

if(S[i]==T[j])//一定要注意i,j分别与那个字符串关联

{

i++;

j++;

}

else

j=next[j]-'0';

if(j==0)

{

 i++;

 j++;

}

}

if(j>T[0]-'0')

return (i-j+1);

else 

return -1;

}

void main()

{

cout<<"*************串的基本操作实验*****************"<<endl;

cout<<"--------------朴素模式匹配算法:"<<endl;

Str master("abcdeidfdfafafa",15);

cout<<"master:"; master.Print ();

Str sub("dfa",3);

cout<<"sub:"; sub.Print ();

cout<<"location:";

cout<<master.BF(master.Data ,sub.Data )<<endl;

cout<<"--------------改进模式匹配算法:"<<endl;

Str Master("ababcabcacbab",13);

cout<<"Master:"; Master.Print ();

Str Sub("abcac",5);

cout<<"Sub:"; Sub.Print ();

cout<<"*****求一个字符串的特征数组next[]:"<<endl;

Str next=Sub.Next ("5abcac" ,5);//特别注意此处传递子字符串的技巧

next.Print ();

int Loca=Master.KMP (Master.Data ,Sub.Data ,next.Data );

cout<<"Location:"<<Loca<<endl;

}

#include <iostream>

using namespace std;

#include <string>

const int StrSize=100;

class Str

{

public://迫不得已,因为在类外不能引用类的私有成员

char Data[StrSize];

public:

Str(){this->Data[0]=0+'0';}

Str(char a[],int Length);

~Str(){};

    void Print();

int  BF(char S[],char T[]);

void Insert(char x);//每次在尾部插入一个字符

Str Next(char a[],int Len);

int KMP(char S[],char T[],char next[]);

    int Length();

string StrConcat(char T[]);

string StrSub(int i,int Length);

int StrCompare(char T[]);

string StrInsert(char T[],int i);

string StrDelete(int i,int Length);

};

Str::Str(char a[],int Length)

{

    Data[0]=Length+'0';//数字转化为字符

for(int i=1;i<=Length;i++)

Data[i]=a[i-1];

}

int Str::Length()

{

return Data[0]-'0';

}

string Str::StrConcat(char T[])

{

int len=strlen(T);

int Length=this->Data [0]-'0';

int strLen=len+Length;

for(int i=Length+1;i<=strLen;i++)

this->Data [i]=T[i-Length-1];

Data[i]='\0';//

this->Data [0]=strLen+'0';

return this->Data ;

}

string Str::StrSub(int i,int Length)

{

Str sub;

for(int j=i;j<=i+Length-1;j++)

sub.Insert (this->Data [j]);

return sub.Data ;

}

int Str::StrCompare(char T[])

{

if(this->Data [0]-'0'!=strlen(T))

{

int min;

if(this->Data [0]-'0'>strlen(T))

min=strlen(T);

else 

min=this->Data [0]-'0';

for(int i=0;i<min;i++)

{

 

if(this->Data [i+1]==T[i])

continue;

if(this->Data [i+1]>T[i])

return 1;

else

return -1;

}

if(i==min)

{

if(min==this->Data [0]-'0')

return -1;

else 

return 1;

}

}

else

{

for(int i=0;i<strlen(T);i++)

{

 

if(this->Data [i+1]==T[i])

continue;

if(this->Data [i+1]>T[i])

return 1;

else

return -1;

}

if(i==strlen(T))

return 0;

}

}

string Str::StrInsert(char T[],int i)

{

int len=strlen(T);

    if(i>this->Data [0]-'0'+1)

throw"插入位置错误!";

else if(i==this->Data [0]-'0'+1)

for(int j=0;j<len;j++)

this->Insert (T[j]);

else

{

for(int k=Data[0]-'0'+len;k>=i;k--)

Data[k]=Data[k-len];

for(int m=i;m<i+len;m++)

Data[m]=T[m-i];

}

int len_now=this->Data [0]-'0'+len;

Data[0]=len_now+'0';

Data[len_now+1]='\0';//

return this->Data;

}

string Str::StrDelete(int i,int Length)

{

for(int j=i+Length;j<=this->Data [0]-'0';j++)

this->Data [j-Length]=this->Data [j];

return this->Data ;

}

void Str::Print ()

{

int Length=Data[0]-'0';//字符转化为整型数

for(int i=1;i<=Length;i++)

cout<<Data[i]<<" ";

//cout<<endl;

}

int  Str::BF(char S[],char T[])

{

int i=1; int j=1;

while((i<=S[0]-'0') && (j<=T[0]-'0'))

{

if(S[i]==T[j])

{

i++;

j++;

}

else

{

i=(i-j+1)+1;

j=1;

}

}

if(j>(T[0]-'0'))

return (i-j+1);

else 

return -1;

}

void Str::Insert (char x)

{

int Len=(Data[0]-'0')+1;

Data[0]=Len+'0';

Data[Len]=x;

}

Str Str::Next (char T[], int Len)

{

Str next("",Len);

int k=0;

for(int j=1;j<=T[0]-'0';j++)

{

if(j==1)

next.Data[j]=0+'0';

if(j>=2)

{

next.Data[j]=1+'0';

for(k=2;k<j;k++)

{

Str sub1;

for(int m=1;m<=k-1;m++)

sub1.Insert(T[m]);

Str sub2;

for(int n=j-k+1;n<=j-1;n++)

sub2.Insert(T[n]);

for(int i=1;i<=sub1.Data[0]-'0';i++)//比较两个字符串前面有限部分是否相等

{

if(sub1.Data[i]==sub2.Data[i])

continue;

else 

break;

}

if(i>sub1.Data[0]-'0')//判断是否已经比较到两个字符串的结尾

if(k>next.Data[j]-'0')next.Data[j]=k+'0';

}

}

}

return next;

}

int Str::KMP (char S[],char T[],char next[])

{

int i=1,j=1;

while(i<=S[0]-'0' && j<=T[0]-'0')

{

if(S[i]==T[j])//一定要注意i,j分别与那个字符串关联

{

i++;

j++;

}

else

j=next[j]-'0';

if(j==0)

{

i++;

j++;

}

}

if(j>T[0]-'0')

return (i-j+1);

else 

return -1;

}

void main()

{

cout<<"*************串的基本操作实验*****************"<<endl;

cout<<"--------------朴素模式匹配算法:"<<endl;

Str master("abcdeidfdfafafa",15);

cout<<"master:"; master.Print ();cout<<endl;

Str sub("dfa",3);

cout<<"sub:"; sub.Print ();cout<<endl;

cout<<"location:";

cout<<master.BF(master.Data ,sub.Data )<<endl;

cout<<"--------------改进模式匹配算法:"<<endl;

Str Master("ababcabcacbab",13);

cout<<"Master:"; Master.Print ();cout<<endl;

Str Sub("abcac",5);

cout<<"Sub:"; Sub.Print ();cout<<endl;

cout<<"*****求子字符串的特征数组next[]:"<<endl;

Str next=Sub.Next ("5abcac" ,5);//特别注意此处传递子字符串的技巧

next.Print ();cout<<endl;

int Loca=Master.KMP (Master.Data ,Sub.Data ,next.Data );

cout<<"Location:"<<Loca<<endl;

cout<<"-----------求字符串的长度:";

cout<<Master.Length()<<endl;

cout<<"-----------字符串连接:"<<endl;

cout<<"Master+Sub:"<<Master.StrConcat ("abcac")<<endl;

cout<<"-----------字符串比较:"<<endl;

cout<<"1:"; Sub.Print(); cout<<" 与 abca "<<Sub.StrCompare ("abca")<<endl;

cout<<"2:"; Sub.Print(); cout<<" 与 abcacb "<<Sub.StrCompare ("abcacb")<<endl;

cout<<"3:"; Sub.Print(); cout<<" 与 aBca "<<Sub.StrCompare ("aBca")<<endl;

cout<<"4:"; Sub.Print(); cout<<" 与 abcaC "<<Sub.StrCompare ("abcaC")<<endl;

cout<<"5:"; Sub.Print(); cout<<" 与 abcac "<<Sub.StrCompare ("abcac")<<endl;

cout<<"-----------字符串插入:"<<endl;

cout<<"向Master中插入123:"<<Master.StrInsert ("123",5)<<endl; 

cout<<"-----------字符串删除:"<<endl;

cout<<"删除Master自6起长度为4的字符串:"<<Master.StrDelete (6,4)<<endl<<endl;

}

汉诺塔问题

递归调用的内部执行过程:

1.运行开始时,首先为递归调用建立一个工作栈,其结构包括值参,局部变量,和返回地址;

2.每次执行递归调用之前,把递归函数的值参和局部变量的当前值及调用后的返回地址入栈;

3.每次递归调用结束后,将栈顶元素出栈,使相应的值参和局部变量恢复为调用前的值,然后转向返回地址指定的位置继续执行。

#include <iostream>

using namespace std;

void Move(char A,char C);

void Hanoi(int n,char A,char B,char C);

void main()

{

cout<<"***************汉诺塔问题***************"<<endl;

int n;

cout<<"输入塔A上原始盘子的数目:";

cin>>n;

cout<<"^^^^^^^^^^^^^^^^^具体移动过程如下:"<<endl;

Hanoi(n,'A','B','C');

}

void Move(char A,char C)

{

cout<<A<<"--->"<<C<<endl;

}

void Hanoi(int n,char A,char B,char C)

{

if(n==1)

Move(A,C);

else

{

Hanoi(n-1,A,C,B);

Move(A,C);

Hanoi(n-1,B,A,C);

}

}

循环队列的应用:

#include <iostream>

using namespace std;

const int MaxSize=15;

const int inf=10000;

class Train

{

private:

int Data[MaxSize];

int front ,rear;

public:

Train();

~Train(){}

int GetFront();//取队头元素

int GetRear();//取队尾元素

int DelFront();//队头元素出队

void InsertRear(int x);//向循环队列中插入元素

bool Full();//判断队列是否为满

bool Empty();//判读队列是否为空

void InitInput(int a[],int n);//初始化输入轨循环队列

int Search(Train t[],int k,int input);

bool AllEmpty(Train t[],int k);

int CountEmpty(Train T[],int m);//计算缓冲队列的个数

void bufferIntooutput(Train t[],int k,Train &out);

    void Order();//重新排列火车

void Print();//打印循环队列

};

Train::Train()

{

front =rear=-1;

}

bool Train::Empty()

{

if(rear==front)

return true;

else

return false;

}

bool Train::Full ()

{

if((rear+1)%MaxSize==front)

return true;

else

return false;

}

int Train:: GetFront()

{

if(!this->Empty())

return this->Data [front+1];

else

throw"队列为空";

}

int Train::GetRear ()

{

if(!this->Empty())

return this->Data [rear];

else

throw"队列为空";

}

int Train::DelFront ()

{

if(front!=rear)

{

int x=Data[front+1];

front=(front+1)%MaxSize;

return x;

}

else

throw"队列为空";

}

void Train::InsertRear (int x)

{

if(!this->Full ())

{

rear=(rear+1)%MaxSize;

Data[rear]=x;

}

else

throw"队列上溢!";

}

void Train::InitInput(int a[],int n)//初始化输入缓冲轨队列

{

if(n>MaxSize-1)//循环队列有一个位置是空着的

throw"队列上溢";

for(int i=0;i<n;i++)

this->InsertRear(a[i]);

}

int Train::CountEmpty (Train T[],int m)

{

int Number=0;

for(int i=0;i<m;i++)

{

if(T[m].Empty ())

Number++;

}

return Number;

}

//查找一个队尾元素小于输入轨队首元素且队尾元素最大的缓冲轨

int Train::Search (Train t[],int k,int input)

{

int which=-1;

int margin=100;

for(int i=0;i<k;i++)

{//如果队列为空,则里面存储的东西是未知的,结果无法预知

if(t[i].front !=t[i].rear && input>t[i].GetRear ())//缓冲队列队尾元素必须先小于input

{

if(t[i].GetRear ()<input && margin>input-t[i].GetRear ())

{

which=i;

margin=input-t[i].GetRear ();

}

}

}

return which;

}

//判断所有缓冲轨是否全为空

bool Train::AllEmpty (Train t[],int k)

{

int count=0;

for(int i=0;i<k;i++)

{

if(t[i].front ==t[i].rear)

count++;

}

if(count>=k)

return true;

else

return false;

}

//将缓冲轨中的火车厢插入到输出轨

void Train::bufferIntooutput (Train t[],int k,Train &out)

{

    int flag=0;

while(!flag)

int min=100;

int which=-1;

for(int i=0;i<k;i++)//获得缓冲队列队首元素最小队列的标号

{

if(t[i].front !=t[i].rear)

{//注意此处万万不可写成min>t[i].DelFront ();

if(min>t[i].GetFront () )//注意如果此缓冲队列队首元素不是最小,此次并不出队

{

min=t[i].GetFront ();

which=i;

}

}

}

flag=AllEmpty(t,k);

if(min!=100)

out.InsertRear (t[which].DelFront ());

else

break;

}

}

void Train::Order ()//重排火车

{

int Length=(rear-front+MaxSize)%MaxSize;//得到输入循环队列的长度

    int k;

Train t[MaxSize];//定义对象数组

cout<<"输入缓冲轨的个数:";

cin>>k;

cout<<"*****输出排好序的火车序列:"<<endl;

Train OutPut;//定义输出缓冲轨

int Nowout=1;//初始化下一个要输出的火车厢编号

int Temp;//定义Temp暂存输入缓冲轨队首元素

for(int i=0;i<Length;i++) 

{

Temp=this->Data[front+1];

if(Temp==Nowout)//如果输入缓冲轨元素等于Nowout

{

if(CountEmpty(t,k)>=1)

{

OutPut.InsertRear(Temp);

Nowout++;

}

else

cout<<"火车厢不能重排!";

}

else//如果输入缓冲轨元素不等于Nowout

{

for(int j=0;j<k;j++)//一次扫描每个缓冲轨,并且取出队首元素

{

if(t[j].front !=t[j].rear )//如果队列为空,去队首元素会抛出异常

{

if (t[j].GetFront ()==Nowout)

{

int DelNum=t[j].DelFront ();//删除此缓冲队列头部元素

OutPut.InsertRear(DelNum);//此时虽然将缓冲队列的队首插入到输出缓冲轨中,但是从输入轨中取出的队头元素还没有处理

Nowout++;

break;

}

}

}

/************只要Nowout!=Temp这段代码都要执行*************/

//查找一个小于输入轨队首元素的最大队尾元素的缓冲轨道的编号

int exist=this->Search (t,k,Temp);

if(exist!=-1)//如果存在,则将输入缓冲轨队首元素插入到此缓冲轨

t[exist].InsertRear (Temp);

else//不存在这样的缓冲轨

{

if(CountEmpty(t,k)>1)

{//如果空缓冲轨的个数大于1,选择一个空缓冲轨将输入缓冲轨队首元素插入

for(int m1=0;m1<k;m1++)

{

if(t[m1].front ==t[m1].rear)

{//注意此处大括号不可省

t[m1].InsertRear (Temp);

break;

}

}

}

else

cout<<"火车厢不能重排!";

}

}

front=(front+1)%MaxSize;//输入缓冲轨队首元素出队

}

cout<<endl;//

//最后还得将各个缓冲轨道中的车厢插入到出轨道中

if(!AllEmpty(t,k))//如果所有缓冲轨道并非全为空

bufferIntooutput(t,k,OutPut);//执行这个函数时候出现异常

OutPut.Print();//打印输出缓冲轨

}

void Train::Print ()//打印循环队列

{

for(int i=front+1;i<=rear;i++)

cout<<Data[i]<<" ";

cout<<endl; 

}

void main()

{

cout<<"************火车厢重排问题************"<<endl;

int a[9];

cout<<"输入初始九节车厢的初始情况:"<<endl;

for(int i=0;i<9;i++)

cin>>a[i];

Train train;

train.InitInput (a,9);

train.Order();

}

 posted on 2012-10-02 13:40  莽原_狼  阅读(202)  评论(0编辑  收藏  举报