开发步骤:

  1. 建立抽象 自然语言描述

  2. 建立接口 queue.h 编写类型的定义、结构体的定义、宏的定义、函数声明、include等内容

  3. 实现接口 queue.c 编写函数的实现

  4. 使用接口 main.c list的使用

      5. 编译过程

               编译环境 : unix 、linux

     方法 1 :gcc main.c queue.c 生成的可执行文件为a.out

               方法 2 :  gcc -o main main.c queue.c ;./main 生成指定名称的可执行文件main

               注意事项 : 三个文件要放在同一文件夹内编译

 

1.queue.h

/*    queue.h -- Queue的接口*/
#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <stdbool.h> /*    提供bool的定义*/

//    Item类型的定义
typedef int Item;
// typedef struct item {int gumption; int charisma;} Item;

#define MAXQUEUE 10

typedef struct node
{
    Item item;
    struct node * next;
} Node;

typedef struct queue 
{
    Node * front; /*    指向队列首项的指针*/
    Node * rear; /*    指向队列尾项的指针*/
    int items; /* 队列中的项数*/
} Queue;

/*    操作: 初始化队列    */
/*    前提条件:      pq指向一个队列 */
/*    后置条件:  队列被初始化为空 */
void InitializeQueue(Queue * pq);

/*    操作:    检查队列是否已满*/
/*    前提条件: pq指向之前被初始化的队列    */
/*    后置条件: 如果队列已满则返回true,否则返回false*/
bool QueueIsFull(const Queue * pq);

/*    操作:检查队列是否为空    */
/*    前提条件: pq指向之前被初始化的队列 */
/*    后置条件: 如果队列为空则返回true,否则返回false*/
bool QueueIsEmpty(const Queue * pq);

/*    操作:确定队列中的项数*/
/*    前提条件: pq指向之前被初始化的队列 */
/*    后置条件:     返回队列中的项数*/
int QueueItemCount(const Queue * pq);

/*    操作:在队列末尾添加项*/
/*    前提条件: pq指向之前被初始化的队列
    item是要被添加在队列末尾的项 */
/*    后置条件: 如果队列不为空,item将被添加在队列末尾,
            该函数返回true;否则,队列不改变,该函数返回false*/
bool Enqueue(Item item, Queue * pq);

/*    操作: 从队列的开头删除项*/
/*    前提条件: pq指向之前被初始化的队列*/
/*    后置条件:     如果队列不为空,队列首端的item将被拷贝到*pitem中 
             并被删除,且函数返回true;
             如果该操作时的队列为空,则重置队列为空
             如果队列在操作前为空,则函数返回false */
bool DeQueue(Item *pitem, Queue * pq);

/*    操作: 清空队列 */
/*    前提条件: pq指向之前被初始化的队列*/
/*    后置条件: 队列被清空*/
void EmptyTheQueue(Queue * pq);

/*    操作: 打印队列*/
/*    前提条件:     pq指向之前被初始化的队列*/
void Echo(Queue * pq);


#endif

2.queue.c

/*    queue.c -- Queue类型的实现    */
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"

/* 局部函数 */
static void CopyToNode(Item item, Node * pn);
static void CopyToItem(Node * pn, Item * pi);

/*    接口方法实现 */

/*    操作: 初始化队列    */
/*    前提条件:      pq指向一个队列 */
/*    后置条件:  队列被初始化为空 */
void InitializeQueue(Queue * pq)
{
    pq->front = pq->rear = NULL;
    pq->items = 0;
}

/*    操作:    检查队列是否已满*/
/*    前提条件: pq指向之前被初始化的队列    */
/*    后置条件: 如果队列已满则返回true,否则返回false*/
bool QueueIsFull(const Queue * pq)
{
    return pq->items == MAXQUEUE;
}

/*    操作:检查队列是否为空    */
/*    前提条件: pq指向之前被初始化的队列 */
/*    后置条件: 如果队列为空则返回true,否则返回false*/
bool QueueIsEmpty(const Queue * pq)
{
    return pq->items == 0;
}

/*    操作:确定队列中的项数*/
/*    前提条件: pq指向之前被初始化的队列 */
/*    后置条件:     返回队列中的项数*/
int QueueItemCount(const Queue * pq)
{
    return pq->items;
}

/*    操作:在队列末尾添加项*/
/*    前提条件: pq指向之前被初始化的队列
    item是要被添加在队列末尾的项 */
/*    后置条件: 如果队列不为空,item将被添加在队列末尾,
            该函数返回true;否则,队列不改变,该函数返回false*/
