数据结构学习笔记-06 队列

280 阅读5分钟

队列-顺序结构

队列假溢出,循环顺序牺牲一个空间 (Q.rear+1)%MAXSIZE == Q.front 判断是否满了

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

#include "math.h"
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */

/**
 队列的特点就是先进先出。在一个连续的空间中,为了避免队列假溢出(出比进快),我们始终保留一个空空间用来作为标记,防止假溢出
 */

//定义状态
typedef int STATUS;
//定义数据类型
typedef int ELEMENT;

/*循环队列的顺序结构*/
typedef struct Queue {
    //分配一个连续的空间,将用于队列元素的储存
    ELEMENT data[MAXSIZE];
    int front;//队列头
    int rear;//对列尾
}Queue;


//初始化
STATUS Queue_init(Queue *Q) {
    //首尾相等
    Q->front = Q->rear = 0;
    return OK;
}

//队列清空
STATUS Queue_clear(Queue *Q) {
    //同样也是清空,至于已经有的元素不需要释放,因为数组空间已开始就已经分配20个
    Q->front = Q->rear = 0;
    return OK;
}

//队列是否为空
STATUS Queue_isEmpty(Queue Q) {
    if (Q.front == Q.rear) {//只要满足front == rear,就是空了,不需要满足front == rear == 0,因为front 可以不为0
        return TRUE;
    } else {
        return FALSE;
    }
}

//队列是否满
STATUS Queue_isFull(Queue Q) {
    if ((Q.rear+1)%MAXSIZE == Q.front) {
        return TRUE;
    } else {
        return FALSE;
    }
}

//元素的个数,也就是当前队列的长度
STATUS Queue_lenght(Queue Q) {
    //因为是队列,在一个连续的空间 rear的数值可能比front的数值小会得到负数,所以要取模
    return (Q.rear - Q.front + MAXSIZE ) % MAXSIZE;
}

//获取对头元素
STATUS Queue_top(Queue Q,ELEMENT *e) {
    if (Queue_isEmpty(Q)) {
        return ERROR;
    }
    //把对头元素赋值给e
    *e = Q.data[Q.front];
    return OK;
}

//队列进入
STATUS Queue_en(Queue *Q,ELEMENT e) {
    //队列已满
    if (Queue_isFull(*Q)) {
        return ERROR;
    }
    
    //将元素e赋值给队尾
    Q->data[Q->rear] = e;
    //rear指针向后移动一位,若到最后则转到数组头部;
    Q->rear = (Q->rear + 1)%MAXSIZE;
    return OK;
}

//队列出队
STATUS Queue_de(Queue *Q,ELEMENT *e) {
    //队列已满
    if (Queue_isFull(*Q)) {
        return ERROR;
    }
    
    //保存出队元素赋值给e
    *e = Q->data[Q->front];
    //front 指针向后移动一位,若到最后则转到数组头部
    Q->front = (Q->front + 1)%MAXSIZE;
    return OK;
}

//队列遍历
STATUS Queue_traverse(Queue Q) {
    int i = Q.front;
    while ((i+Q.front) != Q.rear) {
        printf("%d   ",Q.data[i]);
        i = (i+1)%MAXSIZE;
    }
    printf("\n");
    return OK;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    
    STATUS j;
    int i=0;
    ELEMENT d;
    Queue Q;
    Queue_init(&Q);
    printf("初始化队列后,队列空否?%u(1:空 0:否)\n",Queue_isEmpty(Q));
    
    printf("入队:\n");
    while (i < 10) {
        Queue_en(&Q, i);
        i++;
    }
    Queue_traverse(Q);
    printf("队列长度为: %d\n",Queue_lenght(Q));
    printf("现在队列空否?%u(1:空 0:否)\n",Queue_isEmpty(Q));
    printf("出队:\n");
    
    //出队
    Queue_de(&Q, &d);
    printf("出队的元素:%d\n",d);
    Queue_traverse(Q);
    
    //获取队头
    j = Queue_top(Q,&d);
    if(j)
        printf("现在队头元素为: %d\n",d);
    Queue_clear(&Q);
    printf("清空队列后, 队列空否?%u(1:空 0:否)\n",Queue_isEmpty(Q));
    
    return 0;
}

栈-链表结构

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

#include "math.h"
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */


typedef int STATUS;
typedef int ELEMENT;

/*节点结构*/
typedef struct Node {
    ELEMENT data;
    struct Node *next;
}Node, *LinkNodePtr;


/*队列的链表结构*/
typedef struct QueueNode {
    /* 队头、队尾指针 */
    LinkNodePtr front;
    LinkNodePtr rear;
}QueueLink;

