• C语言队列_6


    队列的基本概念
    队列 (Queue) :也是运算受限的线性表。是一种先进先出 (First In First Out ,简称 FIFO) 的线性表。只允许在表的一端进行插入,而在另一端进行删除。
    队首 (front) :允许进行删除的一端称为队首。
    队尾 (rear) :允许进行插入的一端称为队尾。

    队列中没有元素时称为空队列。在空队列中依次加入元素 a 1 , a 2 , …, a n 之后, a 1 是队首元素, a n 是队尾元素。显然退出队列的次序也只能是 a 1 , a 2 , …, a n ,即队列的修改是依先进先出的原则进行的,如图 3-5 所示。

    基本操作
    1、创建新队列
    2、判空
    3、进队
    4、出队
    5、清空队
    6、获得队头元素
    7、遍历队
    8、销毁队
    9、队长
    顺序队列
    利用一组连续的存储单元 ( 一维数组 ) 依次存放从队首到队尾的各个元素,称为顺序队列。对于队列,和顺序栈相类似,也有动态和静态之分。这里介绍静态顺序队列.其类型定义如
    下:

    typedef int datatype;
    #define MAX_QUEUE_SIZE 100
    typedef struct queue
    {
    datatype queue_array[MAX_QUEUE_SIZE];
    int front;
    int rear;
    }sp_queue;

    设立一个队首指针 front ,一个队尾指针rear ,分别指向队首和队尾元素。
    ◆ 初始化: front=rear =0。
    ◆ 入队:将新元素插入 rear 所指的位置,然后rear 加 1 。
    ◆ 出队:删去 front 所指的元素,然后加 1 并返回被删元素。
    ◆ 队列为空: front=rear 。
    ◆ 队满: rear = MAX_QUEUE_SIZE - 1 或front=rear 。

    在非空队列里,队首指针始终指向队头元素,而队尾指针始终指向队尾元素的下一位置。顺序队列中存在“假溢出”现象。因为在入队和出队操作中,头、尾指针只增加不减小,致使被删除元素的空间永远无法重新利用。因此,尽管队列中实际元素个数可能远远小于数组大小,但可能由于尾指针巳超出向量空间的上界而不能做入队操作。该现象称为假溢出。如图 3-6 所示是数组大小为 5 的顺序队列中队首、队尾指针和队列中元素的变化情况。

    代码实现:

      1 /* 顺序队列接口定义头文件*/
      2 #define true 1
      3 #define false 0
      4 
      5 
      6 /* 队的最大长度 */
      7 #define MAX_QUEUE_SIZE 100
      8 /* 队列的数据类型 */
      9 typedef int datatype;
     10 
     11 /* 静态链的数据结构 */
     12 typedef struct queue{
     13     datatype sp_queue_array[MAX_QUEUE_SIZE];
     14     /* 队头 */
     15     int front;
     16     /* 队尾 */
     17     int rear;
     18 }sp_queue;
     19 
     20 
     21 /* 静态顺序链的接口定义 */
     22 
     23 
     24 /* 静态链的初始化 */
     25 sp_queue queue_init();
     26 
     27 /* 判断队列是否为空,若为空
     28  * 返回true
     29  * 否则返回false
     30 */
     31 int queue_empty(sp_queue q);
     32 
     33 
     34 /* 插入元素e为队q的队尾新元素 
     35  * 插入成功返回true
     36  * 队满返回false
     37 */
     38 int queue_en(sp_queue *q, datatype e);
     39 
     40 
     41 /* 队头元素出队
     42  * 用e返回出队元素,并返回true
     43  * 若队空返回false
     44 */
     45 int queue_de(sp_queue *q, datatype *e);
     46 
     47 /* 清空队 */
     48 void queue_clear(sp_queue *q);
     49 
     50 
     51 /* 获得队头元素
     52  * 队列非空,用e返回队头元素,并返回true
     53  * 否则返回false
     54 */
     55 int get_front(sp_queue, datatype *e );
     56 
     57 
     58 /* 获得队长 */
     59 int queue_len(sp_queue q);
     60 
     61 /* 遍历队 */
     62 void queue_traverse(sp_queue q, void(*visit)(sp_queue q));
     63 
     64 
     65 void visit(sp_queue s);
     66 
     67 
     68 /* 接口实现文件 */
     69 #include<stdio.h>
     70 #include<stdlib.h>
     71 #include"sp_queue.h"
     72 
     73 
     74 sp_queue queue_init()
     75 {
     76     sp_queue q;
     77     q.front = q.rear = 0;
     78     return q;
     79 }
     80 
     81 
     82 
     83 int queue_empty(sp_queue q)
     84 {
     85     return q.front == q.rear;
     86 }
     87 
     88 
     89 int queue_en(sp_queue *q, datatype e)
     90 {
     91     /* 队满 */
     92     if (q -> rear == MAX_QUEUE_SIZE)
     93         return false;
     94 
     95     /* 入队 */
     96     q -> sp_queue_array[q -> rear] = e;
     97     printf("q.sp_queue_array[%d]=%d
    ", q -> rear, e);
     98     q -> rear += 1;
     99     return true;
    100 
    101 }
    102 
    103 
    104 int queue_de(sp_queue *q, datatype *e)
    105 {
    106     /* 队空 */
    107     if(queue_empty(*q))
    108         return false;
    109 
    110     /* 出队 */
    111     q -> rear -= 1;
    112     *e = q -> sp_queue_array[q -> rear];
    113     return true;
    114 }
    115 
    116 
    117 void queue_clear(sp_queue *q)
    118 {
    119     q -> front = q -> rear = 0;
    120 }
    121 
    122 
    123 int get_front(sp_queue q, datatype *e)
    124 {
    125     /* 队空 */
    126     if(q.front == q.rear)
    127         return false;
    128 
    129     /* 获取队头元素 */
    130     *e = q.sp_queue_array[q.front];
    131     return true;
    132 }
    133 
    134 
    135 int queue_len(sp_queue q)
    136 {
    137     return (q.rear - q.front);
    138 }
    139 
    140 
    141 void queue_traverse(sp_queue q, void (*visit)(sp_queue q))
    142 {
    143     visit(q);
    144 }
    145 
    146 void visit(sp_queue q)
    147 {
    148     /* 队空 */
    149     if (q.front == q.rear)
    150         printf("队列为空
    ");
    151 
    152     int temp = q.front;
    153     while(temp != q.rear)
    154     {
    155         printf("%d ",q.sp_queue_array[temp]);
    156         temp += 1;
    157     }
    158     printf("
    ");
    159 }
    160 
    161 
    162 
    163 int main()
    164 {
    165     sp_queue q = queue_init();
    166     queue_en(&q, 1);
    167     queue_en(&q, 2);
    168     printf("length=%d
    ", queue_len(q));
    169     queue_en(&q, 3);
    170     printf("length=%d
    ", queue_len(q));
    171     queue_en(&q, 4);
    172     printf("length=%d
    ", queue_len(q));
    173     queue_en(&q, 5);
    174     printf("length=%d
    ", queue_len(q));
    175     queue_en(&q, 6);
    176     printf("length=%d
    ", queue_len(q));
    177     queue_traverse(q,visit);
    178     datatype *e = (datatype *)malloc(sizeof(*e));
    179     queue_de(&q,e);
    180     printf("queue_de(),e=%d length=%d
    ", *e, queue_len(q));
    181     queue_traverse(q, visit);
    182     queue_clear(&q);
    183     queue_traverse(q, visit);
    184     printf("length:%d
    ", queue_len(q));
    185 }

    队列的链式表示和实现

    队列的链式存储结构简称为链队列,它是限制仅在表头进行删除操作和表尾进行插入操作的单链表。需要两类不同的结点:数据元素结点,队列的队 
    首指针和队尾指针的结点,如图 3-8 所示。 

     数据元素结点类型定义:

    typedef struct q_node{
    datatype data;
    struct q_node *next;
    }q_node;

    指针结点类型:

    typedef struct {
    q_node *front;
    q_node *rear;
    }link_queue;

    链队运算及指针变化

    链队的操作实际上是单链表的操作,只不过是删除 
    在表头进行,插入在表尾进行。插入、删除时分别修改 
    不同的指针。链队运算及指针变化如图 3-9 所示。

    代码实现:

      1 /* 链式栈接口的定义头文件 */
      2 #define true 1
      3 #define false 0
      4 
      5 
      6 /* 队列的数据类型 */
      7 typedef int datatype;
      8 
      9 /* 静态链的数据结构 */
     10 typedef struct q_node{
     11     datatype data;
     12     struct q_node *next;
     13 }q_node,*link_node;
     14 
     15 typedef struct l_queue{
     16     /* 队头指针 */
     17     q_node *front;
     18     /* 队尾指针 */
     19     q_node *rear;
     20 }*link_queue;
     21 
     22 
     23 /* 静态顺序链的接口定义 */
     24 
     25 
     26 /* 静态链的初始化 */
     27 link_queue queue_init();
     28 
     29 /* 判断队列是否为空,若为空
     30  * 返回true
     31  * 否则返回false
     32 */
     33 int queue_empty(link_queue q);
     34 
     35 /* 插入元素e为队q的队尾新元素 
     36  * 插入成功返回true
     37  * 队满返回false
     38 */
     39 int queue_en(link_queue q, datatype e);
     40 
     41 
     42 /* 队头元素出队
     43  * 用e返回出队元素,并返回true
     44  * 若队空返回false
     45 */
     46 int queue_de(link_queue q, datatype *e);
     47 
     48 /* 清空队 */
     49 void queue_clear(link_queue q);
     50 
     51 /* 销毁队 */
     52 void queue_destroy(link_queue q);
     53 
     54 /* 获得队头元素
     55  * 队列非空,用e返回队头元素,并返回true
     56  * 否则返回false
     57 */
     58 int get_front(link_queue q, datatype *e );
     59 
     60 
     61 /* 获得队长 */
     62 int queue_len(link_queue q);
     63 
     64 /* 遍历队 */
     65 void queue_traverse(link_queue q, void(*visit)(link_queue q));
     66 
     67 
     68 void visit(link_queue q);
     69 
     70 
     71 
     72 /* 接口的实现文件 */
     73 #include<stdio.h>
     74 #include<stdlib.h>
     75 #include"lp_queue.h"
     76 
     77 
     78 
     79 link_queue queue_init()
     80 {
     81     /* 新建头结点 */
     82     link_node new_node = (link_node)malloc(sizeof(q_node));
     83     new_node -> next = NULL;
     84     /* 指针结点 */
     85     link_queue q = (link_queue)malloc(sizeof(*q));
     86     q -> front = q -> rear = new_node;
     87     return q;
     88 }
     89 
     90 
     91 int queue_empty(link_queue q)
     92 {
     93     return q -> front == q -> rear;
     94 }
     95 
     96 
     97 int queue_en(link_queue q, datatype e)
     98 {
     99     /* 新建数据结点 */
    100     link_node new_node = (link_node)malloc(sizeof(q_node));
    101     /* 内存分配失败 */
    102     if(!new_node)
    103         return false;
    104     new_node -> data = e;
    105     q -> rear -> next = new_node;
    106     q -> rear = new_node;
    107     return true;
    108 }
    109 
    110 int queue_de(link_queue q, datatype *e)
    111 {
    112     /* 队列为空 */
    113     if (q -> front == q -> rear)
    114         return false;
    115 
    116     *e = q -> front -> next -> data;
    117     link_node temp = q -> front -> next;
    118     q -> front -> next = temp -> next;
    119     /* 防止丢失尾指针 */
    120     if (temp == q.rear -> next)
    121         q -> rear = q -> front; 
    122     free(temp);
    123     temp = NULL;
    124     return true;
    125 }
    126 
    127 void queue_clear(link_queue q)
    128 {
    129     /* 头结点 */
    130     link_node head = q -> front -> next;
    131     head -> next = NULL;
    132     q -> front = q -> rear = head;
    133     /* 第一个结点 */
    134     link_node temp = head -> next;
    135     while(temp)
    136     {
    137         link_node p = temp;
    138         temp = p -> next;
    139         free(p);
    140         p = NULL;
    141     }
    142 }
    143 
    144 
    145 void queue_destroy(link_queue q)
    146 {
    147     queue_clear(q);
    148     free(q);
    149     q = NULL;
    150 }
    151 
    152 
    153 int get_front(link_queue q, datatype *e)
    154 {
    155     /* 队为空 */
    156     if (q -> front == q -> rear)
    157         return false;
    158 
    159     *e = q -> front -> next -> data;
    160     link_node temp = q -> front -> next;
    161     q -> front -> next = temp -> next;
    162     free(temp);
    163     temp = NULL;
    164     return true;
    165 }
    166 
    167 
    168 int queue_len(link_queue q)
    169 {
    170     /* 头结点 */
    171     link_node p = q -> front -> next;
    172     /* 计数器 */
    173     int count = 0;
    174     while(p)
    175     {
    176         count += 1;
    177         p = p -> next;
    178     }
    179     return count;
    180 }
    181 
    182 
    183 void queue_traverse(link_queue q, void(*visit)(link_queue q))
    184 {
    185     visit(q);
    186 }
    187 
    188 void visit(link_queue q)
    189 {
    190     /* 头结点 */
    191     link_node p = q -> front -> next;
    192     if(!p)
    193     {
    194         printf("队列为空");
    195     }
    196     while(p)
    197     {
    198         printf("%d ", p -> data);
    199         p = p -> next;
    200     }
    201     printf("
    ");
    202 }
    203 
    204 int main()
    205 {
    206     link_queue q = queue_init();
    207     queue_en(q, 1);
    208     queue_en(q, 2);
    209     printf("length=%d
    ", queue_len(q));
    210     queue_en(q, 3);
    211     printf("length=%d
    ", queue_len(q));
    212     queue_en(q, 4);
    213     printf("length=%d
    ", queue_len(q));
    214     queue_en(q, 5);
    215     printf("length=%d
    ", queue_len(q));
    216     queue_en(q, 6);
    217     printf("length=%d
    ", queue_len(q));
    218     queue_traverse(q,visit);
    219     datatype *e = (datatype *)malloc(sizeof(*e));
    220     queue_de(q,e);
    221     printf("queue_de(),e=%d length=%d
    ", *e, queue_len(q));
    222     queue_traverse(q, visit);
    223     queue_clear(q);
    224     queue_traverse(q, visit);
    225     printf("length:%d
    ", queue_len(q));
    226 }
  • 相关阅读:
    委托
    Math方法讲解
    正则表达式判断邮件输入的是否正确
    值类型与引用类型作为参数输出的效果
    listView 控件加上选择框
    ?: ?? ? 的区别
    学习思维导图之前先了解这些常识
    PDF文档如何添加图片签名
    CleanMyMac与腾讯柠檬清理软件的简单对比
    如何用思维导图MindManager制作一套学习法
  • 原文地址:https://www.cnblogs.com/linxw-blog/p/12168881.html
Copyright © 2020-2023  润新知