C/C++泛型编程实现数据结构之队列

C/C++泛型编程实现数据结构之队列

早在曾经一篇博文中,我曾介绍过顺序存储和链式存储的区别和好处,博文传送门:https://blog.csdn.net/qq_27180763/article/details/82683029

本章将讲诉:
1. 队列的逻辑结构刨析
2. 顺序存储结构下的循环队列
3. 链式存储结构下的循环链队列
4. C/C++泛型编程类模板实现队列

逻辑结构:

顺序队列的逻辑结构:

#define Max_Size = 100;
template <typename DataType>
struct Queue{
    DataType data[Max_Size];
    int front;
    int rear;
};

由于队列是一种先进先出的FIFO的线性表,所以我们在这里设置了队列的头front和队列的尾部rear;从而实现rear进入的元素可以在front处删除。下面来看链队列的逻辑结构。

链队列的逻辑结构:

struct QueueNode{
        DataType data;
        QueueNode* next;
    };
struct LinkQueue{
        QueueNode* front;
        QueueNode* rear;
    };
LinkQueue Q;

其中Queue_Node这个结构题代表了每个节点的类型,顺序存储中我们采用数组来实现这个队列空间,而在这里我们采用了链表来实现这个访问受限的线性表。

入队列和出队列

这里入队和出队操作要单独拿出来讲。
由于循环队列的入队和出队是循环意义上的入队和出队,为了充分利用数组空间,克服上溢,可将数组空间想象成一个环状空间,并称这个环状空间为循环队列。这种循环队列的出队和入队运算时,头尾指针仍然要加1,只不过当头尾指针指向数组上界Queue_Size-1时,如何按正常的操作进行+1运算,则数组就会产生溢出。因此需要判断+1后是否超过数组上界。
顺序队列入队列和出队列实现:

void En_Queue(DataType info) {
        if(!Queue_full()){
            data[rear] = info;
            rear = (rear + 1) % QueueSize;
        }
        else {
            cout << "the Queue is overflow!" << endl;
        }
    }

    DataType De_Queue() {
        if (!Empty_Queue()){
            DataType x = data[front];
            front = (front + 1) % QueueSize;
            return x;
        }
        else {
            cout << "the Queue is Empty!" << endl;
            exit(0);
        }
    }

链队列入队和出队实现:

void EnQueue(DataType x) {
        QueueNode* p = (QueueNode*)malloc(sizeof(QueueNode));
        p->data = x;
        p->next = NULL;
        Q->rear->next= p;
        Q->rear = p;
    }
DataType DeQueue() {
        QueueNode* p;
        if (QueueEmpty()) {
            cout << "the Queue is empty!" << endl;
            exit(0);
        }
        else {
            p = Q->front;
            Q->front = Q->front->next;
            free(p);
            return Q->front->data;
        }
    }

以上即为重点部分,现在来看完整代码实现:

顺序存储结构下的队列:

template <typename DataType>
class Queue {
private:
    const int QueueSize = 100;

protected:
    DataType data = new DataType[QueueSize];
    int front, rear;

public:
    Queue() {
        front = rear = 0;
    }

    void En_Queue(DataType info) {
        if(!Queue_full()){
            data[rear] = info;
            rear = (rear + 1) % QueueSize;
        }
        else {
            cout << "the Queue is overflow!" << endl;
        }
    }

    DataType De_Queue() {
        if (!Empty_Queue()){
            DataType x = data[front];
            front = (front + 1) % QueueSize;
            return x;
        }
        else {
            cout << "the Queue is Empty!" << endl;
            exit(0);
        }
    }

    bool Empty_Queue() {
        return rear == front;
    }

    bool Queue_full() {
        return (rear + 1) % QueueSize == front;
    }
};

链式存储结构下的队列:

template <typename DataType>
class Link_Queue{
private:
    struct QueueNode{
        DataType data;
        QueueNode* next;
    };
protected:
    struct LinkQueue{
        QueueNode* front;
        QueueNode* rear;
    };

private:
    LinkQueue* Q;
public:
    Link_Queue() {
        Q->front = (QueueNode*)malloc(sizeof(QueueNode));
        Q->rear = Q->front;
        Q->rear->next = NULL;
    }

    bool QueueEmpty() {
        return Q->rear == Q->front;
    }

    void EnQueue(DataType x) {
        QueueNode* p = (QueueNode*)malloc(sizeof(QueueNode));
        p->data = x;
        p->next = NULL;
        Q->rear->next= p;
        Q->rear = p;
    }

    DataType GetFront() {
        if (QueueEmpty()) {
            cout << "the Queue is Empty!" << endl;
            exit(0);
        }
        else {
            return Q->front->next->data;
        }
    }

    DataType DeQueue() {
        QueueNode* p;
        if (QueueEmpty()) {
            cout << "the Queue is empty!" << endl;
            exit(0);
        }
        else {
            p = Q->front;
            Q->front = Q->front->next;
            free(p);
            return Q->front->data;
        }
    }
};

猜你喜欢

转载自blog.csdn.net/qq_27180763/article/details/82731987