跳转至

队列的 C 风格与面向对象实现

介绍链式队列、顺序队列、循环队列的 C++ 实现,使用内容标签页对比 C 风格与面向对象两种写法。

链式队列

链式队列基于单向链表,通过头结点统一管理空队列和出队操作,使用尾插法入队。

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

typedef struct qnode
{
    int data;
    struct qnode * next;
} qnode;

qnode * initqueue()
{
    qnode * queue = (qnode*)malloc(sizeof(qnode));
    queue->next = NULL;
    return queue;
}

qnode* enqueue(qnode * rear, int data)
{
    qnode * enElem = (qnode*)malloc(sizeof(qnode));
    enElem->data = data;
    enElem->next = NULL;
    // 使用尾插法,新元素成为队尾元素
    rear->next = enElem;
    rear = enElem;
    return rear;
}

qnode* dequeue(qnode * top, qnode * rear)
{
    if (top->next == NULL)
    {
        printf("\n队列为空");
        return rear;
    }
    qnode * p = top->next;
    printf("%d ", p->data);
    top->next = p->next;
    if (rear == p)
    {
        rear = top;
    }
    free(p);
    return rear;
}

void destroyqueue(qnode * queue)                        // 新增:释放链式队列所有节点
{
    qnode * p = queue;
    while (p != NULL)
    {
        qnode * tmp = p;
        p = p->next;
        free(tmp);
    }
}

int main()
{
    qnode * queue, *top, *rear;
    queue = top = rear = initqueue();  // 创建头结点
    // 入队,使用尾插法,同时队尾指针指向最后一个元素
    rear = enqueue(rear, 1);
    rear = enqueue(rear, 2);
    rear = enqueue(rear, 3);
    rear = enqueue(rear, 4);
    // 出队
    rear = dequeue(top, rear);
    rear = dequeue(top, rear);
    rear = dequeue(top, rear);
    rear = dequeue(top, rear);
    rear = dequeue(top, rear);
    destroyqueue(queue);                                 // 新增:释放内存
    return 0;
}

enqueue 采用尾插法,新结点接到队尾之后并将 rear 后移。dequeue 从头结点之后取出元素,如果出队后队列变空,将 rear 重置为头结点。destroyqueue 遍历链表逐个释放结点,防止内存泄漏。

顺序队列

顺序队列基于定长数组,通过取模运算实现循环利用存储空间。下面将函数式写法和面向对象写法并列展示。

#include <stdio.h>

#define max 5  // 顺序队列的空间大小

int enqueue(int *a, int front, int rear, int data)
{
    // 队列满判断:如果 rear+1 与 front 重合,表示队列已满
    if ((rear + 1) % max == front)
    {
        printf("空间已满");
        return rear;
    }
    a[rear % max] = data;
    rear++;
    return rear;
}

int dequeue(int *a, int front, int rear)
{
    // 队列空判断:如果 front == rear%max,表示队列为空
    if (front == rear % max)
    {
        printf("队列为空");
        return front;
    }
    printf("%d ", a[front]);
    front = (front + 1) % max;
    return front;
}

int main()
{
    int a[max];
    int front, rear;
    // 初始化队头和队尾指针,队列无元素时两者指向同一位置
    front = rear = 0;
    // 入队
    rear = enqueue(a, front, rear, 1);
    rear = enqueue(a, front, rear, 2);
    rear = enqueue(a, front, rear, 3);
    rear = enqueue(a, front, rear, 4);
    // 出队
    front = dequeue(a, front, rear);
    // 再入队
    rear = enqueue(a, front, rear, 5);
    // 再出队
    front = dequeue(a, front, rear);
    // 再入队
    rear = enqueue(a, front, rear, 6);
    // 再出队
    front = dequeue(a, front, rear);
    front = dequeue(a, front, rear);
    front = dequeue(a, front, rear);
    front = dequeue(a, front, rear);
    return 0;
}
#include <stdio.h>

#define max 50  // 顺序队列的空间大小

typedef int elemtype;

class queue
{
public:
    elemtype a[max];
    int front, rear;
    queue();

    int enqueue(elemtype data);
    int dequeue();
};

queue::queue()
{
    front = rear = 0;
}

int queue::enqueue(elemtype data)
{
    if ((rear + 1) % max == front)
    {
        printf("空间已满");
        return rear;
    }
    a[rear % max] = data;
    rear++;
    return rear;
}

int queue::dequeue()
{
    if (front == rear % max)
    {
        printf("队列为空");
        return front;
    }
    printf("%d ", a[front]);
    front = (front + 1) % max;
    return front;
}

