queue

来源:互联网 发布:朱慈勉 知乎 编辑:程序博客网 时间:2024/06/04 18:08

1.顺序队列

头文件

#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() *//* 函数结果状态代码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef int ElemType;/* c3-3.h 队列的顺序存储结构(可用于循环队列和非循环队列) */#define MAXQSIZE 5 /* 最大队列长度(对于循环队列,最大队列长度要减1) */typedef struct{ElemType *base; /* 初始化的动态分配存储空间 */int front; /* 头指针,若队列不空,指向队列头元素 */int rear; /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */}queue;Status create(queue *Q);Status destroy(queue *Q);Status clear(queue *Q);Status empty(queue Q);int size(queue Q);ElemType front(queue Q);Status push(queue *Q, ElemType e);Status pop(queue *Q);Status traverse(queue Q, void(*vi)(ElemType));

实现文件

/* bo3-4.c 顺序队列(非循环,存储结构由c3-3.h定义)的基本操作(9个) */#include "queue.h"Status create(queue *Q){ /* 构造一个空队列Q */(*Q).base = (ElemType *)malloc(MAXQSIZE*sizeof(ElemType));if (!(*Q).base) /* 存储分配失败 */exit(OVERFLOW);(*Q).front = (*Q).rear = 0;return OK;}Status destroy(queue *Q){ /* 销毁队列Q,Q不再存在 */if ((*Q).base)free((*Q).base);(*Q).base = NULL;(*Q).front = (*Q).rear = 0;return OK;}Status clear(queue *Q){ /* 将Q清为空队列 */(*Q).front = (*Q).rear = 0;return OK;}Status empty(queue Q){ /* 若队列Q为空队列,则返回TRUE,否则返回FALSE */if (Q.front == Q.rear) /* 队列空的标志 */return TRUE;elsereturn FALSE;}int size(queue Q){ /* 返回Q的元素个数,即队列的长度 */return(Q.rear - Q.front);}ElemType front(queue Q){ /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */if (Q.front == Q.rear) /* 队列空 */return ERROR;return *(Q.base + Q.front);}Status push(queue *Q, ElemType e){ /* 插入元素e为Q的新的队尾元素 */if ((*Q).rear >= MAXQSIZE){ /* 队列满,增加1个存储单元 */(*Q).base = (ElemType *)realloc((*Q).base, ((*Q).rear + 1)*sizeof(ElemType));if (!(*Q).base) /* 增加单元失败 */return ERROR;}*((*Q).base + (*Q).rear) = e;(*Q).rear++;return OK;}Status pop(queue *Q){ /* 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */if ((*Q).front == (*Q).rear) /* 队列空 */return ERROR;(*Q).front = (*Q).front + 1;return OK;}Status traverse(queue Q, void(*vi)(ElemType)){ /* 从队头到队尾依次对队列Q中每个元素调用函数vi()。一旦vi失败,则操作失败 */int i;i = Q.front;while (i != Q.rear){vi(*(Q.base + i));i++;}printf("\n");return OK;}

测试文件一

#include "queue.h"void visit(ElemType i){printf("%d ", i);}void main(){Status j;int i, n;ElemType d;queue Q;create(&Q);printf("初始化队列后,队列空否?%u(1:空 0:否)\n", empty(Q));printf("队列长度为:%d\n", size(Q));printf("请输入队列元素个数n: ");scanf("%d", &n);printf("请输入%d个整型队列元素:\n", n);for (i = 0; i<n; i++){scanf("%d", &d);push(&Q, d);}printf("队列长度为:%d\n", size(Q));printf("现在队列空否?%u(1:空 0:否)\n", empty(Q));printf("现在队列中的元素为: \n");traverse(Q, visit);d = front(Q);printf("删除队头元素%d\n", d);printf("队列中的元素为: \n");traverse(Q, visit);d = front(Q);printf("队头元素为: %d\n", d);clear(&Q);printf("清空队列后, 队列空否?%u(1:空 0:否)\n", empty(Q));d = front(Q);printf("队头元素为: %d\n", d);destroy(&Q);}

