Pome资料库
Pome 切换暗/亮/自动模式 切换暗/亮/自动模式 切换暗/亮/自动模式 返回首页

队列-使用队列实作

说明

伫列即队列

队列是一种先进先出的资料结构,想像您在管子中放入球,最先放入的球在另一端会最先跑出来,在这边介绍如何使用阵列来实作队列。

解法

使用阵列来实作伫列,我们必须保留两个旗标,假设front指向伫列的前端,rear向伫列的后端,我们每次从伫列后端加入一个资料,rear就加1指向最后一个资料,每次从伫列前端取出一个资料,front就加1指向伫列的最前端,如下图所示:

这是最简单的伫列实作,但是由于阵列的大小必须先决定,所以这种线性的结构有个问题,front与rear会到达阵列的后端,而这个阵列就不能再使用了, 为了解决这个问题,将阵列当作环状来使用,当front或rear到达阵列后端时,就重新从阵列前端再循环,也就是形成环状伫列,如下图所示:

不过阵列的容量还是受限制,所以这个阵列还是会满的,当front = rear时,伫列就满了;伫列的基本操作有五项:新增伫列、加入资料、显示前端资料、取出前端资料、显示所有的伫列元素。

参考代码

C

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
#include <stdio.h> 
#include <stdlib.h> 
#define N 10 

void createq(int[], int*, int*); 
void showfront(int[], int, int); 
void add(int[], int*, int*, int); 
void del(int[], int*, int*); 
void showqueue(int[], int, int); 

int main(void) { 
    int queue[N]; 
    int front, rear; 
    int input, select; 

    createq(queue, &front, &rear); 

    while(1) { 
        printf("\n\n请输入选项(-1结束):"); 
        printf("\n(1)插入值至伫列"); 
        printf("\n(2)显示伫列前端"); 
        printf("\n(3)删除前端值"); 
        printf("\n(4)显示所有内容"); 
        printf("\n$c>"); 
        scanf("%d", &select); 
        
        if(select == -1) 
            break; 

        switch(select) { 
            case 1: 
                printf("\n输入值:"); 
                scanf("%d", &input); 
                add(queue, &front, &rear, input); 
                break; 
            case 2: 
                showfront(queue, front, rear); 
                break; 
            case 3: 
                del(queue, &front, &rear); 
                break; 
            case 4: 
                showqueue(queue, front, rear); 
                break; 
            default: 
                printf("\n选项错误!"); 
        } 
    } 

    printf("\n"); 

    return 0; 
} 

void createq(int queue[], int* front, int* rear) { 
    int i; 

    for(i = 0; i < N; i++) 
        queue[i] = 0; 

    *front = *rear = 0; 
} 

void showfront(int queue[], int front, int rear) { 
    if(front == rear) 
        printf("\n伫列为空!"); 
    else 
        printf("%d", queue[(front+1) % N]); 
} 

void add(int queue[], int* front, int* rear, int data) { 
    int f, r; 
    f = *front; 
    r = *rear; 
    r = (r+1) % N; 

    if(f == r) { 
        printf("\n伫列已满!"); 
        return; 
    } 

    queue[r] = data; 
    *rear = r; 
} 

void del(int queue[], int* front, int* rear) { 
    int f, r; 
    f = *front; 
    r = *rear; 

    if(f == r) { 
        printf("\n伫列为空!"); 
        return; 
    } 

    f = (f+1) % N; 
    *front = f; 
} 

void showqueue(int queue[], int front, int rear) { 
    int i; 

    printf("\n伫列内容:"); 
    for(i = (front+1) % N; i <= rear; i++) 
        printf("%d ", queue[i]); 
}

补充

您如果仔细演算过上面的环状伫列,您会发现有一个空间会被浪费掉,这是因为判断伫列已满或已空的条件都是front = rear,浪费一个空间对现在的电脑记忆体如此足够来说,并不是个大问题,如果您一定要解决这个问题,可以多使用一个flag来判断,如果flag设定为 1且front = rear,则表示伫列已满,如果flag设定为0则front = rear,则表示伫列已空,这样就不会浪费一个伫列空间了,提供改良后的虚拟码如下:

Procedure add(queue, n, front, rear, flag, data) 
    if(front = rear and flag = 1) 
        then call QUEUE_FULL 
    queue(rear) <- data 
    if(front = rear) 
       then flag <- 1 
end add 

Procedure del(queue, n, front, rear, flag, data) 
    if(front = rear and flag = 0) 
        then call QUEUE_EMPTY 
    front <- (front+1) mod n 
    if(front = rear) 
        then flag <- 1 
end del