• 队列的图文解析 和 对应3种语言的实现(C/C++/Java)


     

    概要

    本章和介绍""时的流程一样,先对队列进行介绍,然后分别给出队列的C、C++和Java三种语言的实现。内容包括:
    1. 队列的介绍
    2. 队列的C实现
    3. 队列的C++实现
    4. 队列的Java实现

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3562279.html


    更多内容: 数据结构与算法系列 目录

    队列的介绍

    队列(Queue),是一种线性存储结构。它有以下几个特点:
    (01) 队列中数据是按照"先进先出(FIFO, First-In-First-Out)"方式进出队列的。
    (02) 队列只允许在"队首"进行删除操作,而在"队尾"进行插入操作。
    队列通常包括的两种操作:入队列 出队列

    1. 队列的示意图

    队列中有10,20,30共3个数据。

    2. 出队列

    出队列前:队首是10,队尾是30。
    出队列后:出队列(队首)之后。队首是20,队尾是30。

    3. 入队列

    入队列前:队首是20,队尾是30。
    入队列后:40入队列(队尾)之后。队首是20,队尾是40。

     

    下面介绍队列的实现,分别介绍C/C++/Java三种实现

    队列的C实现

    共介绍4种C语言实现。
    1. C语言实现一:数组实现的队列,并且只能存储int数据。
    2. C语言实现二:单向链表实现的队列,并且只能存储int数据。
    3. C语言实现三:双向链表实现的队列,并且只能存储int数据。
    4. C语言实现四:双向链表实现的队列,能存储任意类型的数据。

    1. C语言实现一:数组实现的队列,并且只能存储int数据

    实现代码(array_queue.c)

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 
      4 /**
      5  * C 语言: 数组实现的队列,只能存储int数据。
      6  *
      7  * @author skywang
      8  * @date 2013/11/07
      9  */
     10 
     11 // 保存数据的数组
     12 static int *arr=NULL;
     13 // 队列的实际大小
     14 static int count;
     15 
     16 // 创建“队列”
     17 int create_array_queue(int sz) 
     18 {
     19     arr = (int *)malloc(sz*sizeof(int));
     20     if (!arr) 
     21     {
     22         printf("arr malloc error!");
     23         return -1;
     24     }
     25     count = 0;
     26 
     27     return 0;
     28 }
     29 
     30 // 销毁“队列”
     31 int destroy_array_queue() 
     32 {
     33     if (arr) 
     34     {
     35         free(arr);
     36         arr = NULL;
     37     }
     38 
     39     return 0;
     40 }
     41 
     42 // 将val添加到队列的末尾
     43 void add(int val) 
     44 {
     45     arr[count++] = val;
     46 }
     47 
     48 // 返回“队列开头元素”
     49 int front() 
     50 {
     51     return arr[0];
     52 }
     53 
     54 // 返回并删除“队列开头元素”
     55 int pop() 
     56 {
     57     int i = 0;;
     58     int ret = arr[0];
     59 
     60     count--;
     61     while (i++<count)
     62         arr[i-1] = arr[i];
     63 
     64     return ret;
     65 }
     66 
     67 // 返回“队列”的大小
     68 int size() 
     69 {
     70     return count;
     71 }
     72 
     73 // 返回“队列”是否为空
     74 int is_empty()
     75 {
     76     return count==0;
     77 }
     78 
     79 void main() 
     80 {
     81     int tmp=0;
     82 
     83     // 创建“队列”
     84     create_array_queue(12);
     85 
     86     // 将10, 20, 30 依次推入队列中
     87     add(10);
     88     add(20);
     89     add(30);
     90 
     91     // 将“队列开头的元素”赋值给tmp,并删除“该元素”
     92     tmp = pop();
     93     printf("tmp=%d
    ", tmp);
     94 
     95     // 只将“队列开头的元素”赋值给tmp,不删除该元素.
     96     tmp = front();
     97     printf("tmp=%d
    ", tmp);
     98 
     99     add(40);
    100 
    101     // 打印队列
    102     printf("is_empty()=%d
    ", is_empty());
    103     printf("size()=%d
    ", size());
    104     while (!is_empty())
    105     {
    106         printf("%d
    ", pop());
    107     }
    108 
    109     // 销毁队列
    110     destroy_array_queue();
    111 }
    View Code

    运行结果

    tmp=10
    tmp=20
    is_empty()=0
    size()=3
    20
    30
    40

    结果说明该示例中的队列,是通过"数组"来实现的!
    由于代码中已经给出了详细了注释,这里就不再对函数进行说明了。仅对主函数main的逻辑进行简单介绍。
    (01) 在主函数main中,先将 "10, 20, 30"依次入队列。此时,队列的数据是: 10 --> 20 --> 30
    (02) 接着通过pop()返回队首元素;pop()操作并不会改变队列中的数据。此时,队列的数据依然是: 10 --> 20 --> 30
    (03) 接着通过front()返回并删除队首元素。front()操作之后,队列的数据是: 10 --> 30
    (04) 接着通过add(40)将40入队列。add(40)操作之后,队列中的数据是: 10 --> 20 --> 40

    2. C语言实现二:单向链表实现的队列,并且只能存储int数据

    实现代码(slink_queue.c)

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 
      4 /**
      5  * C 语言: 单链表实现“队列”,只能存储int数据。
      6  *
      7  * @author skywang
      8  * @date 2013/11/07
      9  */
     10 
     11 // 单链表节点
     12 struct node {
     13     int val;
     14     struct node* next;
     15 };
     16 
     17 // 表头
     18 static struct node *phead=NULL;
     19 
     20 // 创建节点,val为节点值
     21 static struct node* create_node(val) 
     22 {
     23     struct node *pnode=NULL;
     24     pnode = (struct node*)malloc(sizeof(struct node));
     25     if (!pnode)
     26         return NULL;
     27     pnode->val = val;
     28     pnode->next = NULL;
     29     
     30     return pnode;
     31 }
     32 
     33 // 销毁单向链表
     34 static int destroy_single_link() 
     35 {
     36     struct node *pnode=NULL;
     37 
     38     while (phead != NULL) 
     39     {
     40         pnode = phead;
     41         phead = phead->next;
     42         free(pnode);
     43     }
     44     return 0;
     45 }
     46 
     47 // 将val添加到队列的末尾
     48 static void add(int val) 
     49 {
     50     if (!phead)
     51     {
     52         phead = create_node(val);
     53         return ;
     54     }
     55 
     56     struct node *pnode = create_node(val);
     57     struct node *pend = phead;
     58     while (pend->next)
     59         pend = pend->next;
     60 
     61     pend->next = pnode;
     62 }
     63 
     64 // 返回“队列开头元素”
     65 int front() 
     66 {
     67     return phead->val;
     68 }
     69 
     70 // 返回并删除“队列开头元素”
     71 static int pop() 
     72 {
     73     int ret = phead->val;
     74     struct node *pnode = phead;
     75 
     76     phead = phead->next;
     77     free(pnode);
     78 
     79     return ret;
     80 }
     81 
     82 // 返回链表中节点的个数
     83 static int size() 
     84 {
     85     int count=0;
     86     struct node *pend = phead;
     87 
     88     while (pend) 
     89     {
     90         pend = pend->next;
     91         count++;
     92     }
     93 
     94     return count;
     95 }
     96 
     97 // 链表是否为空
     98 static int is_empty() 
     99 {
    100     return size()==0;
    101 }
    102 
    103 void main() 
    104 {
    105     int tmp=0;
    106 
    107     // 将10, 20, 30 依次加入到队列中
    108     add(10);
    109     add(20);
    110     add(30);
    111 
    112     // 将“队列开头元素”赋值给tmp,并删除“该元素”
    113     tmp = pop();
    114     printf("tmp=%d
    ", tmp);
    115 
    116     // 只将“队列开头的元素”赋值给tmp,不删除该元素.
    117     tmp = front();
    118     printf("tmp=%d
    ", tmp);
    119 
    120     add(40);
    121 
    122     printf("is_empty()=%d
    ", is_empty());
    123     printf("size()=%d
    ", size());
    124     while (!is_empty())
    125     {
    126         printf("%d
    ", pop());
    127     }
    128 
    129     // 销毁队列
    130     destroy_single_link();
    131 }
    View Code

    代码说明"运行结果" 以及 "主函数main的逻辑"都和"C语言实现一"的一样。不同的是,该示例中的队列是通过单向链表实现的。

    3. C语言实现三:双向链表实现的队列,并且只能存储int数据

    实现代码
    双向链表的头文件(double_link.h)

     1 #ifndef _DOUBLE_LINK_H
     2 #define _DOUBLE_LINK_H
     3 
     4 // 新建“双向链表”。成功,返回表头;否则,返回NULL
     5 extern int create_dlink();
     6 // 撤销“双向链表”。成功,返回0;否则,返回-1
     7 extern int destroy_dlink();
     8 
     9 // “双向链表是否为空”。为空的话返回1;否则,返回0。
    10 extern int dlink_is_empty();
    11 // 返回“双向链表的大小”
    12 extern int dlink_size();
    13 
    14 // 获取“双向链表中第index位置的元素的值”。成功,返回节点值;否则,返回-1。
    15 extern int dlink_get(int index);
    16 // 获取“双向链表中第1个元素的值”。成功,返回节点值;否则,返回-1。
    17 extern int dlink_get_first();
    18 // 获取“双向链表中最后1个元素的值”。成功,返回节点值;否则,返回-1。
    19 extern int dlink_get_last();
    20 
    21 // 将“value”插入到index位置。成功,返回0;否则,返回-1。
    22 extern int dlink_insert(int index, int value);
    23 // 将“value”插入到表头位置。成功,返回0;否则,返回-1。
    24 extern int dlink_insert_first(int value);
    25 // 将“value”插入到末尾位置。成功,返回0;否则,返回-1。
    26 extern int dlink_append_last(int value);
    27 
    28 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1
    29 extern int dlink_delete(int index);
    30 // 删除第一个节点。成功,返回0;否则,返回-1
    31 extern int dlink_delete_first();
    32 // 删除组后一个节点。成功,返回0;否则,返回-1
    33 extern int dlink_delete_last();
    34 
    35 // 打印“双向链表”
    36 extern void print_dlink();
    37 
    38 #endif 
    View Code

    双向链表的实现文件(double_link.c)

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 
      4 /**
      5  * C 语言: 双向链表,只能存储int数据。
      6  *
      7  * @author skywang
      8  * @date 2013/11/07
      9  */
     10 
     11 // 双向链表节点
     12 typedef struct tag_node 
     13 {
     14     struct tag_node *prev;
     15     struct tag_node *next;
     16     int value;
     17 }node;
     18 
     19 // 表头。注意,表头不存放元素值!!!
     20 static node *phead=NULL;
     21 // 节点个数。
     22 static int  count=0;
     23 
     24 // 新建“节点”。成功,返回节点指针;否则,返回NULL。
     25 static node* create_node(int value)
     26 {
     27     node *pnode=NULL;
     28     pnode = (node *)malloc(sizeof(node));
     29     if (!pnode)
     30     {
     31         printf("create node error!
    ");
     32         return NULL;
     33     }
     34     // 默认的,pnode的前一节点和后一节点都指向它自身
     35     pnode->prev = pnode->next = pnode;
     36     // 节点的值为value
     37     pnode->value = value;
     38 
     39     return pnode;
     40 }
     41 
     42 // 新建“双向链表”。成功,返回0;否则,返回-1。
     43 int create_dlink()
     44 {
     45     // 创建表头
     46     phead = create_node(-1);
     47     if (!phead)
     48         return -1;
     49 
     50     // 设置“节点个数”为0
     51     count = 0;
     52 
     53     return 0;
     54 }
     55 
     56 // “双向链表是否为空”
     57 int dlink_is_empty()
     58 {
     59     return count == 0;
     60 }
     61 
     62 // 返回“双向链表的大小”
     63 int dlink_size() {
     64     return count;
     65 }
     66 
     67 // 获取“双向链表中第index位置的节点”
     68 static node* get_node(int index) 
     69 {
     70     if (index<0 || index>=count)
     71     {
     72         printf("%s failed! the index in out of bound!
    ", __func__);
     73         return NULL;
     74     }
     75 
     76     // 正向查找
     77     if (index <= (count/2))
     78     {
     79         int i=0;
     80         node *pnode=phead->next;
     81         while ((i++) < index) 
     82             pnode = pnode->next;
     83 
     84         return pnode;
     85     }
     86 
     87     // 反向查找
     88     int j=0;
     89     int rindex = count - index - 1;
     90     node *rnode=phead->prev;
     91     while ((j++) < rindex) 
     92         rnode = rnode->prev;
     93 
     94     return rnode;
     95 }
     96 
     97 // 获取“第一个节点”
     98 static node* get_first_node() 
     99 {
    100     return get_node(0);
    101 }
    102 
    103 // 获取“最后一个节点”
    104 static node* get_last_node() 
    105 {
    106     return get_node(count-1);
    107 }
    108 
    109 // 获取“双向链表中第index位置的元素的值”。成功,返回节点值;否则,返回-1。
    110 int dlink_get(int index)
    111 {
    112     node *pindex=get_node(index);
    113     if (!pindex) 
    114     {
    115         printf("%s failed!
    ", __func__);
    116         return -1;
    117     }
    118 
    119     return pindex->value;
    120 
    121 }
    122 
    123 // 获取“双向链表中第1个元素的值”
    124 int dlink_get_first()
    125 {
    126     return dlink_get(0);
    127 }
    128 
    129 // 获取“双向链表中最后1个元素的值”
    130 int dlink_get_last()
    131 {
    132     return dlink_get(count-1);
    133 }
    134 
    135 // 将“value”插入到index位置。成功,返回0;否则,返回-1。
    136 int dlink_insert(int index, int value) 
    137 {
    138     // 插入表头
    139     if (index==0)
    140         return dlink_insert_first(value);
    141 
    142     // 获取要插入的位置对应的节点
    143     node *pindex=get_node(index);
    144     if (!pindex) 
    145         return -1;
    146 
    147     // 创建“节点”
    148     node *pnode=create_node(value);
    149     if (!pnode)
    150         return -1;
    151 
    152     pnode->prev = pindex->prev;
    153     pnode->next = pindex;
    154     pindex->prev->next = pnode;
    155     pindex->prev = pnode;
    156     // 节点个数+1
    157     count++;
    158 
    159     return 0;
    160 }
    161 
    162 // 将“value”插入到表头位置
    163 int dlink_insert_first(int value) 
    164 {
    165     node *pnode=create_node(value);
    166     if (!pnode)
    167         return -1;
    168 
    169     pnode->prev = phead;
    170     pnode->next = phead->next;
    171     phead->next->prev = pnode;
    172     phead->next = pnode;
    173     count++;
    174     return 0;
    175 }
    176 
    177 // 将“value”插入到末尾位置
    178 int dlink_append_last(int value) 
    179 {
    180     node *pnode=create_node(value);
    181     if (!pnode)
    182         return -1;
    183     
    184     pnode->next = phead;
    185     pnode->prev = phead->prev;
    186     phead->prev->next = pnode;
    187     phead->prev = pnode;
    188     count++;
    189     return 0;
    190 }
    191 
    192 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。
    193 int dlink_delete(int index)
    194 {
    195     node *pindex=get_node(index);
    196     if (!pindex) 
    197     {
    198         printf("%s failed! the index in out of bound!
    ", __func__);
    199         return -1;
    200     }
    201 
    202     pindex->next->prev = pindex->prev;
    203     pindex->prev->next = pindex->next;
    204     free(pindex);
    205     count--;
    206 
    207     return 0;
    208 }    
    209 
    210 // 删除第一个节点
    211 int dlink_delete_first() 
    212 {
    213     return dlink_delete(0);
    214 }
    215 
    216 // 删除组后一个节点
    217 int dlink_delete_last() 
    218 {
    219     return dlink_delete(count-1);
    220 }
    221 
    222 // 撤销“双向链表”。成功,返回0;否则,返回-1。
    223 int destroy_dlink()
    224 {
    225     if (!phead)
    226     {
    227         printf("%s failed! dlink is null!
    ", __func__);
    228         return -1;
    229     }
    230 
    231     node *pnode=phead->next;
    232     node *ptmp=NULL;
    233     while(pnode != phead)
    234     {
    235         ptmp = pnode;
    236         pnode = pnode->next;
    237         free(ptmp);
    238     }
    239 
    240     free(phead);
    241     phead = NULL;
    242     count = 0;
    243 
    244     return 0;
    245 }
    246 
    247 // 打印“双向链表”
    248 void print_dlink()
    249 {
    250     if (count==0 || (!phead))
    251     {
    252         printf("%s dlink is empty!
    ", __func__);
    253         return ;
    254     }
    255 
    256     printf("%s dlink size()=%d
    ", __func__, count);
    257     node *pnode=phead->next;
    258     while(pnode != phead)
    259     {
    260         printf("%d
    ", pnode->value);
    261         pnode = pnode->next;
    262     }
    263 }
    View Code

    双向链表的测试程序(dlink_queue.c)

     1 #include <stdio.h>
     2 #include "double_link.h"
     3 
     4 /**
     5  * C 语言: 双向链表实现“队列”,只能存储int数据。
     6  *
     7  * @author skywang
     8  * @date 2013/11/07
     9  */
    10 
    11 // 创建队列
    12 int create_dlink_queue() 
    13 {
    14     return create_dlink();
    15 }
    16 
    17 // 销毁队列
    18 int destroy_dlink_queue() 
    19 {
    20     return destroy_dlink();
    21 }
    22 
    23 // 将val添加到队列的末尾
    24 int add(int val) 
    25 {
    26     return dlink_append_last(val);
    27 }
    28 
    29 // 返回“队列开头元素”
    30 int front() 
    31 {
    32     return dlink_get_first();
    33 }
    34 
    35 // 返回并删除“队列开头元素”
    36 int pop() 
    37 {
    38     int ret = dlink_get_first();
    39     dlink_delete_first();
    40     return ret;
    41 }
    42 
    43 // 返回“队列”的大小
    44 int size() 
    45 {
    46     return dlink_size();
    47 }
    48 
    49 // 返回“队列”是否为空
    50 int is_empty()
    51 {
    52     return dlink_is_empty();
    53 }
    54 
    55 void main()
    56 {
    57     int tmp=0;
    58 
    59     // 创建“队列”
    60     create_dlink_queue();
    61 
    62     // 将10, 20, 30 依次队列中
    63     add(10);
    64     add(20);
    65     add(30);
    66 
    67     // 将“队列开头的元素”赋值给tmp,并删除“该元素”
    68     tmp = pop();
    69     printf("tmp=%d
    ", tmp);
    70 
    71     // 只将“队列开头的元素”赋值给tmp,不删除该元素.
    72     tmp = front();
    73     printf("tmp=%d
    ", tmp);
    74 
    75     add(40);
    76 
    77     printf("is_empty()=%d
    ", is_empty());
    78     printf("size()=%d
    ", size());
    79     while (!is_empty())
    80     {
    81         printf("%d
    ", pop());
    82     }
    83 
    84     // 销毁队列
    85     destroy_dlink_queue();
    86 }
    View Code

    代码说明"运行结果" 以及 "主函数main的逻辑"都和前两个示例的一样。不同的是,该示例中的队列是通过双向链表实现的。

    4. C语言实现四:双向链表实现的队列,能存储任意类型的数据

    实现代码
    双向链表的头文件(double_link.h)

     1 #ifndef _DOUBLE_LINK_H
     2 #define _DOUBLE_LINK_H
     3 
     4 // 新建“双向链表”。成功,返回表头;否则,返回NULL
     5 extern int create_dlink();
     6 // 撤销“双向链表”。成功,返回0;否则,返回-1
     7 extern int destroy_dlink();
     8 
     9 // “双向链表是否为空”。为空的话返回1;否则,返回0。
    10 extern int dlink_is_empty();
    11 // 返回“双向链表的大小”
    12 extern int dlink_size();
    13 
    14 // 获取“双向链表中第index位置的元素”。成功,返回节点指针;否则,返回NULL。
    15 extern void* dlink_get(int index);
    16 // 获取“双向链表中第1个元素”。成功,返回节点指针;否则,返回NULL。
    17 extern void* dlink_get_first();
    18 // 获取“双向链表中最后1个元素”。成功,返回节点指针;否则,返回NULL。
    19 extern void* dlink_get_last();
    20 
    21 // 将“value”插入到index位置。成功,返回0;否则,返回-1。
    22 extern int dlink_insert(int index, void *pval);
    23 // 将“value”插入到表头位置。成功,返回0;否则,返回-1。
    24 extern int dlink_insert_first(void *pval);
    25 // 将“value”插入到末尾位置。成功,返回0;否则,返回-1。
    26 extern int dlink_append_last(void *pval);
    27 
    28 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1
    29 extern int dlink_delete(int index);
    30 // 删除第一个节点。成功,返回0;否则,返回-1
    31 extern int dlink_delete_first();
    32 // 删除组后一个节点。成功,返回0;否则,返回-1
    33 extern int dlink_delete_last();
    34 
    35 #endif 
    View Code

    双向链表的实现文件(double_link.c)

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 
      4 /**
      5  * C 语言: 双向链表,能存储任意数据。
      6  *
      7  * @author skywang
      8  * @date 2013/11/07
      9  */
     10 
     11 // 双向链表节点
     12 typedef struct tag_node 
     13 {
     14     struct tag_node *prev;
     15     struct tag_node *next;
     16     void* p;
     17 }node;
     18 
     19 // 表头。注意,表头不存放元素值!!!
     20 static node *phead=NULL;
     21 // 节点个数。
     22 static int  count=0;
     23 
     24 // 新建“节点”。成功,返回节点指针;否则,返回NULL。
     25 static node* create_node(void *pval)
     26 {
     27     node *pnode=NULL;
     28     pnode = (node *)malloc(sizeof(node));
     29     if (!pnode)
     30     {
     31         printf("create node error!
    ");
     32         return NULL;
     33     }
     34     // 默认的,pnode的前一节点和后一节点都指向它自身
     35     pnode->prev = pnode->next = pnode;
     36     // 节点的值为pval
     37     pnode->p = pval;
     38 
     39     return pnode;
     40 }
     41 
     42 // 新建“双向链表”。成功,返回0;否则,返回-1。
     43 int create_dlink()
     44 {
     45     // 创建表头
     46     phead = create_node(NULL);
     47     if (!phead)
     48         return -1;
     49 
     50     // 设置“节点个数”为0
     51     count = 0;
     52 
     53     return 0;
     54 }
     55 
     56 // “双向链表是否为空”
     57 int dlink_is_empty()
     58 {
     59     return count == 0;
     60 }
     61 
     62 // 返回“双向链表的大小”
     63 int dlink_size() {
     64     return count;
     65 }
     66 
     67 // 获取“双向链表中第index位置的节点”
     68 static node* get_node(int index) 
     69 {
     70     if (index<0 || index>=count)
     71     {
     72         printf("%s failed! index out of bound!
    ", __func__);
     73         return NULL;
     74     }
     75 
     76     // 正向查找
     77     if (index <= (count/2))
     78     {
     79         int i=0;
     80         node *pnode=phead->next;
     81         while ((i++) < index) 
     82             pnode = pnode->next;
     83 
     84         return pnode;
     85     }
     86 
     87     // 反向查找
     88     int j=0;
     89     int rindex = count - index - 1;
     90     node *rnode=phead->prev;
     91     while ((j++) < rindex) 
     92         rnode = rnode->prev;
     93 
     94     return rnode;
     95 }
     96 
     97 // 获取“第一个节点”
     98 static node* get_first_node() 
     99 {
    100     return get_node(0);
    101 }
    102 
    103 // 获取“最后一个节点”
    104 static node* get_last_node() 
    105 {
    106     return get_node(count-1);
    107 }
    108 
    109 // 获取“双向链表中第index位置的元素”。成功,返回节点值;否则,返回-1。
    110 void* dlink_get(int index)
    111 {
    112     node *pindex=get_node(index);
    113     if (!pindex) 
    114     {
    115         printf("%s failed!
    ", __func__);
    116         return NULL;
    117     }
    118 
    119     return pindex->p;
    120 
    121 }
    122 
    123 // 获取“双向链表中第1个元素的值”
    124 void* dlink_get_first()
    125 {
    126     return dlink_get(0);
    127 }
    128 
    129 // 获取“双向链表中最后1个元素的值”
    130 void* dlink_get_last()
    131 {
    132     return dlink_get(count-1);
    133 }
    134 
    135 // 将“pval”插入到index位置。成功,返回0;否则,返回-1。
    136 int dlink_insert(int index, void* pval) 
    137 {
    138     // 插入表头
    139     if (index==0)
    140         return dlink_insert_first(pval);
    141 
    142     // 获取要插入的位置对应的节点
    143     node *pindex=get_node(index);
    144     if (!pindex) 
    145         return -1;
    146 
    147     // 创建“节点”
    148     node *pnode=create_node(pval);
    149     if (!pnode)
    150         return -1;
    151 
    152     pnode->prev = pindex->prev;
    153     pnode->next = pindex;
    154     pindex->prev->next = pnode;
    155     pindex->prev = pnode;
    156     // 节点个数+1
    157     count++;
    158 
    159     return 0;
    160 }
    161 
    162 // 将“pval”插入到表头位置
    163 int dlink_insert_first(void *pval) 
    164 {
    165     node *pnode=create_node(pval);
    166     if (!pnode)
    167         return -1;
    168 
    169     pnode->prev = phead;
    170     pnode->next = phead->next;
    171     phead->next->prev = pnode;
    172     phead->next = pnode;
    173     count++;
    174     return 0;
    175 }
    176 
    177 // 将“pval”插入到末尾位置
    178 int dlink_append_last(void *pval) 
    179 {
    180     node *pnode=create_node(pval);
    181     if (!pnode)
    182         return -1;
    183     
    184     pnode->next = phead;
    185     pnode->prev = phead->prev;
    186     phead->prev->next = pnode;
    187     phead->prev = pnode;
    188     count++;
    189     return 0;
    190 }
    191 
    192 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。
    193 int dlink_delete(int index)
    194 {
    195     node *pindex=get_node(index);
    196     if (!pindex) 
    197     {
    198         printf("%s failed! the index in out of bound!
    ", __func__);
    199         return -1;
    200     }
    201 
    202     pindex->next->prev = pindex->prev;
    203     pindex->prev->next = pindex->next;
    204     free(pindex);
    205     count--;
    206 
    207     return 0;
    208 }    
    209 
    210 // 删除第一个节点
    211 int dlink_delete_first() 
    212 {
    213     return dlink_delete(0);
    214 }
    215 
    216 // 删除组后一个节点
    217 int dlink_delete_last() 
    218 {
    219     return dlink_delete(count-1);
    220 }
    221 
    222 // 撤销“双向链表”。成功,返回0;否则,返回-1。
    223 int destroy_dlink()
    224 {
    225     if (!phead)
    226     {
    227         printf("%s failed! dlink is null!
    ", __func__);
    228         return -1;
    229     }
    230 
    231     node *pnode=phead->next;
    232     node *ptmp=NULL;
    233     while(pnode != phead)
    234     {
    235         ptmp = pnode;
    236         pnode = pnode->next;
    237         free(ptmp);
    238     }
    239 
    240     free(phead);
    241     phead = NULL;
    242     count = 0;
    243 
    244     return 0;
    245 }
    View Code

    双向链表的测试程序(dlink_queue.c)

      1 #include <stdio.h>
      2 #include "double_link.h"
      3 
      4 /**
      5  * C 语言: 双向链表实现“队列”,能存储任意数据。
      6  *
      7  * @author skywang
      8  * @date 2013/11/07
      9  */
     10 
     11 // 创建队列
     12 int create_dlink_queue() 
     13 {
     14     return create_dlink();
     15 }
     16 
     17 // 销毁队列
     18 int destroy_dlink_queue() 
     19 {
     20     return destroy_dlink();
     21 }
     22 
     23 // 将p添加到队列的末尾
     24 int add(void *p) 
     25 {
     26     return dlink_append_last(p);
     27 }
     28 
     29 // 返回“队列开头元素”
     30 void* front() 
     31 {
     32     return dlink_get_first();
     33 }
     34 
     35 // 返回“队列开头的元素”,并删除“该元素”
     36 void* pop() 
     37 {
     38     void *p = dlink_get_first();
     39     dlink_delete_first();
     40     return p;
     41 }
     42 
     43 // 返回“队列”的大小
     44 int size() 
     45 {
     46     return dlink_size();
     47 }
     48 
     49 // 返回“队列”是否为空
     50 int is_empty()
     51 {
     52     return dlink_is_empty();
     53 }
     54 
     55 
     56 typedef struct tag_stu
     57 {
     58     int id;
     59     char name[20];
     60 }stu;
     61 
     62 static stu arr_stu[] = 
     63 {
     64     {10, "sky"},
     65     {20, "jody"},
     66     {30, "vic"},
     67     {40, "dan"},
     68 };
     69 #define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) )
     70 
     71 static void print_stu(stu *p) 
     72 {
     73     if (!p)
     74         return ;
     75 
     76     printf("id=%d, name=%s
    ", p->id, p->name);
     77 }
     78 
     79 void main()
     80 {
     81     stu *pval=NULL;
     82 
     83     // 创建“队列”
     84     create_dlink_queue();
     85 
     86     // 将10, 20, 30 依次推入队列中
     87     int i=0;
     88     for (i=0; i<ARR_STU_SIZE-1; i++)
     89     {
     90         add(&arr_stu[i]);
     91     }
     92 
     93     // 将“队列开头的元素”赋值给tmp,并删除“该元素”
     94     pval = (stu*)pop();
     95     print_stu(pval) ;
     96 
     97     // 只将“队列开头的元素”赋值给tmp,不删除该元素.
     98     pval = front();
     99     print_stu(pval) ;
    100 
    101     add(&arr_stu[ARR_STU_SIZE-1]);
    102 
    103     printf("is_empty()=%d
    ", is_empty());
    104     printf("size()=%d
    ", size());
    105     // 打印队列中的所有元素
    106     while (!is_empty())
    107     {
    108         pval = pop();
    109         print_stu(pval) ;
    110     }
    111 
    112     // 销毁队列
    113     destroy_dlink_queue();
    114 }
    View Code

    运行结果

    id=10, name=sky
    id=20, name=jody
    is_empty()=0
    size()=3
    id=20, name=jody
    id=30, name=vic
    id=40, name=dan

    结果说明该示例中的队列是通过双向链表实现的,并且能存储任意类型的数据。

     

    队列的C++实现

    C++的STL中本身就包含了list类,基本上该list类就能满足我们的需求,所以很少需要我们自己来实现。本部分介绍2种C++实现。
    1. C++实现一:数组实现的队列,能存储任意类型的数据。
    2. C++实现二:C++的 STL 中自带的"队列"(list)的示例。

    1. C++实现一:数组实现的队列,能存储任意类型的数据

    实现代码
    队列的实现文件(ArrayQueue.h)

     1 #ifndef ARRAY_QUEUE_HXX
     2 #define ARRAY_QUEUE_HXX
     3 
     4 #include <iostream>
     5 using namespace std;
     6 
     7 template<class T> class ArrayQueue{
     8     public:
     9         ArrayQueue();
    10         ~ArrayQueue();
    11 
    12         void add(T t);
    13         T front();
    14         T pop();
    15         int size();
    16         int is_empty();
    17 
    18     private:
    19         T *arr;
    20         int count;
    21 };
    22 
    23 // 创建“队列”,默认大小是12
    24 template<class T>
    25 ArrayQueue<T>::ArrayQueue() 
    26 {
    27     arr = new T[12];
    28     if (!arr) 
    29     {
    30         cout<<"arr malloc error!"<<endl;
    31     }
    32 }
    33 
    34 // 销毁“队列”
    35 template<class T>
    36 ArrayQueue<T>::~ArrayQueue() 
    37 {
    38     if (arr) 
    39     {
    40         delete[] arr;
    41         arr = NULL;
    42     }
    43 }
    44 
    45 // 将val添加到队列的末尾
    46 template<class T>
    47 void ArrayQueue<T>::add(T t) 
    48 {
    49     arr[count++] = t;
    50 }
    51 
    52 
    53 // 返回“队列开头元素”
    54 template<class T>
    55 T ArrayQueue<T>::front() 
    56 {
    57     return arr[0];
    58 }
    59 
    60 // 返回并删除“队列末尾的元素”
    61 template<class T>
    62 T ArrayQueue<T>::pop() 
    63 {
    64     int i = 0;;
    65     T ret = arr[0];
    66 
    67     count--;
    68     while (i++<count)
    69         arr[i-1] = arr[i];
    70 
    71     return ret;
    72 }
    73 
    74 // 返回“队列”的大小
    75 template<class T>
    76 int ArrayQueue<T>::size() 
    77 {
    78     return count;
    79 }
    80 
    81 // 返回“队列”是否为空
    82 template<class T>
    83 int ArrayQueue<T>::is_empty()
    84 {
    85     return count==0;
    86 }
    87 
    88 
    89 #endif
    View Code

    队列的测试程序(Main.cpp)

     1 #include <iostream>
     2 #include "ArrayQueue.h"
     3 using namespace std;
     4 
     5 /**
     6  * C++ : 数组实现“队列”,能存储任意数据。
     7  *
     8  * @author skywang
     9  * @date 2013/11/07
    10  */
    11 int main() 
    12 {
    13     int tmp=0;
    14     ArrayQueue<int> *astack = new ArrayQueue<int>();
    15 
    16     // 将10, 20, 30 依次推入队列中
    17     astack->add(10);
    18     astack->add(20);
    19     astack->add(30);
    20 
    21     // 将“队列开头元素”赋值给tmp,并删除“该元素”
    22     tmp = astack->pop();
    23     cout<<"tmp="<<tmp<<endl;
    24 
    25     // 只将“队列开头的元素”赋值给tmp,不删除该元素.
    26     tmp = astack->front();
    27     cout<<"tmp="<<tmp<<endl;
    28 
    29     astack->add(40);
    30 
    31     cout<<"is_empty()="<<astack->is_empty()<<endl;
    32     cout<<"size()="<<astack->size()<<endl;
    33     while (!astack->is_empty())
    34     {
    35         tmp = astack->pop();
    36         cout<<tmp<<endl;
    37     }
    38 
    39     return 0;
    40 }
    View Code

    运行结果

    tmp=10
    tmp=20
    is_empty()=0
    size()=3
    20
    30
    40

    结果说明关于"队列的声明和实现都在头文件中"的原因,是因为队列的实现利用了C++模板,而"C++编译器不能支持对模板的分离式编译"。

    2. C++实现二:C++的 STL 中自带的"队列"(list)的示例

    实现代码(StlQueue.cpp)

     1 #include <iostream>
     2 #include <queue>
     3 using namespace std;
     4 
     5 /**
     6  * C++ : STL中的队列(queue)的演示程序。
     7  *
     8  * @author skywang
     9  * @date 2013/11/07
    10  */
    11 int main ()
    12 {
    13     int tmp=0;
    14     queue<int> iqueue;
    15 
    16     // 将10, 20, 30 依次加入队列的末尾
    17     iqueue.push(10);
    18     iqueue.push(20);
    19     iqueue.push(30);
    20 
    21     // 删除队列开头的元素
    22     iqueue.pop();
    23 
    24     // 将“队列开头的元素”赋值给tmp,不删除该元素.
    25     tmp = iqueue.front();
    26     cout<<"tmp="<<tmp<<endl;
    27 
    28     // 将40加入到队列的末尾
    29     iqueue.push(40);
    30 
    31     cout << "empty()=" << iqueue.empty() <<endl;
    32     cout << "size()=" << iqueue.size() <<endl;
    33     while (!iqueue.empty()) 
    34     {
    35         tmp = iqueue.front();
    36         cout<<tmp<<endl;
    37         iqueue.pop();  
    38     }
    39 
    40     return 0;
    41 }
    View Code

    运行结果

    tmp=20
    empty()=0
    size()=3
    20
    30
    40

    队列的Java实现

    和C++一样,JDK包Queue中的也提供了"队列"的实现。JDK中的Queue接口就是"队列",它的实现类也都是队列,用的最多的是LinkedList。本部分介绍给出2种Java实现
    1. Java实现一:数组实现的队列,能存储任意类型的数据。
    2. Java实现二:Java的 Collection集合 中自带的"队列"(LinkedList)的示例。

    1. Java实现一:数组实现的队列,能存储任意类型的数据

    实现代码(ArrayQueue.java)

     1 /**
     2  * Java : 数组实现“队列”,只能存储int数据。
     3  *
     4  * @author skywang
     5  * @date 2013/11/07
     6  */
     7 public class ArrayQueue {
     8 
     9     private int[] mArray;
    10     private int mCount;
    11 
    12     public ArrayQueue(int sz) {
    13         mArray = new int[sz];
    14         mCount = 0;
    15     }
    16 
    17     // 将val添加到队列的末尾
    18     public void add(int val) {
    19         mArray[mCount++] = val;
    20     }
    21 
    22     // 返回“队列开头元素”
    23     public int front() {
    24         return mArray[0];
    25     }
    26 
    27     // 返回“栈顶元素值”,并删除“栈顶元素”
    28     public int pop() {
    29         int ret = mArray[0];
    30         mCount--;
    31         for (int i=1; i<=mCount; i++)
    32             mArray[i-1] = mArray[i];
    33         return ret;
    34     }
    35 
    36     // 返回“栈”的大小
    37     public int size() {
    38         return mCount;
    39     }
    40 
    41     // 返回“栈”是否为空
    42     public boolean isEmpty() {
    43         return size()==0;
    44     }
    45 
    46     public static void main(String[] args) {
    47         int tmp=0;
    48         ArrayQueue astack = new ArrayQueue(12);
    49 
    50         // 将10, 20, 30 依次推入栈中
    51         astack.add(10);
    52         astack.add(20);
    53         astack.add(30);
    54 
    55         // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
    56         tmp = astack.pop();
    57         System.out.printf("tmp=%d
    ", tmp);
    58 
    59         // 只将“栈顶”赋值给tmp,不删除该元素.
    60         tmp = astack.front();
    61         System.out.printf("tmp=%d
    ", tmp);
    62 
    63         astack.add(40);
    64 
    65         System.out.printf("isEmpty()=%b
    ", astack.isEmpty());
    66         System.out.printf("size()=%d
    ", astack.size());
    67         while (!astack.isEmpty()) {
    68             System.out.printf("size()=%d
    ", astack.pop());
    69         }
    70     }
    71 }
    View Code

    运行结果

    tmp=10
    tmp=20
    isEmpty()=false
    size()=3
    size()=20
    size()=30
    size()=40

    结果说明:ArrayQueue是通过数组实现的队列,而且ArrayQueue中使用到了泛型,因此它支持任意类型的数据。

     

    2. Java实现二:Java的 Collection集合 中自带的"队列"(LinkedList)的示例

    实现代码(QueueTest.java)

     1 import java.util.Stack;
     2 
     3 /**
     4  * 用“栈”实现队列
     5  *
     6  * @author skywang
     7  */
     8 public class StackList<T> {
     9 
    10     // 向队列添加数据时:(01) 将“已有的全部数据”都移到mIn中。 (02) 将“新添加的数据”添加到mIn中。
    11     private Stack<T> mIn  = null;
    12     // 从队列获取元素时:(01) 将“已有的全部数据”都移到mOut中。(02) 返回并删除mOut栈顶元素。
    13     private Stack<T> mOut = null;
    14     // 统计计数
    15     private int mCount = 0;
    16 
    17     public StackList() {
    18         mIn = new Stack<T>();
    19         mOut = new Stack<T>();
    20         mCount = 0;
    21     }
    22 
    23     private void add(T t) {
    24         // 将“已有的全部数据”都移到mIn中
    25         while (!mOut.empty())
    26             mIn.push(mOut.pop());
    27 
    28         // 将“新添加的数据”添加到mIn中
    29         mIn.push(t);
    30         // 统计数+1
    31         mCount++;
    32     }
    33 
    34     private T get() {
    35         // 将“已有的全部数据”都移到mOut中
    36         while (!mIn.empty())
    37             mOut.push(mIn.pop());
    38         // 统计数-1
    39         mCount--;
    40 
    41         // 返回并删除mOut栈顶元素
    42         return mOut.pop();
    43     }
    44 
    45     private int size() {
    46         return mCount;
    47     }
    48     private boolean isEmpty() {
    49         return mCount==0;
    50     }
    51 
    52     public static void main(String[] args) {
    53         StackList slist = new StackList();
    54 
    55         // 将10, 20, 30 依次推入栈中
    56         slist.add(10);
    57         slist.add(20);
    58         slist.add(30);
    59 
    60         System.out.printf("isEmpty()=%b
    ", slist.isEmpty());
    61         System.out.printf("size()=%d
    ", slist.size());
    62         while(!slist.isEmpty()) {
    63             System.out.printf("%d
    ", slist.get());
    64         }
    65     }
    66 }
    View Code

    运行结果

    tmp=10
    tmp=20
    isEmpty()=false
    size()=3
    tmp=20
    tmp=30
    tmp=40
  • 相关阅读:
    linux cmake安装方法
    Linux下安装numpy
    linux下安装opencv3.0
    linux升级gcc
    php session获取不到的解决方法
    python Tesseract安装方法
    SQLite-编译指示
    第十章:定积分
    7. 错误、调试和测试
    钱纳里的工业化阶段理论
  • 原文地址:https://www.cnblogs.com/skywang12345/p/3562279.html
Copyright © 2020-2023  润新知