2.链队列

头文件

#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() *//* 函数结果状态代码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef int ElemType;typedef struct QNode{ElemType data;struct QNode *next;}QNode, *QueuePtr;typedef struct{QueuePtr front, rear; /* 队头、队尾指针 */}LinkQueue;Status create(LinkQueue *Q);Status destroy(LinkQueue *Q);Status clear(LinkQueue *Q);Status empty(LinkQueue Q);int size(LinkQueue Q);ElemType front(LinkQueue Q);Status push(LinkQueue *Q, ElemType e);Status pop(LinkQueue *Q);Status traverse(LinkQueue Q, void(*vi)(ElemType));

实现文件

/* bo3-2.c 链队列(存储结构由c3-2.h定义)的基本操作(9个) */#include "queueLink.h"Status create(LinkQueue *Q){ /* 构造一个空队列Q */(*Q).front = (*Q).rear = (QueuePtr)malloc(sizeof(QNode));if (!(*Q).front)exit(OVERFLOW);(*Q).front->next = NULL;return OK;}Status destroy(LinkQueue *Q){ /* 销毁队列Q(无论空否均可) */while ((*Q).front){(*Q).rear = (*Q).front->next;free((*Q).front);(*Q).front = (*Q).rear;}return OK;}Status clear(LinkQueue *Q){ /* 将Q清为空队列 */QueuePtr p, q;(*Q).rear = (*Q).front;p = (*Q).front->next;(*Q).front->next = NULL;while (p){q = p;p = p->next;free(q);}return OK;}Status empty(LinkQueue Q){ /* 若Q为空队列,则返回TRUE,否则返回FALSE */if (Q.front == Q.rear)return TRUE;elsereturn FALSE;}int size(LinkQueue Q){ /* 求队列的长度 */int i = 0;QueuePtr p;p = Q.front;while (Q.rear != p){i++;p = p->next;}return i;}ElemType front(LinkQueue Q) /* 避免与bo2-6.c重名 */{ /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */QueuePtr p;if (Q.front == Q.rear)exit(0);p = Q.front->next;return p->data;}Status push(LinkQueue *Q, ElemType e){ /* 插入元素e为Q的新的队尾元素 */QueuePtr p = (QueuePtr)malloc(sizeof(QNode));if (!p) /* 存储分配失败 */exit(OVERFLOW);p->data = e;p->next = NULL;(*Q).rear->next = p;(*Q).rear = p;return OK;}Status pop(LinkQueue *Q){ /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */QueuePtr p;if ((*Q).front == (*Q).rear)return ERROR;p = (*Q).front->next;(*Q).front->next = p->next;if ((*Q).rear == p)(*Q).rear = (*Q).front;free(p);return OK;}Status traverse(LinkQueue Q, void(*vi)(ElemType)){ /* 从队头到队尾依次对队列Q中每个元素调用函数vi()。一旦vi失败,则操作失败 */QueuePtr p;p = Q.front->next;while (p){vi(p->data);p = p->next;}printf("\n");return OK;}

测试文件一

#include "queueLink.h"void visit(ElemType i){printf("%d ", i);}void main(){int i;ElemType d;LinkQueue q;i = create(&q);if (i)printf("成功地构造了一个空队列!\n");printf("是否空队列?%d(1:空 0:否)  ", empty(q));printf("队列的长度为%d\n", size(q));push(&q, -5);push(&q, 5);push(&q, 10);printf("插入3个元素(-5,5,10)后,队列的长度为%d\n", size(q));printf("是否空队列?%d(1:空 0:否)  ", empty(q));printf("队列的元素依次为:");traverse(q, visit);d = front(q);printf("队头元素是:%d\n", d);d = front(q);  pop(&q);printf("删除了队头元素%d\n", d);d = front(q);printf("新的队头元素是:%d\n", d);clear(&q);printf("清空队列后,q.front=%u q.rear=%u q.front->next=%u\n", q.front, q.rear, q.front->next);destroy(&q);printf("销毁队列后,q.front=%u q.rear=%u\n", q.front, q.rear);}

