学科分类
目录
数据结构

顺序队列的实现

使用顺序表实现的队列称作顺序队列。顺序队列的实现和顺序表的实现相似,只是在顺序队列中只允许在一端进行插入,在另一端进行删除。定义两个变量front与rear分别标识队头与队尾,当删除队头元素时,front后移到下一个位置;当插入新元素时,在rear指示的位置插入,插入后,rear向后移动指向下一个存储位置。假设向图1中的队列插入新元素100:

图1 新元素100入队

首先将100插入到rear指示的位置,然后将rear向后移动。插入完成后的队列如图2所示。

图2 插入新元素100后

如图2所示,在rear位置插入新的元素后,rear向后移动;当再有新的元素入队时,还是插入到rear指示的位置,直到队列已满。假如顺序队列的大小为MAXSIZE,则当队尾指针指向MAXSIZE-1位置时(rear=MAXSIZE-1),队列就满了。

同样,当有元素出队时,front指针要向后移动,指向新的队头元素,其过程如图3所示。

图3 元素出队

当队列中元素全部出队时,front与rear指向同一块内存,即front=rear,这也是判断队列是否为空的条件。下面我们来实现一个具备以下功能的简单顺序队列:

● 创建一个空队列。

● 获取队列大小。

● 判断队列是否为空。

● 入队、出队。

● 获取队头元素。

● 清空、销毁队列。

并且完成此队列的测试,具体代码如例1所示。

例1

SeqQueue.h //头文件

 1    #ifndef _SQQUEUE_H
 2    #define _SQQUEUE_H
 3    
 4    #define MAXSIZE 50
 5    typedef struct Queue* SeqQueue;
 6    struct Queue
 7    {
 8        int front;                             // 队头
 9        int rear;                             // 队尾
 10        int data[MAXSIZE];                     // 数据
 11    };
 12    
 13    SeqQueue Create();                         // 初始化操作,建立一个空队列Sq
 14    int getLength(SeqQueue Sq);             // 返回队列Sq的元素个数(长度)
 15    int IsEmpty(SeqQueue Sq);                 // 判断队列是否为空
 16    void Insert(SeqQueue Sq, int val);        // 入队
 17    int Del(SeqQueue Sq);                    // 出队
 18    int GetHead(SeqQueue Sq);                // 获取队头元素
 19    void Clear(SeqQueue Sq);                // 将队列Sq清空
 20    void Destory(SeqQueue Sq);                 //销毁队列
 21    
 22    #endif    //_SQQUEUE_H

SeqQueue.c //函数实现文件

 23    #include "SeqQueue.h"
 24    #include <string.h>
 25    #include <stdio.h>
 26    #include <stdlib.h>
 27    
 28    SeqQueue Create()
 29    {
 30        SeqQueue Sq = (SeqQueue)malloc(sizeof(struct Queue)); //分配空间
 31        Sq->front = Sq->rear = -1;
 32        memset(Sq->data, 0, MAXSIZE*sizeof(int));
 33        return Sq;
 34    }
 35    
 36    int getLength(SeqQueue Sq)
 37    {
 38        return Sq->rear - Sq->front;             //队列长度是队头队尾之差
 39    }
 40    
 41    int IsEmpty(SeqQueue Sq)
 42    {
 43        if (Sq->front = Sq->rear)                //判断队列是否为空的条件
 44        {
 45            return 1;
 46        }
 47        return 0;
 48    }
 49    
 50    // 数组前边是队头, 后边是队尾
 51    void Insert(SeqQueue Sq, int val)
 52    {
 53        // 队列是否已满
 54        if (Sq->rear == MAXSIZE - 1)
 55        {
 56            printf("队列已满,无法再插入元素!\n");
 57            return;
 58        }
 59        //如果是空队列
 60        if (Sq->front == Sq->rear) 
 61        {
 62            Sq->front = Sq->rear = 0; 
 63            Sq->data[Sq->rear] = val;
 64            Sq->rear++;
 65        }
 66        else
 67        {
 68            Sq->data[Sq->rear] = val;             //保存数据
 69            Sq->rear++;
 70        }
 71    }
 72    
 73    int Del(SeqQueue Sq)
 74    {
 75        // 空队列
 76        if (Sq->front == Sq->rear)                 //队列为空的条件
 77        {
 78            printf("队列为空,无元素可弹!\n");
 79            return 10000; //返回错误标志
 80        }
 81        int temp = Sq->data[Sq->front];
 82        Sq->front++;                             //删除队头元素后,front向后移动
 83        return temp;
 84    }
 85    
 86    int GetHead(SeqQueue Sq)
 87    {
 88        // 空队列
 89        if (Sq->front == Sq->rear)
 90        {
 91            printf("队列为空,无元素可取!\n");
 92            return 10000;
 93        }
 94        // 获取元素
 95        return  Sq->data[Sq->front];
 96    }
 97    
 98    void Clear(SeqQueue Sq)
 99    {
 100    
 101        Sq->front = Sq->rear = -1;
 102        printf("队列已清空!\n");
 103    }
 104    
 105    void Destory(SeqQueue Sq)
 106    {
 107        free(Sq);
 108        printf("队列已销毁!\n");
 109    }

main.c //测试文件

 110    #include <stdio.h>
 111    #include <stdlib.h>
 112    #include "SeqQueue.h"
 113    
 114    int main()
 115    {
 116        SeqQueue Sq = Create();                     //创建队列
 117        srand((unsigned)time(0));
 118        for (int i = 0; i < 10; ++i)
 119        {
 120            Insert(Sq, rand() % 100);                 //入队列,随机产生的数
 121        }
 122        printf("队列长度:%d\n", getLength(Sq));
 123        printf("队头元素  出队元素\n");
 124        while (Sq->front != Sq->rear)                 //出队列,循环条件是队列不为空
 125        {
 126            int ret = GetHead(Sq);                    //获取队头元素
 127            printf("  %d          ", ret);
 128            ret = Del(Sq);                             //出队列
 129            printf("%d\n", ret);
 130        }
 131        printf("队列长度:%d\n", getLength(Sq));
 132        Clear(Sq);
 133        Destory(Sq);
 134    
 135        system("pause");
 136        return 0;
 137    }

运行结果如图4所示。

图4 例1运行结果

在例1中,代码6-11行定义了一个struct,其中定义了队头队尾标志front与rear,与一个int类型数组data,表明此队列用来存放int类型数据。之后的代码中一共实现了队列的创建、获取长度、判空、入队、出队、获取队头元素、清空和销毁这八个基本操作。顺序队列的实现与顺序表相似,但有几点需要注意:获取长度时,队列的长度是队列中实际存储数据的个数;在判断是否为空时,其条件是“front == rear”是否成立;在有新元素入队时,rear要向后移动;在有元素出队时,front要向后移动。

脚下留心:队列的“溢出”

在顺序队列的存储过程中,可能出现“溢出”现象,队列的“溢出”有两种情况,一种为真“溢出”,一种为假“溢出”。

所谓真“溢出”是指当队列分配的空间已满,此时再往里存储元素则会出现“溢出”,这种“溢出”是真的再无空间来存储元素,是真“溢出”。

而假“溢出”是指队列尚有空间而出现的“溢出”情况。当front端有元素出队时,front向后移动;当rear端有元素入队时,rear向后移动,若rear已指到队列中下标最大的位置,此时虽然front前面有空间,但再有元素入队也会出现“溢出”,这种“溢出”叫作“假溢出”。

点击此处
隐藏目录