仅设尾指针的循环队列问题

仅设尾指针的循环队列问题 不知道哪里错了 但好像思路没什么问题

输入一个整数序列:a
1

,a
2

,a
3

,…,a
n

,进行入队或出队操作。用带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意:不设头指针),试编写相应的置空队、判队空、入队和出队等算法,并实现以下任务:对输入的a
i

,当a
i

0时,将a
i

入队;当a
i

=0时,队头元素出队,若出队时队空则发生下溢“UNDERFLOW”,一旦发生下溢,则停止处理。

输入格式:
测试数据有多组,处理到文件尾。每组测试数据首先输入正整数n(n≤30),再输入n个整数。

输出格式:
对于每组测试,若处理过程中未发生下溢,则依次输出队列中当前还存在的元素(每两个数据之间留一个空格),否则输出“UNDERFLOW”表示下溢(若最终队列为空,也输出“UNDERFLOW”)。引号不必输出。

输入样例:
11 1 2 3 4 5 6 0 0 7 8 0
7 1 2 3 0 0 0 0
输出样例:
4 5 6 7 8
UNDERFLOW


```c++
#include<iostream>
using namespace std;
typedef int elemtype;
struct QNode{
    elemtype data;
    QNode *next;
};
struct LinkQueue{
    QNode *rear;
    void init();
    void inqueue(elemtype e);
    void outqueue();
    bool empty();
    void getFront();
};
void LinkQueue::init(){
    rear=new QNode;
    rear->next=rear;
}
void LinkQueue::inqueue(elemtype e){
    QNode *p=new QNode;
    p->data=e;
    p->next=rear->next;
    rear->next=p;
    rear=p;
}
void LinkQueue::outqueue(){
    if(rear==rear->next) return;
    QNode *p=rear->next->next;
    rear->next->next=p->next;
    if(p==rear){
        rear=rear->next;
    }
    delete p;
}
bool LinkQueue::empty(){
    return rear=rear->next;
}
void solve(int n,int a[]){
    LinkQueue que;
    que.init();
    for(int i=0;i<n;i++){
        if(a[i]>0){
            que.inqueue(a[i]);
        }else if(que.empty()!=true&&a[i]==0){
            que.outqueue();
        }
    }
    if(que.empty()==true){
        cout<<"UNDERFLOW"<<endl;
        return;
    }else{
        int cnt=0;
        cout<<1111;
        for(int i=0;i<n;i++){
            cnt++;
            if(cnt!=1){
                cout<<" ";
            }
            cout<<a[i];
        }
    }
}
int main(){
    int n;
    while(cin>>n){
        int a[n];
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        solve(n,a);
    }
}


![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/941821786286176.png "#left")

#include<stdio.h>
#include<stdlib.h>

/**
 * 链式循环队列结点结构体定义
 */
typedef struct CLNode {
    /**
     * 结点数据域,存储结点的数据值
     */
    int data;
    /**
     * 结点指针域,存储当前结点的后继结点的地址
     */
    struct CLNode *next;
    /**
     * 结点指针域,即队尾指针,指向队尾结点,存储队列尾结点的地址
     */
    struct CLNode *rear;
} CLNode;

/**
 * 初始化队列
 * @param queue 未初始化的队列
 */
void init(CLNode **queue) {
    // 创建头结点,queue 即为链式队列的头结点,为头结点分配空间
    *queue = (CLNode *) malloc(sizeof(CLNode));
    // 将链式队列头结点的 next 和 rear 指针都指向自身,因为是循环的,并且是空队列
    (*queue)->next = *queue;
    (*queue)->rear = *queue;
}

/**
 * 将元素入队
 * @param rear 循环链式队列的尾指针,指向链式队列的尾结点
 * @param ele 待入队的元素
 */
void enQueue(CLNode **rear, int ele) {
    // 1.创建新结点
    // 1.1 为新结点分配存储空间
    CLNode *newNode = (CLNode *) malloc(sizeof(CLNode));
    // 1.2 为新结点指定数据域
    newNode->data = ele;
    // 1.2 为新结点指定指针域,新结点的指针域初始都指向 null
    newNode->next = NULL;

    // 2.将新结点入队
    // 2.1 将新结点的 next 指针指向原队尾结点的后继结点。即将新结点与原队列头结点连接起来
    // 实际上 rear 指向队尾结点;rear->next 由于是循环链式队列,所以指向的是头结点
    newNode->next = (*rear)->next;
    // 2.2 将原队尾结点的 next 指针指向新结点。即将原队列尾与新结点连接起来,才构成一个循环链
    (*rear)->next = newNode;
    // 2.3 将队尾指针指向新结点,即此时新结点成为了队列的队尾结点
    (*rear) = newNode;
}

/**
 * 将元素出队
 * @param rear 循环链式队列的尾指针,指向链式队列的尾结点
 * @param ele 保存出队的元素
 * @return 如果出队成功则返回 1,否则返回 0 表示出队失败
 */
int deQueue(CLNode **rear, int *ele) {
    // 0.参数校验,如果是空队列,则返回 0 表示不能出队。注意循环链表的判空条件
    if ((*rear)->next == *rear) {
        return 0;
    }

    // 其中 rear 指向队尾结点;rear->next 由于是循环链式队列,所以指向的是头结点
    // 局部变量,头结点
    CLNode *headNode = (*rear)->next;
    // 局部变量,开始结点。而头结点的后继结点就是开始结点
    CLNode *startNode = headNode->next;

    // 1.用 ele 保存开始结点的数据域,因为队列是从队头出队,所以就是出队开始结点
    *ele = startNode->data;
    // 2.删除队头结点。即将队头结点的 next 指针指向原开始结点的后继结点
    headNode->next = startNode->next;
    // 如果元素出队后队列为空,则需要特殊处理
    if (startNode==*rear){
        *rear=(*rear)->next;
    }
    // 3.释放被删结点的空间
    free(startNode);
    // 4.返回 1 表示出队成功
    return 1;
}

/**
 * 打印循环链式队列
 * @param queue 队列
 */
void print(CLNode *queue) {
    printf("[");
    CLNode *node = queue->next;
    while (node != queue) {
        printf("%d", node->data);
        if (node->next != queue) {
            printf(", ");
        }
        node = node->next;
    }
    printf("]\n");
}

int main() {
    // 声明队列
    CLNode *queue;

    // 初始化队列
    printf("\n初始化队列:\n");
    init(&queue);
    print(queue);

    // 将元素入队
    printf("\n将元素入队:\n");
    // 这里传入的参数可能有点难以理解,因为 enQueue 方法的第一个参数是双指针,所以传入的是指针变量的地址
    // queue是一个指针变量;&queue就是指针变量的地址,而queue->rear是为了获取队列的队尾指针,将队尾指针作为参数传入而非在函数内获取,是为了更直观了解函数的功能
    enQueue(&(queue->rear), 11);
    print(queue);
    enQueue(&(queue->rear), 22);
    print(queue);
    enQueue(&(queue->rear), 33);
    print(queue);
    enQueue(&(queue->rear), 44);
    print(queue);
    enQueue(&(queue->rear), 55);
    print(queue);
    enQueue(&(queue->rear), 66);
    print(queue);

    // 将元素出队
    printf("\n将元素出队:\n");
    int ele;
    deQueue(&(queue->rear), &ele);
    printf("出队元素:%d\n", ele);
    print(queue);
    deQueue(&(queue->rear), &ele);
    printf("出队元素:%d\n", ele);
    print(queue);
    deQueue(&(queue->rear), &ele);
    printf("出队元素:%d\n", ele);
    print(queue);
}