这篇文章是关于严蔚敏清华版《数据结构》教材的代码,包括书上大纲规定的线性表,链表,栈,队列,二叉树,图,排序,
查找等基本算法的编码,还包括循环链表,广义表,两栈共享空间,字符串模式匹配等非常规,较难数据结构的编码,除此之外书本
后面大量的思考题,例如约瑟夫环,括号匹配,迷宫问题,八皇后,火车厢重排,斐波那契查找等一些列经典问题也有代码。文章中
的代码,均已调试通过,并附有程序运行结果,读者可以自行复制运行。
这是我用一个假期重学数据结构的劳动结果,希望此篇文章,能给初学数据局结构的同学以帮助,代码若有什么问题,可以
直接用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();
}