循环队列

头文件

#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() *//* 函数结果状态代码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef int ElemType;/* c3-3.h 队列的顺序存储结构(可用于循环队列和非循环队列) */#define MAXQSIZE 5 /* 最大队列长度(对于循环队列,最大队列长度要减1) */typedef struct{ElemType *base; /* 初始化的动态分配存储空间 */int front; /* 头指针,若队列不空,指向队列头元素 */int rear; /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */}queue;Status create(queue *Q);Status destroy(queue *Q);Status clear(queue *Q);Status empty(queue Q);int size(queue Q);ElemType front(queue Q);Status push(queue *Q, ElemType e);Status pop(queue *Q);Status traverse(queue Q, void(*vi)(ElemType));

实现文件

#include "cirQueue.h"Status create(queue *Q){ /* 构造一个空队列Q */(*Q).base = (ElemType *)malloc(MAXQSIZE*sizeof(ElemType));if (!(*Q).base) /* 存储分配失败 */exit(OVERFLOW);(*Q).front = (*Q).rear = 0;return OK;}Status destroy(queue *Q){ /* 销毁队列Q,Q不再存在 */if ((*Q).base)free((*Q).base);(*Q).base = NULL;(*Q).front = (*Q).rear = 0;return OK;}Status clear(queue *Q){ /* 将Q清为空队列 */(*Q).front = (*Q).rear = 0;return OK;}Status empty(queue Q){ /* 若队列Q为空队列,则返回TRUE,否则返回FALSE */if (Q.front == Q.rear) /* 队列空的标志 */return TRUE;elsereturn FALSE;}int size(queue Q){ /* 返回Q的元素个数,即队列的长度 */return(Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;}ElemType front(queue Q){ /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */if (Q.front == Q.rear) /* 队列空 */exit(0);return  *(Q.base + Q.front);}Status push(queue *Q, ElemType e){ /* 插入元素e为Q的新的队尾元素 */if (((*Q).rear + 1) % MAXQSIZE == (*Q).front) /* 队列满 */return ERROR;(*Q).base[(*Q).rear] = e;(*Q).rear = ((*Q).rear + 1) % MAXQSIZE;return OK;}Status pop(queue *Q){ /* 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR */if ((*Q).front == (*Q).rear) /* 队列空 */return ERROR;(*Q).front = ((*Q).front + 1) % MAXQSIZE;return OK;}Status traverse(queue Q, void(*vi)(ElemType)){ /* 从队头到队尾依次对队列Q中每个元素调用函数vi().一旦vi失败,则操作失败 */int i;i = Q.front;while (i != Q.rear){vi(*(Q.base + i));i = (i + 1) % MAXQSIZE;}printf("\n");return OK;}

测试文件一
#include "cirQueue.h"void visit(ElemType i){printf("%d ", i);}void main(){Status j;int i = 0, l;ElemType d;queue Q;create(&Q);printf("初始化队列后,队列空否?%u(1:空 0:否)\n", empty(Q));printf("请输入整型队列元素(不超过%d个),-1为提前结束符: ", MAXQSIZE - 1);do{scanf("%d", &d);if (d == -1)break;i++;push(&Q, d);} while (i<MAXQSIZE - 1);printf("队列长度为: %d\n", size(Q));printf("现在队列空否?%u(1:空 0:否)\n", empty(Q));printf("连续%d次由队头删除元素,队尾插入元素:\n", MAXQSIZE);for (l = 1; l <= MAXQSIZE; l++){d = front(Q);pop(&Q);printf("删除的元素是%d,请输入待插入的元素: ", d);scanf("%d", &d);push(&Q, d);}l = size(Q);printf("现在队列中的元素为: \n");traverse(Q, visit);printf("共向队尾插入了%d个元素\n", i + MAXQSIZE);if (l - 2>0)printf("现在由队头删除%d个元素:\n", l - 2);while (size(Q)>2){d = front(Q);pop(&Q);printf("删除的元素值为%d\n", d);}d = front(Q);printf("现在队头元素为: %d\n", d);clear(&Q);printf("清空队列后, 队列空否?%u(1:空 0:否)\n", empty(Q));destroy(&Q);}
队列的应用一,模拟银行排队

