数据结构课程设计报告
题目:银行业务活动的模拟
学生姓名:赖锡宏
学
号:1021112513
班 级: 10211125
指导教师:高永平
2012 年 6 月 15 日
计算机与信息技术学院综合性、设计性实验报告
数据结构
专业:计算机科学与技术 年级/班级:
课程名称
本组成员
学号姓名
实验地点
项目名称
银行业务模拟系统的设计与实现
指导教师
实验时间
实验类型 综合性/设计性
一、实验目的
1)通过实验掌握对离散事件模拟的认识;
2)进一步理解队列的实现与应用;
3)对链表的操作有更深层次的理解;
该实验涉及到线性表的建立、插入、删除等操作,涉及到了队列的建立、插
入、删除,涉及到了离散事件的应用思想,还涉及到了排序的概念。完成这个实
验对线性表、队列及 C 语言编程等多方面的知识将是一个很好的利用,对离散事
件也将有一个初步的认识。
二、实验仪器或设备
1 台/学生微型计算机。
三、总体设计(设计原理、设计方案及流程等)
1.设计原理:
为了计算平均时间,就要掌握每个客户到达银行和离开银行这两个时
刻,后者减去前者即为每个客户在银行逗留的时间。所有客户逗留时间的
总和被一天内进入银行的客户数除便是所求的平均时间。
事件的主要信息是事件类型和事件发生的时刻,算法中要处理的事件
有两类:一类是客户到达的时间,另一类是客户离开的时间。前一类事件
发生的时刻随客户到来自然形成,后一类事件发生时刻则由客户事务所需
时间 和等待所耗时间而定。由于驱动程序是按时间发生时刻的先后顺序
进行,则事件表应该是有序表,其主要操作是插入和删除事件。
2.设计方案及流程
由于在实际的银行中,客户到达的时刻及其办理事务所需时间都是随
机的,在模拟程序中可用随机数代替,不失一般性。假设第一个客户进门
的时刻为 0,即是模拟程序处理的第一个事件,之后每个客户到达的时刻
在前一个客户到达时设定。因此在客户到达事件发生时需先产生两个随机
数:其一为此时刻到达的客户办理事务所需时间 durtime;其二为下一个
客 户 将 到 达 的 时 间 间 隔 intertime , 假 设 当 前 事 件 发 生 的 时 刻 为
occurtime,则下一个客户到达事件发生的时刻为 occurtime+intertime。
由此应产生一个新的客户到达时间插入表;刚到达的客户则应插入到当前
所含元素最少的队列中;若该队列在插入前为空,则还应产生一个客户离
开事件插入事件表。
客户离开时间的处理比较简单。首先计算该客户在银行逗留的时间,
然后从队列中删除该客户后查看队列是否为空,若不空则设定一个新的队
头客户离开事件。
四、实验步骤(包括主要步骤、代码分析等)
第 1 次:完成程序的主框架设计,进行调试,验证其正确性;
第 2 次:详细设计,进行调试,验证其正确性;
第 3 次:进行整体调试,运行程序,对运行结果进行分析,完成实验报告。
程序代码如下:
#include
#include // malloc()等
#include
#include
#include
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status; // Status 是函数的类型,其值是函数结果状态代码,
如 OK 等
#define Qu 4 // 客户队列数
typedef struct
{
int OccurTime; // 事件发生时刻
int NType;
}Event,ElemType;
typedef struct LNode
{
ElemType data;
LNode *next;
}*Link,*Position;
struct LinkList // 链表类型
{
Link head,tail;
int len;
};
typedef struct
{
int ArrivalTime; // 到达时刻
int Duration; // 办理事务所需时间
}QElemType; // 定义 QElemType(队列的数据元素类型)为结构体类型;
typedef struct QNode
{
QElemType data;
QNode *next;
}*QueuePtr;
struct LinkQueue
{
QueuePtr front,rear; // 队头、队尾指针
};
typedef LinkList EventList; // 事件链表类型,定义为有序链表
EventList ev; // 事件表
Event en; // 事件
Event et; // 临时变量
LinkQueue q[Qu]; // Qu 个客户队列
QElemType customer; // 客户记录
int TotalTime=0,CustomerNum=0; // 累计客户逗留时间,客户数(初值为
0)
int CloseTime; // 银行营业时间(单位是分)
//对链表的操作:
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;
}
else
return ERROR;
}
Status DelFirst(LinkList &L,Link h,Link &q)
{
q=h->next;
if(q) // 链表非空
{
h->next=q->next;
if(!h->next) // 删除尾结点
L.tail=h; // 修改尾指针
L.len--;
return OK;
}
else
return FALSE; // 链表空
}
ElemType GetCurElem(Link p)
{ // 已知 p 指向线性链表中的一个结点,返回 p 所指结点中数据元素的值
return p->data;
}
Status ListEmpty(LinkList L)
{
if(L.len)
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{
return L.len;
}
Position GetHead(LinkList L)
{ // 返回线性链表 L 中头结点的位置
return L.head;
}
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)
{
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 InitQueue(LinkQueue &Q)
{ // 构造一个空队列 Q
if(!(Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode))))
exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
Status QueueEmpty(LinkQueue Q)
{ // 若 Q 为空队列,则返回 TRUE,否则返回 FALSE
if(Q.front==Q.rear)
return TRUE;
else
return 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(LinkQueue Q,QElemType &e)
{ // 若队列不空,则用 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;
if(!(p=(QueuePtr)malloc(sizeof(QNode)))) // 存储分配失败
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;
}
int cmp(Event a,Event b)
{ // 依事件 a 的发生时刻<、=或>事件 b 的发生时刻分别返回-1、0 或 1
if(a.OccurTime==b.OccurTime)
return 0;
else
return
(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