数据结构 | C语言实现队列的顺序和链式结构

队列的顺序结构实现

队列遵循的是先进先出的规则,我们使用一个定长数组和队头队尾两个指针来完成这个结构。
顺序结构使用结构体来表示,如下:

#define maxsize 100

typedef struct {
	int data[maxsize]; // 定长数组存放队列元素
	int front, rear; // 队头队尾指针
}Queue;

我这里实现的队列,front指针是一个队头结点,无意义,front+1所在位置才是队伍第一个元素,有点类似链表的头结点~
这里需要明确几个操作状态:

  1. 初始化:front = rear = 0;
  2. 进队:队不满,data[ ++ rear] = value;
  3. 出队:队非空,data[++front] = value,然后返回元素;

循环队列可以保证充分地利用数组空间。我们使用+1取余的方式来循环 front rear指针。

  1. front ++ -> front = (front + 1) % maxsize
  2. rear ++ -> rear = (rear + 1 ) % maxsize
  3. 长度为 (rear - front ) % maxsize

实现代码如下:

#include 
#include 
#include 

#define MAXSIZE 200
#define ERROR -1

typedef struct QNode* Queue;
typedef struct QNode QNode;

struct QNode{
    int data[MAXSIZE];
    int rear;  // rear所在位置就是刚入队元素的位置
    int front; // front的位置表示队头
    // 当 rear + 1 % MAXSIZE == front时,队满;
    // 当 rear == front 时,队空
    // 当删除时,front 向前移动一个位置;
    // 当处于边界的时候,可以考虑 + 1 % maxsize 实现循环移动指针的效果。
};

Queue initialQueue(){
    Queue Q = (Queue)malloc(sizeof(QNode));
    Q->rear=Q->front=0;
    return Q;
}

bool addQ(Queue Q,int item){
    /*添加元素的方法是:先移动rear指针,然后在rear所指的位置记录数据*/
    if(Q->rear + 1 % MAXSIZE == Q->front){
        printf("The queue is full \n");
        return false;
    }
    Q->rear = (Q->rear + 1)% MAXSIZE;
    Q->data[Q->rear] = item;
    return true;
}

int deleteQ(Queue Q){
    if(Q->front == Q->rear){
        printf("The queue is empty \n");
        return ERROR;
    }
    Q->front = (Q->front + 1)  % MAXSIZE;
    return Q->data[Q->front];
}

void printQueue(Queue Q){
    if(Q->front == Q->rear)
        printf("\n");

    int front = Q->front;
    int rear = Q->rear;
    while(front != rear){
        printf("%d -> ", Q->data[front + 1]);
        front = (front + 1) % MAXSIZE;
    }
    printf("\n");
}

int main()
{
    Queue Q = initialQueue();
    addQ(Q, 1);
    addQ(Q, 2);
    addQ(Q, 3);
    printQueue(Q);
    deleteQ(Q);
    deleteQ(Q);
    printQueue(Q);
    return 0;
}

队列的链式存储

队列的链式存储不需要实现上述类似的循环队列,因为不存在队列满的情况。
我们同样使用一个带有头指针和尾指针的结构体来实现队列。
我这里实现的头指针是链表的头结点,起到辅助编程的作用,第二个结点存储的元素才是队列的第一个元素。
尾指针则是指向链表最后一个结点的地址。

#include 
#include 

#define ERROR -1

typedef struct QNode QNode;

struct QNode{
    int val;
    QNode* next;
};

struct LinkQueue{
    QNode *rear;  // 队头结点
    QNode *front; // 队尾结点
};

typedef struct LinkQueue *Queue;
typedef struct LinkQueue LinkQueue;

Queue initialQueue(){
    Queue Q = (Queue)malloc(sizeof(LinkQueue));
    Q->rear = NULL;
    Q->front = (QNode*)malloc(sizeof(QNode));
    Q->front->val=-1;  // make no sense.
    Q->front->next=Q->rear;
    return Q;
}

int AddQ(Queue Q, int val){
    QNode* qnode = (QNode*)malloc(sizeof(QNode));
    qnode->val = val;
    qnode->next=NULL;
    if(Q->rear == NULL){
        Q->rear = qnode;
        Q->front->next=qnode;
    }
    else{
        // printf("%d", Q->front->next->val);
        Q->rear->next = qnode;
        Q->rear = Q->rear->next;
    }
}


int deleteQ(Queue Q){
    if(Q->front->next == NULL){
        printf("The queue is empty!\n");
        return ERROR;
    }
    int val = 0;
    QNode* node = Q->front->next;
    val = node->val;
    if(node == Q->rear){
        // 只剩下一个结点
        free(node);
        Q->rear = Q->front->next = NULL;
    }
    else{
        Q->front->next = node->next;
        free(node);
    }
    return val;
}

void printQueue(Queue Q){
    if(Q->front->next==NULL){
        printf("print: queue is empty.\n");
        return;
    }
    QNode* qnode = Q->front->next;
    while(qnode){
        printf("%d ->", qnode->val);
        qnode = qnode->next;
    }
    printf("\n");
}


int main()
{
    Queue Q = initialQueue();
    AddQ(Q, 1);
    AddQ(Q, 2);
    AddQ(Q, 4);
    AddQ(Q, 5);
    printQueue(Q);
    deleteQ(Q);
    deleteQ(Q);
    printQueue(Q);
    return 0;
}

以上代码仅经过简单的测试,如果存在问题,欢迎留言指教,谢谢!

你可能感兴趣的:(DataStructure,C,DataStructure)