头文件LinkList.h

#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() *//* 函数结果状态代码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef struct /* 定义ElemType为结构体类型 */{int OccurTime; /* 事件发生时刻 */int NType; /* 事件类型,Qu表示到达事件,0至Qu-1表示Qu个窗口的离开事件 */}Event, ElemType; /* 事件类型,有序链表LinkList的数据元素类型 *//* c2-5.h 带头结点的线性链表类型 */typedef struct LNode /* 结点类型 */{ElemType data;struct LNode *next;}LNode, *Link, *Position;typedef struct LinkList /* 链表类型 */{Link head, tail; /* 分别指向线性链表中的头结点和最后一个结点 */int len; /* 指示线性链表中数据元素的个数 */}LinkList;typedef LinkList EventList; /* 事件链表类型,定义为有序链表 */Status MakeNode(Link *p, ElemType e);void FreeNode(Link *p);Status InitList(LinkList *L);Status ClearList(LinkList *L);Status DestroyList(LinkList *L);Status InsFirst(LinkList *L, Link h, Link s);Status DelFirst(LinkList *L, Link h, Link *q);Status Append(LinkList *L, Link s);Position PriorPos(LinkList L, Link p);Status Remove(LinkList *L, Link *q);Status InsBefore(LinkList *L, Link *p, Link s);Status InsAfter(LinkList *L, Link *p, Link s);Status SetCurElem(Link p, ElemType e);ElemType GetCurElem(Link p);Status ListEmpty(LinkList L);int ListLength(LinkList L);Position GetHead(LinkList L);Position GetLast(LinkList L);Position NextPos(Link p);Status LocatePos(LinkList L, int i, Link *p);Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));Status ListTraverse(LinkList L, void(*visit)(ElemType));Status OrderInsert(LinkList *L, ElemType e, int(*comp)(ElemType, ElemType));Status LocateElemP(LinkList L, ElemType e, Position *q, int(*compare)(ElemType, ElemType));

头文件queueLink1.h

#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() *//* 函数结果状态代码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef struct{int ArrivalTime; /* 到达时刻 */int Duration; /* 办理事务所需时间 */}QElemType; /* 定义QElemType(队列的数据元素类型)为结构体类型; */typedef struct QNode{QElemType data;struct QNode *next;}QNode, *QueuePtr;typedef struct{QueuePtr front, rear; /* 队头、队尾指针 */}LinkQueue;Status InitQueue(LinkQueue *Q);Status DestroyQueue(LinkQueue *Q);Status ClearQueue(LinkQueue *Q);Status QueueEmpty(LinkQueue Q);int QueueLength(LinkQueue Q);Status GetHead_Q(LinkQueue Q, QElemType *e);Status EnQueue(LinkQueue *Q, QElemType e);Status DeQueue(LinkQueue *Q, QElemType *e);Status QueueTraverse(LinkQueue Q, void(*vi)(QElemType));

实现文件

