From 8baabc67575093141c63f068ca7df313588f460f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=A2=A6=E7=90=A6?= <2260836370@qq.com> Date: Sun, 18 Jun 2023 22:03:03 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=88=98=E6=A2=A6=E7=90=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 234 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 213 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 5c726d1..8654a95 100644 --- a/README.md +++ b/README.md @@ -132,38 +132,229 @@ ADT Queue{ # 3. 系统实现 -说明所使用的语言、开发工具等。 -介绍项目的文件结构,以及主要函数的功能。 +语言:C语言 +开发工具:VS Code +采用模块化设计,通过大量的函数实现,银行开门、客户进门、客户离开等功能进而统计一天内客户在银行逗留的平均时间 +## 3.1 核心数据结构的实现 +首先通过有序链表,实现一部分功能如:先初始化有序表,在第i个位置之前插入元素e,删除链表中第一个结点并以q返回,已知p指向线性链表中的一个结点,返回p所指结点中元素的值等等。其次通过队列实现入队和出队。 +typedef struct +{ + int OccurTime;//事件发生时刻 + int NType;//事件类型,0表示到达事件,1-4表示四个窗口的离开事件 +}Event, ElemType; +typedef struct LNode +{ + ElemType data; + struct LNode* next; +}LNode, * LinkList; +typedef LinkList EventList; +typedef struct +{ +int ArrivalTime;//到达时刻 +int Duration;//办理事务所需事件 +}QElemType; +typedef struct QNode +{ +QElemType data; +struct QNode* next; +}QNode, * QueuePtr; +typedef struct +{ +QueuePtr front;//队头指针 +QueuePtr rear;//队尾指针 +}LinkQueue; +EventList ev;//事件表 +Event en;//事件 +LinkQueue q[5];//四个客户队列 +QElemType customer;//客户记录 +int TotalTime, CustomerNum, CloseTime; +链表 +【1】通过一个个指针将节点串起来 +【2】对于元素的随机访问,需要使用计数器来访问指定的元素,并且只能从头节点开始访问,每访问一个节点,计数器加1,直到给定的“下标” +【3】增加元素和删除元素的效率很高 +队列 +【1】先进先出 +【2】线程池中的线程就是从任务队列中取出任务 +## 3.2 核心算法的实现 +Status InitList(LinkList& L)//链表初始化 +{ +L = (LinkList)malloc(sizeof(LNode)); +if (!L) +{ +exit(OVERFLOW); +} +L->next = NULL; +return OK; +} +Status ListInsert_L(LinkList& L, int i, ElemType e)//在第i个位置之前插入元素e +{ +LinkList p = L; +int j = 0; +while (p && j < i - 1)//注意是i-1,因为要找被插入元素的前一个元素 +{ +p = p->next; +j++; +} +if (!p || j > i - 1) +{ +return ERROR; +} +LinkList s = (LinkList)malloc(sizeof(LNode)); +if (!s) +{ +exit(OVERFLOW); +} +s->data = e; +s->next = p->next; +p->next = s; +return OK; +} +Status ListEmpty(LinkList L)//判断链表是否为空 +//空表:头指针和头结点仍然存在,但头结点指向NULL +{ +if (L->next) +{ +return FALSE; +} +else +{ +return TRUE; +} +} +Status DelFirst(LinkList L, LNode*& q)//删除链表中第一个结点并以q返回 +{ +if (!L->next) +{ +return ERROR; +} +q = L->next; +L->next = q->next; +return OK; +} +LNode* GetHead(LinkList L)//返回链表头结点 +{ +return L; +} -## 3.1 核心数据结构的实现 -描述数据结构的实现方法。 -可以配合程序代码加以说明。如: +ElemType GetCurElem(LNode* p)//已知p指向线性链表中的一个结点,返回p所指结点中元素的值 +{ +return p->data; +} -``` -struct LNode { -E data; // 数据元素 -LNode *next; // 指向下一个结点的指针 -}; +void PrintEventList()//打印事件链表  +{ +printf("Current Eventlist is:\n"); +ListTraverse(ev); +} +Status ListTraverse(LinkList& L) //遍历链表   +{ +LNode* p = L->next; +if (!p) { +printf("List is empty.\n"); +return ERROR; +} -``` +while (p != NULL) { +printf("OccurTime:%d,Event Type:%d\n", p->data.OccurTime, p->data.NType); +p = p->next; +} +printf("\n"); +return OK; +} -对该数据结构的特点进行分析。 -## 3.2 核心算法的实现 -描述算法的实现方法。 -可以配合程序代码加以说明。如: +Status InitQueue(LinkQueue& Q)//链队列的初始化 +{ +Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode)); +if (!Q.front) +{ +exit(OVERFLOW); +} +Q.front->next = NULL; +return OK; +} +Status EnQueue(LinkQueue& Q, QElemType e)//入队 +{ +QNode* 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)//出队 +{ +if (Q.front == Q.rear) +{ +return ERROR; +} +QNode* p = Q.front->next; +e = p->data; +Q.front->next = p->next; +if (Q.rear == p)//注意这里要考虑到,当队列中最后一个元素被删后,队列尾指针也丢失了,因此需对队尾指针重新复制(指向头结点) +{ +Q.rear = Q.front; +} +free(p); +return OK; +} -``` -// 冒泡排序 -void bubble_sort(T a[], int n) +int QueueLength(LinkQueue Q)//返回队列的长度 +{ +int count = 0; +QNode* p = Q.front->next; +while (p) { +p = p->next; +count++; +} +return count; +} + +Status GetHead(LinkQueue Q, QElemType& e)//获取队头元素 +{ +if (Q.front == Q.rear) +{ return ERROR;} +e = Q.front->next->data; +} +Status QueueEmpty(LinkQueue Q)//判断队列是否为空 { -...... +if (Q.front == Q.rear) +{ +return TRUE; +} +return FALSE; +} +void PrintQueue()//打印队列 +{ +//打印当前队列   +int i; +for (i = 1; i <= 4; i++) { +printf("窗口 %d 有 %d 个客户:", i, QueueLength(q[i])); +QueueTraverse(q[i]); +} +printf("\n"); +} +Status QueueTraverse(LinkQueue Q)//遍历队列Q   +{ +QNode* p = Q.front->next; +if (!p) { +printf("--Is empty.\n"); +return ERROR; +} +while (p) { +printf("(到达时刻 %d min 办理业务需要花费 %d min) ", p->data.ArrivalTime, p->data.Duration); +p = p->next; +} +printf("\n"); +return OK; } -```` -对该算法的时间和空间复杂度进行分析。 # 4.系统测试 @@ -316,6 +507,7 @@ The Average Time is 15.285714 成员(2)金雨佳: 成员(3)赵亚璇: 成员(4)刘梦琦: +通过这次数据结构实训,让我意识到了团队协作的重要性,运用数据结构的知识模拟银行系统,更加熟练地掌握单链表和队列的应用,将所学的知识用在实践项目上时我此次实训的最大收获,在未来的生活中,我要努力学习技术,将知识联系到实际生活当中,把所学用到所用。 # 参考文献 From 8b4e8c60f175f6309776c04d7596a5f58ea7191c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=BD=A9=E6=9C=88?= Date: Sun, 18 Jun 2023 22:21:25 +0800 Subject: [PATCH 2/2] 1 --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 8654a95..8bdc305 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,8 @@ ADT Queue{ 采用模块化设计,通过大量的函数实现,银行开门、客户进门、客户离开等功能进而统计一天内客户在银行逗留的平均时间 ## 3.1 核心数据结构的实现 首先通过有序链表,实现一部分功能如:先初始化有序表,在第i个位置之前插入元素e,删除链表中第一个结点并以q返回,已知p指向线性链表中的一个结点,返回p所指结点中元素的值等等。其次通过队列实现入队和出队。 + +``` typedef struct { int OccurTime;//事件发生时刻 @@ -168,6 +170,8 @@ Event en;//事件 LinkQueue q[5];//四个客户队列 QElemType customer;//客户记录 int TotalTime, CustomerNum, CloseTime; +``` + 链表 【1】通过一个个指针将节点串起来 【2】对于元素的随机访问,需要使用计数器来访问指定的元素,并且只能从头节点开始访问,每访问一个节点,计数器加1,直到给定的“下标” @@ -176,6 +180,7 @@ int TotalTime, CustomerNum, CloseTime; 【1】先进先出 【2】线程池中的线程就是从任务队列中取出任务 ## 3.2 核心算法的实现 +``` Status InitList(LinkList& L)//链表初始化 { L = (LinkList)malloc(sizeof(LNode)); @@ -354,6 +359,7 @@ p = p->next; printf("\n"); return OK; } +```