bool Enqueue(Item item, Queue * pq)
{
    Node * pnew;

    if (QueueIsFull(pq))
        return false;
    pnew = (Node *) malloc(sizeof(Node));
    if (pnew == NULL)
    {
        fprintf(stderr, "Unable to allocate memory!\n" );
        exit(1);
    }
    CopyToNode(item, pnew);
    pnew->next =NULL;
    if (QueueIsEmpty(pq))
        pq->front = pnew; /*    项位于队列的首端*/
    else
        pq->rear->next = pnew; /*    链接到队列的尾端*/
    pq->rear = pnew; /*    记录队列尾端的位置*/
    pq->items++; /*    队列的项数加1*/

    return true;

}

/*    操作: 从队列的开头删除项*/
/*    前提条件: pq指向之前被初始化的队列*/
/*    后置条件:     如果队列不为空,队列首端的item将被拷贝到*pitem中 
             并被删除,且函数返回true;
             如果该操作时的队列为空,则重置队列为空
             如果队列在操作前为空,则函数返回false */
bool DeQueue(Item *pitem, Queue * pq)
{
    Node * pt;

    if (QueueIsEmpty(pq))
        return false;
    CopyToItem(pq->front,pitem);
    pt = pq->front;
    pq->front = pq->front->next;
    free(pt);
    pq->items--;
    if (pq->items == 0)
        pq->rear = NULL;

    return true;
}

/*    操作: 清空队列 */
/*    前提条件: pq指向之前被初始化的队列*/
/*    后置条件: 队列被清空*/
void EmptyTheQueue(Queue * pq)
{
    Item dummy;
    while (!QueueIsEmpty(pq))
        DeQueue(&dummy, pq);
}

/*    操作: 打印队列*/
/*    前提条件:     pq指向之前被初始化的队列*/
void Echo(Queue * pq)
{
    if (QueueIsEmpty(pq))
        puts("当前队列为空.");
    else
    {
        puts("打印当前队列元素(front->rear):");
        Node * newpt = pq->front;
        while (newpt != NULL)
        {
            printf("\t当前队列元素:%d\n", newpt->item );
            newpt = newpt->next;
        }
    }

}

/*    局部函数*/
static void CopyToNode(Item item, Node * pn)
{
    pn->item = item;
}

static void CopyToItem(Node * pn, Item * pi)
{
    *pi = pn->item;
}

3.main.c

/*  use_q.c -- 驱动程序测试 Queue 接口 */
/*  与 queue.c 一起编译 */
#include <stdio.h>
#include "queue.h" /* 定义 Queue、Item*/

void Test1();

int main(void)
{
  //Test1();
  Queue line;

  //初始化
  InitializeQueue(&line);
  //添加元素
  Enqueue(10,&line);
  Enqueue(9,&line);
  Enqueue(8,&line);
  Enqueue(7,&line);

  //查看当前元素
  Echo(&line);

  //删除一个元素
  int d;
  DeQueue(&d,&line);
  printf("被删除的元素是:%d\n", d );

  //查看当前元素
  Echo(&line);

  //判断队列是否为空
  bool isEmpty = QueueIsEmpty(&line);
  printf("当前队列是否为空:%d\n", isEmpty );

  //判断队列是否已满
  bool isFull = QueueIsFull(&line);
  printf("当前队列是否已满:%d\n", isFull );

  //添加元素
  Enqueue(6,&line);
  Enqueue(5,&line);
  Enqueue(4,&line);
  Enqueue(3,&line);
  Enqueue(2,&line);
  Enqueue(1,&line);
  Enqueue(0,&line);
  Enqueue(100,&line);

  //查看当前元素
  Echo(&line);

  //判断队列是否已满
  isFull = QueueIsFull(&line);
  printf("当前队列是否已满:%d\n", isFull );

  //查看当前节点数量
  int size = QueueItemCount(&line);
  printf("当前队列的节点数量:%d\n", size );

  //清空队列
  EmptyTheQueue(&line);

  return 0;
}

/*  测试1*/
void Test1()
{
  Queue line;
  Item temp;
  char ch;

  InitializeQueue(&line);
  puts("Testing the Queue interface. Type a to add a value,");
  puts("type d to delete a value, and type q to quit.");
  while ((ch = getchar()) != 'q')
  {
      if(ch != 'a' && ch != 'd') /* 忽略其他输出*/
           continue;
      if (ch == 'a')
      {
          printf("Integer to add:" );
          scanf("%d", &temp);
          if (!QueueIsFull(&line))
          {
              printf("Putting %d into queue\n", temp );
              Enqueue(temp, &line);
          }
          else
              puts("Queue is full");
      }
      else
      {
          if (QueueIsEmpty(&line))
              puts("Nothing to delete!");
          else
          {
              DeQueue(&temp, &line);
              printf("Removing %d from queue\n", temp );
          }      
      }
      printf("%d items in queue\n", QueueItemCount(&line) );
      puts("Type a to add, d to delete, q to quit:"); 
  }
  Echo(&line);
  EmptyTheQueue(&line);
  puts("Bye!");  
}