#include "LinkList.h"/* bo2-6.c 具有实用意义的线性链表(存储结构由c2-5.h定义)的24个基本操作 */Status MakeNode(Link *p, ElemType e){ /* 分配由p指向的值为e的结点,并返回OK;若分配失败。则返回ERROR */*p = (Link)malloc(sizeof(LNode));if (!*p)return ERROR;(*p)->data = e;return OK;}void FreeNode(Link *p){ /* 释放p所指结点 */free(*p);*p = NULL;}Status InitList(LinkList *L){ /* 构造一个空的线性链表 */Link p;p = (Link)malloc(sizeof(LNode)); /* 生成头结点 */if (p){p->next = NULL;(*L).head = (*L).tail = p;(*L).len = 0;return OK;}elsereturn ERROR;}Status ClearList(LinkList *L){ /* 将线性链表L重置为空表,并释放原链表的结点空间 */Link p, q;if ((*L).head != (*L).tail)/* 不是空表 */{p = q = (*L).head->next;(*L).head->next = NULL;while (p != (*L).tail){p = q->next;free(q);q = p;}free(q);(*L).tail = (*L).head;(*L).len = 0;}return OK;}Status DestroyList(LinkList *L){ /* 销毁线性链表L,L不再存在 */ClearList(L); /* 清空链表 */FreeNode(&(*L).head);(*L).tail = NULL;(*L).len = 0;return OK;}Status InsFirst(LinkList *L, Link h, Link s) /* 形参增加L,因为需修改L */{ /* h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前 */s->next = h->next;h->next = s;if (h == (*L).tail) /* h指向尾结点 */(*L).tail = h->next; /* 修改尾指针 */(*L).len++;return OK;}Status DelFirst(LinkList *L, Link h, Link *q) /* 形参增加L,因为需修改L */{ /* h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。 *//* 若链表为空(h指向尾结点),q=NULL,返回FALSE */*q = h->next;if (*q) /* 链表非空 */{h->next = (*q)->next;if (!h->next) /* 删除尾结点 */(*L).tail = h; /* 修改尾指针 */(*L).len--;return OK;}elsereturn FALSE; /* 链表空 */}Status Append(LinkList *L, Link s){ /* 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的 *//* 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新 *//* 的尾结点 */int i = 1;(*L).tail->next = s;while (s->next){s = s->next;i++;}(*L).tail = s;(*L).len += i;return OK;}Position PriorPos(LinkList L, Link p){ /* 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置 *//* 若无前驱,则返回NULL */Link q;q = L.head->next;if (q == p) /* 无前驱 */return NULL;else{while (q->next != p) /* q不是p的直接前驱 */q = q->next;return q;}}Status Remove(LinkList *L, Link *q){ /* 删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点 */Link p = (*L).head;if ((*L).len == 0) /* 空表 */{*q = NULL;return FALSE;}while (p->next != (*L).tail)p = p->next;*q = (*L).tail;p->next = NULL;(*L).tail = p;(*L).len--;return OK;}Status InsBefore(LinkList *L, Link *p, Link s){ /* 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前, *//* 并修改指针p指向新插入的结点 */Link q;q = PriorPos(*L, *p); /* q是p的前驱 */if (!q) /* p无前驱 */q = (*L).head;s->next = *p;q->next = s;*p = s;(*L).len++;return OK;}Status InsAfter(LinkList *L, Link *p, Link s){ /* 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后, *//* 并修改指针p指向新插入的结点 */if (*p == (*L).tail) /* 修改尾指针 */(*L).tail = s;s->next = (*p)->next;(*p)->next = s;*p = s;(*L).len++;return OK;}Status SetCurElem(Link p, ElemType e){ /* 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值 */p->data = e;return OK;}ElemType GetCurElem(Link p){ /* 已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值 */return p->data;}Status ListEmpty(LinkList L){ /* 若线性链表L为空表,则返回TRUE,否则返回FALSE */if (L.len)return FALSE;elsereturn TRUE;}int ListLength(LinkList L){ /* 返回线性链表L中元素个数 */return L.len;}Position GetHead(LinkList L){ /* 返回线性链表L中头结点的位置 */return L.head;}Position GetLast(LinkList L){ /* 返回线性链表L中最后一个结点的位置 */return L.tail;}Position NextPos(Link p){ /* 已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置 *//* 若无后继,则返回NULL */return p->next;}Status LocatePos(LinkList L, int i, Link *p){ /* 返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR *//* i=0为头结点 */int j;if (i<0 || i>L.len)return ERROR;else{*p = L.head;for (j = 1; j <= i; j++)*p = (*p)->next;return OK;}}Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType)){ /* 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置, *//* 若不存在这样的元素,则返回NULL */Link p = L.head;dop = p->next;while (p&&!(compare(p->data, e))); /* 没到表尾且没找到满足关系的元素 */return p;}Status ListTraverse(LinkList L, void(*visit)(ElemType)){ /* 依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败 */Link p = L.head->next;int j;for (j = 1; j <= L.len; j++){visit(p->data);p = p->next;}printf("\n");return OK;}Status OrderInsert(LinkList *L, ElemType e, int(*comp)(ElemType, ElemType)){ /* 已知L为有序线性链表,将元素e按非降序插入在L中。(用于一元多项式) */Link o, p, q;q = (*L).head;p = q->next;while (p != NULL&&comp(p->data, e)<0) /* p不是表尾且元素值小于e */{q = p;p = p->next;}o = (Link)malloc(sizeof(LNode)); /* 生成结点 */o->data = e; /* 赋值 */q->next = o; /* 插入 */o->next = p;(*L).len++; /* 表长加1 */if (!p) /* 插在表尾 */(*L).tail = o; /* 修改尾结点 */return OK;}Status LocateElemP(LinkList L, ElemType e, Position *q, int(*compare)(ElemType, ElemType)){ /* 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中 *//* 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数 *//* compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式) */Link p = L.head, pp;do{pp = p;p = p->next;} while (p && (compare(p->data, e)<0)); /* 没到表尾且p->data.expn<e.expn */if (!p || compare(p->data, e)>0) /* 到表尾或compare(p->data,e)>0 */{*q = pp;return FALSE;}else /* 找到 */{*q = p;return TRUE;}}

