循环队列的主要特点及其应用

来源:互联网 发布:网络棋牌频道直播象棋 编辑:程序博客网 时间:2024/06/14 21:33

   相信大家对队列都不陌生,举个列子我就想到排队打饭了,先到的先打饭;也就是说队列同栈相反,是队头取元素,队尾加元素的,我就不多加赘述了。要注意到队列结构由于他的队尾指针指向最后一个数组元素时,队头指针不一定在数组下标为零的地方,这就意味着在数组的前几组数据为空时可能会浪费资源,而队尾却又加不了数据了,这就是顺序队列的一个 假溢出现象,为了解决这个问题,在实际应用中,使用循环队列成为较为理想的数据结构。

循环队列的意思是组成一个环状队列,将队尾指针的下一位子指向队头指针这样在数组空间足够的情况下,不但不会假溢出,而且数组空间多余的空间也可以留下来等待做下一步的添加操作,下面是循环队列的实现代码:

//超超
// 2016 10 6
#include<iostream>
using namespace std;
//使用枚举定义队列类的成员函数的返回值类型
enum error_code{success,underflow,overflow};
//定义x的元素类型
typedef int elementtype;
//定义一个队列类 
const int maxlen=15;


int main(){
void read_write();
read_write();
return 1;
}


class queue{
public:
queue();
bool isempty() const;
bool isfull() const;
/*
const可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。 
还是上面的例子,如果在函数体内修改了i,编译器就会报错; 
例如: void f(const int i) { i=10;//error! } 
*/
/*
为函数重载提供了一个参考。 
class A { ...... 
void f(int i) {......} //一个函数 
void f(int i) const {......} //上一个函数的重载 ...... 
}; 
*/
error_code get_front(elementtype &x) const;//取队头元素
error_code append(const elementtype x);//入队
error_code serve();//出队
private:
int count;
int front;//定义队头的指针
int rear;//定义队尾的指针
elementtype data[maxlen];//定义队列的数组长度


};
//在初始换队列时应该注意不止是将记数器置零,还有队头的指针应该置零,队尾为最大值减一,
//但主要到为了不浪费空间,我们经常使用的是循环队列,所以空队列时尾指针等于头指针
queue::queue(){
count=0;
front=0;
rear=0;
}
bool queue::isempty() const{
if(count==0) return true;
else return false;
}
bool queue::isfull() const{
if(count==maxlen-1) return true;
else return false;
}
//取队头元素时,使用头指针,头指针指向的下一个位子为第一个值
error_code queue::get_front(elementtype &x)const{
if(isempty()) return underflow;
else {
x=data[(front+1)%maxlen];
return success;
}
}
//入队时,头指针不变,尾指针要加一,然后存储,计数器加一
error_code queue::append(const elementtype x){
if(isfull()) return overflow;
else{
rear=(rear+1)%maxlen;
data[rear]=x;
count++;
return success;
}
}
//出队,先入先出,从头部出队列,头指针要指向下一位,同时尾指针要指向上一位
error_code queue::serve(){
if(isempty()) return underflow;
else {
front=(front+1)%maxlen;
count--;
return success;
}
}
//下面我们使用队列存数据
void read_write(){
queue q; 
elementtype x;
while (!q.isfull())
{
cin>>x; 
q.append(x);
}
while (!q.isempty()) 
{
q.get_front(x); 
cout<<x<<"   "; 
q.serve();
}
cout<<endl;
}

这样一段代码是我们比较想要的结果。

记得在打印杨辉三角的时候,我们使用简单的循环和运算,这样一种队列结构,用在打印杨辉三角上的花费上显得会轻松很多。

下面是使用队列来打印杨辉三角(在主函数中调用即可):

// 利用队列Q打印n行杨辉三角形
void  Out_Number(int n)           
{  int s1,s2;  queue Q;                 
    int i,j;
    error_code Ec;                        // 定义错误类型代码,以便调用函数时用
   cout<<1<<endl;                       // 输出第一行上的1 
   Ec=Q.append(1);                     // 所输出的1入队
     for(i=2; i<=n; i++)                 // 依次计算并输出第2~i行上的数据
      {  s1=0;                                   // 存放前一个出队的数
         for(j=1; j<=i-1; j++)          //计算并输出第i行上前 i-1 个数据
         {   Ec= Q.get_front(s2);  Ec=Q.serve( );     // 取队头元素
             cout<<s1+s2;                     // 计算并输出当前行中的一个元素
             Ec=Q.append(s1+s2);      // 所输出的当前行中的元素入队
             s1=s2;                                // 调整变量的值
          }
        cout<<1<<endl;                   // 输出当前行中的最后一个元素1并换行
        Ec=Q.append(1);                  //本行最后的1入队
     }
}

这就是具体应用的一个较好的例子了。

所以遇到像有进有出情况的列子,就可以优先考虑栈和队列的结构,这样来的效率会很高。


1 0