1. 程式人生 > >《資料結構》(C語言版)——迴圈佇列――――佇列的順序儲存結構

《資料結構》(C語言版)——迴圈佇列――――佇列的順序儲存結構

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
// 用到的庫檔案
#include <stdio.h>  // printf();scanf()
#include <stdlib.h> // exit()
#include <malloc.h> // malloc()
#include <time.h>   // srand((unsigned)time(NULL));
// 函式結果狀態程式碼
#define TRUE    1
#define FALSE   0
#define OK      1
#define ERROR   0
#define INFEASIBLE  -1
#define OVERFLOW    -2
// Status是函式的型別,其值是函式結果狀態程式碼
typedef int Status;
// #define ElemType int  // 也可以用巨集定義確定ElemType型別
typedef char QElemType;
// -----迴圈佇列――――佇列的順序儲存結構-----
#define MAXQSIZE 100    // 最大佇列長度
typedef struct {        // 佇列鏈式結構
    QElemType *base;    // 初始化的動態分配儲存空間
    int front;          // 頭指標,若佇列不空,指向佇列頭元素
    int rear;           // 尾指標,若佇列不空,指向佇列尾元素的下一個位置
} SqQueue;

// 操作結果:構造一個空佇列Q。
Status InitQueue(SqQueue &Q) {
    Q.base = (QElemType*)malloc(MAXQSIZE * sizeof(QElemType));
    if(!Q.base)                     // 儲存分配失敗
        exit(OVERFLOW);             // exit(-2)程式異常退出
    Q.front = Q.rear = 0;
    return OK;
}// InitQueue

// 操作結果:銷燬佇列Q,Q不再存在。
Status DestroyQueue(SqQueue &Q) {
    Q.front = Q.rear = 0;
    free(Q.base);
    return OK;
}// DestroyQueue

// 操作結果:把Q置為空佇列。
Status ClearQueue(SqQueue &Q) {
    Q.front = Q.rear = 0;
    return OK;
}// ClearQueue

// 操作結果:若Q為空佇列,返回TRUE,否則返回FALSE
Status QueueEmpty(SqQueue Q) {
    if(Q.front == Q.rear)
        return TRUE;                // 返回1
    else
        return FALSE;               // 返回0
}// QueueEmpty

// 操作結果:返回Q的元素個數,即佇列的長度。
int QueueLength(SqQueue Q) {
    return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}// QueueLength

// 操作結果:若Q為非空佇列,則用e返回Q的隊頭元素。
Status GetHead(SqQueue Q, QElemType &e) {
    if(Q.front == Q.rear)
        return ERROR;               // 空佇列
    e = Q.base[Q.front];            // 取隊頭元素
    printf("獲取的隊頭元素:%c\n", e);
    return OK;
}// GetHead

// 操作結果:插入元素e為Q的新的隊尾元素。
Status EnQueue(SqQueue &Q, QElemType e) {
    // 少用一個元素空間,約定以“佇列頭指標在佇列尾指標的下一位置上”作為佇列滿的標誌。
    if((Q.rear + 1) % MAXQSIZE == Q.front)
        return ERROR;               // 佇列滿
    Q.base[Q.rear] = e;             // 插入元素e
    Q.rear = (Q.rear+1)%MAXQSIZE;   // rear後移
    printf("插入的隊尾元素:%c\n", e);
    return OK;
}// EnQueue

// 操作結果:刪除Q的隊頭元素,並用e返回其值。
Status DeQueue(SqQueue &Q, QElemType &e) {
    if(Q.front == Q.rear)
        return ERROR;               // 空佇列
    e = Q.base[Q.front];
    Q.front = (Q.front+1)%MAXQSIZE; // front後移
    printf("刪除的隊頭元素:%c\n", e);
    return OK;
}

Status visit(QElemType e) {
    printf("%c -> ", e);
    return OK;
}// DeQueue
// 操作結果:從 隊頭到隊尾,依次對Q的每個資料元素呼叫函式visit()。一旦vistit()失敗,剛操作失敗。
Status QueueTraverse(SqQueue Q, Status (*pfn_visit)(QElemType)) {
    if(Q.front == Q.rear) {
        printf("佇列為空!\n");
        return ERROR;               // 空佇列
    }
    int i = Q.front;                // i指向隊頭元素下標
    while(i != Q.rear) {
        visit(Q.base[i]);
        i = (i+1) % MAXQSIZE;
    }
    printf("\n");
    return OK;
}// QueueTraverse

int main() {
    SqQueue Q;

    // 構造空佇列
    if(InitQueue(Q)) {
        // 插入元素
        for(int i=0; i<26; i++)
            EnQueue(Q, 'A' + i);
    }

    // 求佇列長
    printf("佇列的大小:%d\n", QueueLength(Q));

    // 返回佇列的隊頭元素
    QElemType e;
    if(GetHead(Q, e))
        QueueTraverse(Q, visit);

    // 刪除佇列的隊頭元素
    if(DeQueue(Q, e))
        QueueTraverse(Q, visit);

    // 判空
    if(QueueEmpty(Q))
        printf("佇列為空。\n");
    else
        printf("佇列非空。\n");

    // 置空
    ClearQueue(Q);
    QueueTraverse(Q, visit);

    // 判空
    if(QueueEmpty(Q))
        printf("佇列為空。\n");
    else
        printf("佇列非空。\n");

    // 銷燬
    DestroyQueue(Q);
    return 0;
}