/* bo3-2.c 链队列(存储结构由c3-2.h定义)的基本操作(9个) */#include "queueLink1.h"/* bo3-2.c 链队列(存储结构由c3-2.h定义)的基本操作(9个) */Status InitQueue(LinkQueue *Q){ /* 构造一个空队列Q */(*Q).front = (*Q).rear = (QueuePtr)malloc(sizeof(QNode));if (!(*Q).front)exit(OVERFLOW);(*Q).front->next = NULL;return OK;}Status DestroyQueue(LinkQueue *Q){ /* 销毁队列Q(无论空否均可) */while ((*Q).front){(*Q).rear = (*Q).front->next;free((*Q).front);(*Q).front = (*Q).rear;}return OK;}Status ClearQueue(LinkQueue *Q){ /* 将Q清为空队列 */QueuePtr p, q;(*Q).rear = (*Q).front;p = (*Q).front->next;(*Q).front->next = NULL;while (p){q = p;p = p->next;free(q);}return OK;}Status QueueEmpty(LinkQueue Q){ /* 若Q为空队列,则返回TRUE,否则返回FALSE */if (Q.front == Q.rear)return TRUE;elsereturn FALSE;}int QueueLength(LinkQueue Q){ /* 求队列的长度 */int i = 0;QueuePtr p;p = Q.front;while (Q.rear != p){i++;p = p->next;}return i;}Status GetHead_Q(LinkQueue Q, QElemType *e) /* 避免与bo2-6.c重名 */{ /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */QueuePtr p;if (Q.front == Q.rear)return ERROR;p = Q.front->next;*e = p->data;return OK;}Status EnQueue(LinkQueue *Q, QElemType e){ /* 插入元素e为Q的新的队尾元素 */QueuePtr p = (QueuePtr)malloc(sizeof(QNode));if (!p) /* 存储分配失败 */exit(OVERFLOW);p->data = e;p->next = NULL;(*Q).rear->next = p;(*Q).rear = p;return OK;}Status DeQueue(LinkQueue *Q, QElemType *e){ /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */QueuePtr p;if ((*Q).front == (*Q).rear)return ERROR;p = (*Q).front->next;*e = p->data;(*Q).front->next = p->next;if ((*Q).rear == p)(*Q).rear = (*Q).front;free(p);return OK;}Status QueueTraverse(LinkQueue Q, void(*vi)(QElemType)){ /* 从队头到队尾依次对队列Q中每个元素调用函数vi()。一旦vi失败,则操作失败 */QueuePtr p;p = Q.front->next;while (p){vi(p->data);p = p->next;}printf("\n");return OK;}

主程序

