循環隊列拾遺-使用數組實現循環隊列

循環隊列

爲充分利用向量空間,克服”假溢出”現象的方法是:將向量空間想象爲一個首尾相接的圓環,並稱這種向量爲循環向量。存儲在其中的隊列稱爲循環隊列(Circular Queue)。這種循環隊列可以以單鏈表的方式來在實際編程應用中來實現。

循環隊列的問題

循環隊列中,由於入隊時尾指針向前追趕頭指針;出隊時頭指針向前追趕尾指針,造成隊空和隊滿時頭尾指針均相等。

因此,無法通過條件front==rear來判別隊列是”空”還是”滿”。

解決這個問題的方法至少有兩種:
1. 另設一布爾變量以區別隊列的空和滿;
2. 另一種方式就是數據結構常用的: 隊滿時:(rear+1)%n==front,n爲隊列長度(所用數組大小),由於rear,front均爲所用空間的指針,循環只是邏輯上的循環,所以需要求餘運算。

話不多說,先貼代碼再進行解釋

//來自於http://blog.csdn.net/nyhuachen/article/details/6422352
/************************************************************************/
/* author : thomas
   E-mail: [email protected]                                         */
/************************************************************************/
//循環隊列(數組實現)
#include <stdlib.h>
#include <stdio.h>
#define MAXSIZE 5
typedef int T;
typedef struct tag
{
    int front, rear, MaxSize, count; //其實MaxSize變量完全可以不要
    T elements[MAXSIZE];
} QUEUE;

定義了使用到的變量,包括front\rear\count等
front指定隊首位置,刪除一個元素就將front順時針移動一位;
rear指向元素要插入的位置,插入一個元素就將rear順時針移動一位;
count存放隊列中元素的個數,當count等於MaxSize時,不可再向隊列中插入元素。

void creat( QUEUE *queue )
{
    queue -> front = 0;
    queue -> rear = 0;
    queue -> count = 0;
    queue -> MaxSize = MAXSIZE - 1;
}

這個應該類似於java中的構造函數

int is_empty( QUEUE queue)  //其實最好傳指針免得棧開銷太大
{
    if ( queue.count == 0 )
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
int is_full( QUEUE queue )
{
    if ( queue.count == MAXSIZE )
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

這是用了第一種判斷隊列滿的方式,只不過把bool型的變量轉換成了MAXSIZE以及count這兩個變量的求是否相等。

void readqueue( QUEUE queue ) //just read the value
{
    if ( queue.count == 0 )  //可以用前面的is_empty函數進行判斷
    {
        printf("the queue is empty! no number is available! /n");
    }
    else
    {
        printf("the first number is %d /n", queue.elements[queue.front]);
    }
}
void in_queue( QUEUE *queue, T value )
{
    if ( queue -> count == MAXSIZE )  //可以利用前面的is_full函數進行判斷
    {
        printf("sorry! the queue is full! no space is available!/n");
    }
    else
    {
        if ( queue -> count == 0 )
        {
            //主要是處理隊列爲空時的入隊列
            queue -> elements[queue -> rear] = value;
            queue -> count += 1;
        }
        else
        {
            queue -> rear = (queue -> rear + 1) % MAXSIZE;
            queue -> elements[queue ->rear] = value;
            queue -> count += 1;
        }
    }
}
T out_queue( QUEUE *queue )
{
    if ( queue -> count == 0 )  //可以利用前面的is_empty函數進行判斷
    {
        printf("sorry! the queue is empty! no number is available! /n");
        exit(EXIT_FAILURE);
    }
    else
    {
        queue -> front = (queue -> front + 1) % MAXSIZE;
        queue -> count -= 1;
        return queue -> elements[queue -> front];
    }
}
//print queue
void print( QUEUE queue )
{
    int i = 1;/*count var*/
    if ( queue.count == 0 )
    {
        printf("the queue is empty! no number can be printed! /n");
    }
    else
    {
        //count = queue.count;
        printf("the number of queue is %d /n", queue.count);
        for ( i; i <= queue.count; i++ )
        {
            printf("the %d number is %d /n", i, queue.elements[(queue.front + i - 1) % MAXSIZE]);
            //printf("the %d number is %d /n", i, queue.elements[queue.front + i - 1]);
        }
    }
}
//test functions
void main(int argc, char *argv[])
{
    QUEUE queue;
    creat(&queue);
    //out_queue(&queue);
    in_queue(&queue, 2);
    print(queue);
    in_queue(&queue, 4);
    print(queue);
    in_queue(&queue, 5);
    print(queue);
    in_queue(&queue, 6);
    print(queue);
    in_queue(&queue, 1);
    print(queue);
    out_queue(&queue);
    print(queue);
    in_queue(&queue, 9);
    print(queue);
    //out_queue(&queue);
    //print(queue);
    in_queue(&queue, 7);
    //print(queue);
}

其實這篇文章也想彙總下第二種方法對循環隊列判斷是否滿的解釋:
也即是
–>隊滿時: (rear+1)%maxsize=front
隊滿時的示意圖
–>隊空時:rear=front
當循環隊列爲空時的示意圖
–>正常時:
正常時的示意圖
這部分是http://blog.csdn.net/huangkq1989/article/details/5719529在其的文章處提到的

關鍵在於少用一個位置,用這個位置爲條件將循環隊列的邏輯循環(故之只能用%計算)顯式地表述出來。

有的時候退一步更能海闊天空=V=
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章