数据结构--银行模拟

头文件list.h
#include "stdafx.h"
#include <cstdlib>
#include "my.h"

//#define ElemType char     //定义链表中元素的类型

typedef struct LNode    //结点的结构
{
    ElemType data;
    LNode *next;
}*Link,*Position;

typedef struct LinkList   //定义链表的结构
{
    Link head;
    Link tail;
    int len;
}LinkList;

int MakeNode(Link &p, ElemType e)//分配有p指向的值为e的结点,并返回OK,否则返回ERROR
{
    p = (Link)malloc(sizeof(ElemType));
    if(!p)
        return ERROR;
    p->data = e;
    return OK;
}

void FreeNode(Link &p)//释放p指向的结点
{
    free(p);
    p = NULL;
}

int InitList(LinkList &L)//链表初始化
{
    Link p = (Link)malloc(sizeof(LNode));
    if(!p)
        return ERROR;
    p->next = NULL;
    L.head = L.tail = p;
    L.len =0;
    return OK;
}

void ClearList(LinkList &L)//将线性链表置为空表,并释放原链表结点空间
{
    Link p,q;
    if(L.head != L.tail)
    {
        p = q = L.head->next;
        L.head->next =NULL;
        while(p != L.tail)
        {
            q = p->next;
            free(p);
            p = q;
        }
        free(p);
        L.tail = L.head;
        L.len = 0;
    }
}

void DestroyList(LinkList &L)//销毁线性链表
{
    ClearList(L);
    FreeNode(L.head);
    L.tail = NULL;
    L.len = 0;
}

void InsFirst(LinkList &L, Link h, Link &s)//h指向线性链表的头结点,在h之后插入s指向的结点
{
    s->next = h->next;
    h->next = s;
    if(h == L.tail)
        L.tail = s;
    L.len++;
}

int DelFirst(LinkList &L, Link h, Link &q)//h指向线性链表的头结点,删除h之后的第一个结点,并以q返回
{
    q = h->next;
    if(q)
    {
        h->next = q->next;
        if(q == L.tail)
            L.tail = h;
        L.len--;
        return OK;
    }
    else
        return ERROR;
}

int Append(LinkList &L, Link s)//将s指向的链表一串结点链接在L的尾结点后,并将尾结点指向新的尾结点
{
    Link p = s;
    int   j = 1;
    if(!p)
        return ERROR;
    L.tail->next = s;
    while(p->next)
    {
        p = p->next;
        j++;
    }
    L.tail = p;
    L.len += j;
    return OK;
}

int Remove(LinkList &L, Link &q)//删除L的尾结点,并以q返回,改变链表的尾指针指向新的尾结点
{
    if(L.len == 0)
    {
        q = NULL;
        return ERROR;
    }
    Link p = L.head;
    while(p->next != L.tail)
    {
        p = p->next;
    }
    q = L.tail;
    p->next = NULL;
    L.tail = p;
    L.len--;
    return OK;
}

void InsBefore(LinkList &L, Link &p, Link s)//p为链表L中的一个结点,在p之前插入s指向的结点,并使p指向新的结点
{
    Link temp = L.head;
    while(temp->next != p)
        temp = temp->next;
    s->next = temp->next;
    temp->next = s;
    L.len++;
    p = s;
}

void InsAfter(LinkList &L, Link &p, Link s)//p是链表L中的一个结点,在p之后插入s指向的结点,并使p指向新的结点
{
    if(p == L.tail)
    {
        p->next = s;
        s->next = NULL;
        L.tail = s;
    }
    else
    {
        s->next = p->next;
        p->next = s;
    }
    p = s;
    L.len++;
}

void SetCurElem(Link &p , ElemType e)//用e更新p指向结点的元素
{
    p->data = e;
}

ElemType GetCurElem(Link p)//获取p指向的结点中数据元素的值
{
    return p->data;
}

int ListEmpty(LinkList &L)//链表是否为空
{
    return L.len == 0 ? 1:0;
}

int ListLength(LinkList &L)//链表的长度
{
    return L.len;
}

Position GetHead(LinkList L)//获取链表的头结点
{
    return L.head;
}

Position GetLast(LinkList L)//获取链表的尾结点
{
    return L.tail;
}

Position PriorPos(LinkList L, Link p)//p为线性链表L的结点,返回p指向的结点的直接前驱,反则返回NULL
{
    if(p || p==L.head || p==L.head->next)
        return NULL;
    Link temp = L.head;
    while(temp->next != p)
    {
        temp = temp->next;
    }
    return temp;
}