/* algo3-12.c 银行业务模拟。实现算法3.6、3.7的程序 */#define Qu 4 /* 客户队列数 */#define Khjg 5 /* 两相邻到达的客户的时间间隔最大值 */#define Blsj 30 /* 每个客户办理业务的时间最大值 */#include "LinkList.h"#include "queueLink1.h"/* 程序中用到的主要变量(全局)。算法3.7 */EventList ev; /* 事件表 */Event en; /* 事件 */Event et; /* 临时变量 */LinkQueue q[Qu]; /* Qu个客户队列 */QElemType customer; /* 客户记录 */int TotalTime = 0, CustomerNum = 0; /* 累计客户逗留时间,客户数(初值为0) */int CloseTime; /* 银行营业时间(单位是分) */int cmp(Event a, Event b){ /* 依事件a的发生时刻<、=或>事件b的发生时刻分别返回-1、0或1 */if (a.OccurTime == b.OccurTime)return 0;elsereturn (a.OccurTime - b.OccurTime) / abs(a.OccurTime - b.OccurTime);}void OpenForDay(){ /* 初始化操作 */int i;InitList(&ev); /* 初始化事件链表为空 */en.OccurTime = 0; /* 设定第一个客户到达事件 */en.NType = Qu; /* 到达 */OrderInsert(&ev, en, cmp); /* 插入事件表 */for (i = 0; i<Qu; ++i) /* 置空队列 */InitQueue(&q[i]);}void Random(int *d, int *i){*d = rand() % Blsj + 1; /* 1到Blsj之间的随机数 */*i = rand() % Khjg + 1; /* 1到Khjg之间的随机数 */}int Minimum(LinkQueue Q[]) /* 返回最短队列的序号 */{int l[Qu];int i, k;for (i = 0; i<Qu; i++)l[i] = QueueLength(Q[i]);k = 0;for (i = 1; i<Qu; i++)if (l[i]<l[0]){l[0] = l[i];k = i;}return k;}void CustomerArrived(){ /* 处理客户到达事件,en.NType=Qu */QElemType f;int durtime, intertime, i;++CustomerNum;Random(&durtime, &intertime); /* 生成随机数 */et.OccurTime = en.OccurTime + intertime; /* 下一客户到达时刻 */et.NType = Qu; /* 队列中只有一个客户到达事件 */if (et.OccurTime<CloseTime) /* 银行尚未关门,插入事件表 */OrderInsert(&ev, et, cmp);i = Minimum(q); /* 求长度最短队列的序号,等长为最小的序号 */f.ArrivalTime = en.OccurTime;f.Duration = durtime;EnQueue(&q[i], f);if (QueueLength(q[i]) == 1){et.OccurTime = en.OccurTime + durtime;et.NType = i;OrderInsert(&ev, et, cmp); /* 设定第i队列的一个离开事件并插入事件表 */}}void CustomerDeparture(){ /* 处理客户离开事件,en.NTyPe<Qu */int i;i = en.NType;DeQueue(&q[i], &customer); /* 删除第i队列的排头客户 */TotalTime += en.OccurTime - customer.ArrivalTime; /* 累计客户逗留时间 */if (!QueueEmpty(q[i])){ /* 设定第i队列的一个离开事件并插入事件表 */GetHead_Q(q[i], &customer);et.OccurTime = en.OccurTime + customer.Duration;et.NType = i;OrderInsert(&ev, et, cmp);}}void Bank_Simulation(){Link p;OpenForDay(); /* 初始化 */while (!ListEmpty(ev)){DelFirst(&ev, GetHead(ev), &p);en.OccurTime = GetCurElem(p).OccurTime;en.NType = GetCurElem(p).NType;if (en.NType == Qu)CustomerArrived(); /* 处理客户到达事件 */elseCustomerDeparture(); /* 处理客户离开事件 */} /* 计算并输出平均逗留时间 */printf("顾客总数:%d, 所有顾客共耗时:%d分钟, 平均每人耗时: %d分钟\n", CustomerNum, TotalTime, TotalTime / CustomerNum);}void main(){printf("请输入银行营业时间长度(单位:分)\n");scanf("%d", &CloseTime);Bank_Simulation();}


0 0