//初始化
STATUS Queue_init(QueueLink *Q) {
    //1. 头/尾指针都指向新生成的结点
    Q->front = Q->rear = (LinkNodePtr)malloc(sizeof(Node));
    
    //2.判断是否创建新结点成功与否
    if (Q->front == NULL || Q->rear == NULL) {
        return ERROR;
    }
    
    //3.头结点的指针域置空,当然也可以是Q->rear->data = NULL;因为两个指针指向同一个区域
    Q->front->next = NULL;
    
    return OK;
}


//队列销毁
STATUS Queue_destory(QueueLink *Q) {
    //遍历整个队列,销毁队列每个节点
    while (Q->front) {
        Q->rear = Q->front->next;
        free(Q->front);
        Q->front = Q->rear;
    }
    return OK;
}

//队列置空
STATUS Queue_clear(QueueLink *Q) {
    //1.临时变量
    LinkNodePtr p,q;
    //2.先将rear 指向 front
    Q->rear = Q->front;
    //3.用p 拿到front->next
    p = Q->front->next;
    //4.将Q->front->next置空
    Q->front->next = NULL;
    
    //将p中的数据释放
    while (p) {
        q = p;
        p = p->next;
        free(q);
    }
    return OK;
}

//为空判断
STATUS Queue_isEmpty(QueueLink Q) {
    if (Q.rear == Q.front) {
        return TRUE;
    } else {
        return FALSE;
    }
}

//长度
STATUS Queue_lenght(QueueLink Q) {
    int i = 0;
    LinkNodePtr temp = Q.front;
    while (temp != Q.rear) {
        temp = temp->next;
        i ++;
    }
    return i;
}

//入队
STATUS Queue_en(QueueLink *Q,ELEMENT e) {
    //新增入队节点
    LinkNodePtr p = malloc(sizeof(Node));
    if (p == NULL) {
        return ERROR;
    }
    //节点赋值
    p->data = e;
    p->next = NULL;
    
    //插入队尾
    Q->rear->next = p;
    //修改队尾指针
    Q->rear = p;
    
    return OK;
}

//出列
STATUS Queue_de(QueueLink *Q,ELEMENT *e) {
    //是否为空
    if (Queue_isEmpty(*Q)) {
        return ERROR;
    }
    //返回出对列元素
    *e = Q->front->data;
    
    //新建临时结点
    LinkNodePtr temp;
    //将要删除的队头结点暂时存储在temp
    temp = Q->front;
    //将原队列头结点的后继p->next 赋值给头结点后继
    Q->front = Q->front->next;
    
    //若队头就是队尾,则删除后将rear指向头结点.
    if (Q->front == Q->rear) {
        Q->rear = Q->front;
    }
    
    //释放节点
    free(temp);
    
    return OK;
}

//头元素
STATUS Queue_top(QueueLink Q,ELEMENT *e) {
    if (Queue_isEmpty(Q)) {
        return ERROR;
    }
    *e = Q.front->next->data;
    
    return OK;
}


//遍历
STATUS Queue_traverse(QueueLink Q) {
    if (Queue_isEmpty(Q)) {
        return ERROR;
    }
    LinkNodePtr temp;
    temp = Q.front->next;
    while (temp) {
        printf("%d ",temp->data);
        temp = temp->next;
    }
    
    printf("\n");
    return OK;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("链队列的表示与操作!\n");
    
    STATUS iStatus;
    ELEMENT d;
    QueueLink q;
    
    //1.初始化队列q
    iStatus = Queue_init(&q);
    
    //2. 判断是否创建成
    if (iStatus) {
        printf("成功地构造了一个空队列\n");
    }
    
    //3.判断队列是否为空
    printf("是否为空队列?%d (1:是 0:否)\n",Queue_isEmpty(q));
    
    //4.获取队列的长度
    printf("队列的长度为%d\n",Queue_lenght(q));
    
    //5.插入元素到队列中
    Queue_en(&q, -3);
    Queue_en(&q, 6);
    Queue_en(&q, 12);
    
    printf("队列的长度为%d\n",Queue_lenght(q));
    printf("是否为空队列?%d (1:是 0:否)\n",Queue_isEmpty(q));
    
    //6.遍历队列
    printf("队列中的元素如下:\n");
    Queue_traverse(q);

    //7.获取队列头元素
    iStatus = Queue_top(q, &d);
    if (iStatus == OK) {
        printf("队头元素是:%d\n",d);
    }
    
    //8.删除队头元素
    iStatus = Queue_de(&q, &d);
    if (iStatus == OK) {
        printf("删除了的队头元素为:%d\n",d);
    }
    
    //9.获取队头元素
    iStatus = Queue_top(q, &d);
    if (iStatus == OK) {
        printf("新的队头元素为:%d\n",d);
    }
    
    //10.清空队列
    Queue_clear(&q);
    
    //11.销毁队列
    Queue_destory(&q);
    return 0;
}