Position NextPos(LinkList L, Link p)//p为线性链表L的结点,返回p指向的结点的直接后继,反则返回NULL
{
    if(p)
        return NULL;
    return p->next;
}
int LocatePos(LinkList L, int i ,Link &p)//返回线性链表L中第i个结点,并以p返回
{
    int j=0;
    p = L.head;
    while(p && j<i)
    {
        p = p->next;
        j++;
    }
    if( j>i || !p)
        return ERROR;
    return OK;
}

//int cmp(ElemType a, ElemType b)//结点数据值a>b 返回1 , a<b 返回-1 , a=b返回0
//{
//    if(a>b)
//        return 1;
//    else if(a<b)
//        return -1;
//    else
//        return 0;
//}

int cmp(Event a , Event b)
{
    if(a.Occurtime > b.Occurtime)
        return 1;
    else if(a.Occurtime < b.Occurtime)
        return -1;
    else
        return 0;
}

void OrderInsert(LinkList &L, ElemType e, int (*cmp)(ElemType, ElemType))
{
    Link o,p,q;
    q = L.head;
    p = q->next;
    while(p && cmp(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++;
    if(!p)
        L.tail = o;
}

Position LocateElm(LinkList L, ElemType e, int (*cmp)(ElemType,ElemType))//返回线性链表L中第一个满足cmp条件的结点
{
    Link p = L.head->next;
    while(p && !cmp(e,p->data))
        p= p->next;
    return p;
}

void Visit(ElemType a)//输出结点数据值
{
    //cout<<a<<" ";
}

void ListTraverse(LinkList L, void (*Visit)(ElemType))//遍历线性链表
{
    Link p = L.head->next;
    while(p)
    {
        Visit(p->data);
        p = p->next;
    }
}


头文件 queue.h
#include "stdafx.h"
#include <stdlib.h>
#include "my.h"
//#define QElemType char //定义队列元素的类型

typedef struct QNode//定义结点的结构
{
    QElemType data;
    QNode *next;
}QNode,*QueuePtr;

typedef struct LinkQueue//定义队列结构
{
    QueuePtr front;
    QueuePtr rear;
}LinkQueue;

int InitQueue(LinkQueue &Q)//初始化队列
{
    Q.front = (QueuePtr)malloc(sizeof(QNode));
    if(!Q.front)
        return ERROR;
    Q.front->next = NULL;
    Q.rear  = Q.front;
    return OK;
}

int DestroyQueue(LinkQueue &Q)//销毁队列
{
    while(Q.front)
    {
        Q.rear = Q.front->next;
        free (Q.front);
        Q.front = Q.rear;
    }
    return OK;
}

int InsertQueue(LinkQueue &Q, QElemType e)//在对尾插入元素
{
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(!p)
        return ERROR;
    p->data = e;
    p->next = NULL;
    Q.rear->next = p;
    Q.rear = p;
    return OK;
}

int DeleteQueue(LinkQueue &Q, QElemType &e)//在对头删除元素
{
    if(Q.front == Q.rear)
        return ERROR;
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(!p)
        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 QueueEmpty(LinkQueue &Q)//判断队列是否空
{
    if(Q.front == Q.rear)
        return OK;
    else
        return ERROR;
}

int QueueLength(LinkQueue &Q)//队列的长度
{
    QueuePtr p = Q.front;
    int num = 0;
    while(p != Q.rear)
    {
        num++;
        p = p->next;
    }
    return num;
}

int GetHead(LinkQueue &Q, QElemType &e)//获取对头元素
{
    if(!QueueEmpty(Q))
    {
        e = Q.front->next->data;
        return OK;
    }
    else
        return ERROR;
}

int Minimun(LinkQueue *Q)
{
    int a1 = QueueLength(Q[1]);
    int a2 = QueueLength(Q[2]);
    int a3 = QueueLength(Q[3]);
    int a4 = QueueLength(Q[4]);

    int min = a1 < a2 ? a1 : a2;
    min = min < a3 ? min : a3;
    min = min < a4 ? min : a4;

    if(min == a1)
        return 1;
    else if(min == a2)
        return 2;
    else if(min == a3)
        return 3;
    else
        return 4;
}

头文件 my.h
#pragma once

#define   TRUE                    1
#define   FALSE                    0
#define   OK                        1
#define   ERROR                0
#define   OVERFLOW       -2
#define   INFEASIBLE           -1

typedef struct Event
{
    int Occurtime;
    int NType;
}Event,ElemType;

typedef struct QElemType
{
    int ArrivalTime;
    int Duration;
}QElemType;

源文件
// bank simulate.cpp : Defines the entry point for the console application.
/*-----CODE FOR FUN---------------
-------CREATED BY Dream_Whui--
-------2015-1-26--------------------*/

#include "stdafx.h"
#include "list.h"
#include "queue.h"
#include "my.h"
#include <iostream>
using namespace std;

typedef LinkList EventList; //事件链表

#define            DRTIME    15 //办理时间不超过30分钟
#define            INTIME        5   //用户到达时间间隔不超过5分钟
#define            CLOSEDTIME   480 //银行关闭时间,从0分钟开始计时

EventList                ev ; //事件链表
Event                    en, et; //某事件,某临时时间
LinkQueue            q[5]; //4个客户队列
QElemType            customer; //队列中的客户

int TotalTime=0 ,        CustomerNum=0;//办理总时间,客户总数
FILE *fp, *fq;

void OpenForDay()
{
    TotalTime = 0;  //总时间初始化
    CustomerNum = 0; //客户总数初始化
    InitList(ev); //初始化事件链表
    en.Occurtime = 0;//第一个客户到达时间
    fprintf(fq,"首位客户到达时刻=%3d,",en.Occurtime);  
    en.NType = 0;//类型0,表示客户到达
    OrderInsert(ev, en, cmp);//插入到事件链表中
    for(int i=1; i<5; i++)
        InitQueue(q[i]);//初始化4个队列
}

void Radom(int &durtime, int &intertime)
{
    durtime = rand()%DRTIME + 1;
    intertime = rand()%INTIME +1;
}

void CustomerArrived()//处理客户到达时间
{
    int durtime , intertime;
    CustomerNum++;
    Radom(durtime, intertime); //随机产生办理时间和时间间隔
    et.Occurtime = en.Occurtime + intertime;//下一个客户的到达时间
    et.NType = 0;
    if(et.Occurtime < CLOSEDTIME)
        OrderInsert(ev,et,cmp);
    int i = Minimun(q);//在4个队列中找出长度最小的队列
    //if(CustomerNum<=20) // 输出前20个客户到达信息到文件a.txt中  
        fprintf(fq,"办理业务的时间=%2d,所排队列=%d\n下一客户到达时刻=%3d,",durtime,i,et.Occurtime);
    QElemType Q;
    Q.ArrivalTime = en.Occurtime;//客户的到达时间
    Q.Duration = durtime;//客户的办理时间
    InsertQueue(q[i],Q);//插入到队列中
    if(QueueLength(q[i])==1)//该队列只有一个客户,生成离开事件
    {
        et.Occurtime = en.Occurtime + durtime;//客户的离开时间
        et.NType = i;//类型i(i>0),表示队列i有离开事件
        OrderInsert(ev,et,cmp);//插入到事件链表中
    }
}

void CustomerDeparture()
{
    int i = en.NType;
    DeleteQueue(q[i],customer);//删除队列第一个元素,并用customer返回
    TotalTime += en.Occurtime - customer.ArrivalTime;//客户的逗留时间=客户离开时间-客户到达时间
    cout<<en.Occurtime<<" "<<customer.ArrivalTime<<" "<<en.Occurtime - customer.ArrivalTime<<" "<<TotalTime<<endl;
    if(!QueueEmpty(q[i]))
    {
        GetHead(q[i], customer);//取队列的第一个元素,并生成离开事件
        et.Occurtime = en.Occurtime + customer.Duration;//客户的离开时间
        et.NType = i;
        OrderInsert(ev,et,cmp);
    }
}

void bank_simulate()
{
    Link p;
    OpenForDay();
    while(!ListEmpty(ev))
    {
        DelFirst(ev,ev.head,p);
        en = GetCurElem(p);
        //if (en.Occurtime< 50) // 输出前50分钟内发生的事件到文件d.txt  
        fprintf(fp, "p->data.OccurTime = %3d p->data.NType = %d\n", p->data.Occurtime, p->data.NType);
        if(en.NType == 0)
            CustomerArrived();
        else
            CustomerDeparture();
    }
    cout<<"客户总数:"<<CustomerNum<<endl
        <<"所有客户共耗时:"<<TotalTime<< "分钟"<<endl
        <<"平均每人耗时:"<< TotalTime/CustomerNum<<"分钟"<<endl;
}
int main(int argc, char* argv[])
{
    fq = fopen("a.txt","w");//客户到达信息
    fp= fopen("b.txt","w");//有序事件表的历史信息
    bank_simulate();
    fclose(fp);
    fclose(fq);
    return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值