数据结构之队列(Queue)

关于队列

队列,顾名思义,也就是一条队伍,进入队伍的时候,只能从队尾排队,离开队伍的时候,只能从队首离开。队列也有数组实现和链式实现。

队列的数组实现

用一般数组实现队列的时候,入队,则在队尾插入一个元素,出队,则将队首的元素出队。那么,由于数组的长度是固定的,入队只能从队尾入队,因此经常性的出队会使得队首越来越靠近队尾,队首前面的数组空间不能被利用,导致大量的数组空间被浪费,显然这不是优秀的数据结构。
因此习惯上用循环数组实现数组实现的队列。
判断队列为空和队列未满可以有两种策略。
第一种:在队列的数据结构增加计数器counter属性
第二种:将数组中一块空间禁用。
在第一种方法下:队列的数组实现基本操作如下:

#include<iostream>
using namespace std;
#define SIZE 10
typedef struct QueueNode
{//用循环数组实现队列,用计数器counter判断队空和队满
    int arr[SIZE];
    int front;
    int rear; 
    int counter;
}*ArrayQueue;
ArrayQueue CreateQueue()
{
    QueueNode* Node = (QueueNode*)malloc(sizeof(QueueNode));
    Node->front = 0;
    Node->rear = -1;
    Node->counter = 0;
    return Node;
}
bool IsFull(ArrayQueue q)
{
    return (q->counter == SIZE);
}
bool IsEmpty(ArrayQueue q)
{
    return (q->counter = 0);
}
void EnQueue(ArrayQueue q, int val)
{
    if (!IsFull(q))
    {
        q->rear = (q->rear + 1) % SIZE;
        q->arr[q->rear] = val;
        q->counter++;
    }
}
void DeQueue(ArrayQueue q)
{
    if (!IsEmpty(q))
    {
        q->front = (q->front + 1)  % SIZE;
        q->counter--;
    }
}
int Front(ArrayQueue q)
{
    int val = -1;
    if (!IsEmpty(q))
    {
        val = q->arr[q->front];
    }
    return val;
}

在第二种方法下,队列的数组实现基本操作如下:

#include<iostream>
using namespace std;
#define SIZE 10
typedef struct QueueNode2
{
    int arr[SIZE];
    int front;
    int rear;
}*ArrayQueue2;
ArrayQueue2 CreateQueue2()
{
    QueueNode2* Node = (QueueNode2*)malloc(sizeof(QueueNode));
    Node->front = 0;
    Node->rear = -1;
    return Node;
}
bool IsFull2(ArrayQueue2 q)
{
    return ((q->rear+2) % SIZE ==q->front);
}
bool IsEmpty2(ArrayQueue2 q)
{
    return ((q->front+1) % SIZE == q->rear);
}
void EnQueue2(ArrayQueue2 q, int val)
{
    if (!IsFull2(q))
    {
        q->rear = (q->rear + 1) % SIZE;
        q->arr[q->rear] = val;
    }
}
void DeQueue2(ArrayQueue2 q)
{
    if (!IsEmpty2(q))
    {
        q->front = (q->front + 1) % SIZE;
    }
}
int Front2(ArrayQueue2 q)
{
    int val = -1;
    if (!IsEmpty2(q))
    {
        val = q->arr[q->front];
    }
    return val;
}

队列的链式实现

链式实现的时候,永远不用忘记,链式数据结构习惯上有一个头结点,这个头结点的数据域部分一般不用,也可以用于存储重要的信息,而头结点后面那个元素才是第一个元素。

#include<iostream>
using namespace std;
typedef struct LinkedQueueNode
{//定义结点数据结构,用于串联结点
    int value;
    struct LinkedQueueNode* next;
};
typedef struct LinkedQueue
{//定义队列数据结构,用于指向链式队列中的队首和队尾
    LinkedQueueNode* front;
    LinkedQueueNode* rear;
};
bool IsEmpty(LinkedQueue* q)
{
    return (q->front == q->rear);
}
LinkedQueueNode* CreateNode()
{
    LinkedQueueNode* Node = (LinkedQueueNode*)malloc(sizeof(LinkedQueueNode));
    if (Node != NULL)
    {
        Node->value = 0;
        Node->next = NULL;
    }
    else
    {
        cout << "Node applys for memory failed " << endl;
    }
    return Node;
}
LinkedQueue* CreateQueue()
{
    LinkedQueue* Queue = (LinkedQueue*)malloc(sizeof(LinkedQueue));
    LinkedQueueNode* Node = CreateNode();
    if (Queue != NULL && Node != NULL)
    {
        Queue->front = Node;
        Queue->rear = Node;
    }
    else 
    {
        cout << "Queue applys for memory failed" << endl;
    }
    return Queue;
}
void EnQueue(LinkedQueue* q,int val)
{
    LinkedQueueNode* Node = CreateNode();
    if (Node != NULL)
    {
        Node->value = val;
        q->rear->next = Node; //将队尾的下一个元素指向新元素
        q->rear = q->rear->next;//将新元素的地址赋值给队尾  
    }
    else
    {
        cout << "apply for memory failed" << endl;
    }
}
bool UpdateNode(LinkedQueue* q,int preVal,int aftVal)
{
    bool flag = false;
    for (LinkedQueueNode* Node  = q->front->next;q->front != q->rear; Node = Node->next)
    {
        if (Node->value==preVal)
        {
            Node->value = aftVal;
            flag = true;
            return flag;
        }
    }
    return flag;
}
void DeQueue(LinkedQueue* q)
{
    if (!IsEmpty(q))
    {
        LinkedQueueNode* Node = q->front->next;//Node是头结点的下一个元素,即第一个元素
        q->front->next = Node->next;//使头结点的下一个元素指向第二个元素
        if (q->rear == Node)
        {//如果第一个元素是队尾,就是队列除了头结点只有一个元素
            q->rear = q->front;//使队尾指向对头,这个操作由判空条件决定的
        }
        free(Node);
    }
    else
    {
        cout << "LinkedQueue is empty" << endl;
    }
}
int Front(LinkedQueue* q)
{
    if (!IsEmpty(q))
    {
        return (q->front->next->value);
    }
    else
    {
        cout << "LinkedQueue is empty" << endl;
        return -1;
    }
}
void main()
{
    LinkedQueue* Queue = CreateQueue();
    EnQueue(Queue, 100);
    EnQueue(Queue, 200);
    EnQueue(Queue, 300);
    EnQueue(Queue, 400);
    EnQueue(Queue, 500);
    UpdateNode(Queue,300,1000);
    cout << "Front : " << Front(Queue)<< endl;
    DeQueue(Queue);
    cout << "After Dequeue Front is : " << Front(Queue) << endl;
    DeQueue(Queue);
    cout << "After Dequeue Front is : " << Front(Queue) << endl;
    DeQueue(Queue);
    cout << "After Dequeue Front is : " << Front(Queue) << endl;
    DeQueue(Queue);
    cout << "After Dequeue Front is : " << Front(Queue) << endl;
    DeQueue(Queue);
    cout << "After Dequeue Front is : " << Front(Queue) << endl;
}

猜你喜欢

转载自blog.csdn.net/qq_31729917/article/details/81055938
今日推荐