int main()
{
    queue q = queue();
    q.enqueue(1);
    q.enqueue(2);
    q.enqueue(3);
    q.enqueue(4);
    q.dequeue();
    q.enqueue(5);
    q.dequeue();
    q.enqueue(6);
    q.dequeue();
    q.dequeue();
    q.dequeue();
    q.dequeue();
    return 0;
}

两种风格的核心逻辑一致:enqueuerear 作为计数累加,通过 rear % max 定位写入位置;dequeuefront 取模,保证循环读取出队元素。C 风格将 frontrear 作为函数参数显式传递,面向对象则封装为成员变量。

循环队列

循环队列使用动态分配内存,不依赖固定数组,队列长度可灵活调整。同样将 C 风格与面向对象写法并列展示。

注意原代码中两个文件均忘记释放动态分配的内存,这里补充了释放逻辑。

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

#define MAXQSIZE 100

typedef int qelemtype;
typedef int status;

typedef struct
{
    qelemtype * base;
    int front;
    int rear;
} sqqueue;

status initqueue(sqqueue &q)
{
    q.base = (qelemtype *)malloc(MAXQSIZE * sizeof(qelemtype));
    if (!q.base) exit(0);
    q.front = q.rear = 0;
    return 1;
}

void destroyqueue(sqqueue &q)                       // 新增:释放动态分配的存储空间
{
    free(q.base);
    q.base = NULL;
}

int queuelength(sqqueue q)
{
    return (q.rear - q.front + MAXQSIZE) % MAXQSIZE;
}

status enqueue(sqqueue &q, qelemtype e)
{
    if ((q.rear + 1) % MAXQSIZE == q.front) return 0;
    q.base[q.rear] = e;
    printf("入队元素:%d\n", e);
    q.rear = (q.rear + 1) % MAXQSIZE;
    return 1;
}

status dequeue(sqqueue &q, qelemtype &e)
{
    if (q.front == q.rear) return 0;
    e = q.base[q.front];
    printf("出队元素:%d\n", e);
    q.front = (q.front + 1) % MAXQSIZE;
    return 1;
}

int main()
{
    sqqueue q;
    int i;
    initqueue(q);
    enqueue(q, 1);
    enqueue(q, 2);
    enqueue(q, 3);
    enqueue(q, 4);
    enqueue(q, 5);
    dequeue(q, i);
    dequeue(q, i);
    dequeue(q, i);
    dequeue(q, i);
    dequeue(q, i);
    destroyqueue(q);                                 // 新增:释放内存
    return 0;
}
#include <stdio.h>
#include <stdlib.h>

#define MAXQSIZE 100

typedef int qelemtype;
typedef int status;

class sqqueue
{
public:
    qelemtype * base;
    int front;
    int rear;
    sqqueue();
    ~sqqueue();                                      // 新增:析构函数声明
    status initqueue();
    int length();
    status enqueue(qelemtype e);
    status dequeue(qelemtype &e);
};

sqqueue::sqqueue()
{
    base = (qelemtype *)malloc(MAXQSIZE * sizeof(qelemtype));
    if (!base) exit(0);
    front = rear = 0;
}

sqqueue::~sqqueue()                                  // 新增:析构函数释放内存
{
    free(base);
}

int sqqueue::length()
{
    return (rear - front + MAXQSIZE) % MAXQSIZE;
}

status sqqueue::enqueue(qelemtype e)
{
    if ((rear + 1) % MAXQSIZE == front) return 0;
    base[rear] = e;
    printf("入队元素:%d\n", e);
    rear = (rear + 1) % MAXQSIZE;
    return 1;
}

status sqqueue::dequeue(qelemtype &e)
{
    if (front == rear) return 0;
    e = base[front];
    printf("出队元素:%d\n", e);
    front = (front + 1) % MAXQSIZE;
    return 1;
}

int main()
{
    int i;
    sqqueue q = sqqueue();
    q.enqueue(1);
    q.enqueue(2);
    q.enqueue(3);
    q.enqueue(4);
    q.enqueue(5);
    q.dequeue(i);
    q.dequeue(i);
    q.dequeue(i);
    q.dequeue(i);
    q.dequeue(i);
    return 0;
}

C 风格通过 struct 聚合数据、独立函数操作队列,initqueuedestroyqueue 手动管理生命周期。面向对象将数据和操作封装为类,构造函数分配内存、析构函数自动释放。两者的 enqueuedequeue 都对 frontrear 做取模处理,队列长度公式 (rear - front + MAXQSIZE) % MAXQSIZE 可在任意状态下计算元素个数。