mirror of
https://github.com/kangjianwei/Data-Structure.git
synced 2026-08-18 17:27:25 +08:00
💡 【教材】 ▲03 栈和队列
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
/******************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\01 SequenceStack *
|
||||
* *
|
||||
* 内 容: 顺序栈相关函数测试 *
|
||||
* *
|
||||
******************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "SequenceStack.c" //**▲03 栈和队列**//
|
||||
|
||||
void PrintElem(SElemType_Sq e);
|
||||
//测试函数,打印整型
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
SqStack S;
|
||||
int i;
|
||||
SElemType_Sq e;
|
||||
|
||||
printf("▼1\n▲函数 InitStack 测试...\n"); //1.函数InitStack测试
|
||||
{
|
||||
printf("初始化顺序栈 S ...\n");
|
||||
InitStack_Sq(&S);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼4\n▲函数 StackEmpty 测试...\n"); //4.函数StackEmpty测试
|
||||
{
|
||||
StackEmpty_Sq(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼7\n▲函数 Push 测试...\n"); //7.函数Push测试
|
||||
{
|
||||
for(i=1; i<=6; i++)
|
||||
{
|
||||
printf("将 \"%2d\" 压入栈 S ", 2*i);
|
||||
Push_Sq(&S, 2*i);
|
||||
printf("(累计第 %d 个元素)...\n", S.top-S.base);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼9\n▲函数 StackTraverse 测试...\n"); //9.函数StackTraverse测试
|
||||
{
|
||||
printf(" S 中的元素为:S = ");
|
||||
StackTraverse_Sq(S, PrintElem);
|
||||
printf("\n\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼8\n▲函数 Pop 测试...\n"); //8.函数Pop测试
|
||||
{
|
||||
Pop_Sq(&S, &e);
|
||||
printf("栈顶元素 \"%d\" 出栈...\n", e);
|
||||
printf(" S 中的元素为:S = ");
|
||||
StackTraverse_Sq(S, PrintElem);
|
||||
printf("\n\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼5\n▲函数 StackLength 测试...\n"); //5.函数StackLength测试
|
||||
{
|
||||
i = StackLength_Sq(S);
|
||||
printf(" S 的长度为 %d \n", i);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼6\n▲函数 GetTop 测试...\n"); //6.函数GetTop测试
|
||||
{
|
||||
GetTop_Sq(S, &e);
|
||||
printf("栈顶元素的值为 \"%d\" \n", e);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼3\n▲函数 ClearStack 测试...\n"); //3.函数ClearStack测试
|
||||
{
|
||||
printf("清空 S 前:");
|
||||
StackEmpty_Sq(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
ClearStack_Sq(&S);
|
||||
printf("清空 S 后:");
|
||||
StackEmpty_Sq(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼2\n▲函数 DestroyStack 测试...\n"); //2.函数DestroyStack测试
|
||||
{
|
||||
printf("销毁 S 前:");
|
||||
S.base!=NULL && S.top!=NULL ? printf(" S 存在!\n") : printf(" S 不存在!!\n");
|
||||
DestroyStack_Sq(&S);
|
||||
printf("销毁 S 后:");
|
||||
S.base!=NULL && S.top!=NULL ? printf(" S 存在!\n") : printf(" S 不存在!!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PrintElem(SElemType_Sq e)
|
||||
{
|
||||
printf("%d ", e);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/******************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\01 SequenceStack *
|
||||
* *
|
||||
* 文件名: SequenceStack.c *
|
||||
* *
|
||||
******************************************/
|
||||
|
||||
#ifndef SEQUENCESTACK_C
|
||||
#define SEQUENCESTACK_C
|
||||
|
||||
#include "SequenceStack.h" //**▲03 栈和队列**//
|
||||
|
||||
Status InitStack_Sq(SqStack *S)
|
||||
{
|
||||
(*S).base = (SElemType_Sq *)malloc(STACK_INIT_SIZE*sizeof(SElemType_Sq));
|
||||
if(!(*S).base)
|
||||
exit(OVERFLOW);
|
||||
|
||||
(*S).top = (*S).base;
|
||||
(*S).stacksize = STACK_INIT_SIZE;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Status DestroyStack_Sq(SqStack *S)
|
||||
{
|
||||
free((*S).base);
|
||||
|
||||
(*S).base = NULL;
|
||||
(*S).top = NULL;
|
||||
(*S).stacksize = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Status ClearStack_Sq(SqStack *S)
|
||||
{
|
||||
(*S).top = (*S).base;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Status StackEmpty_Sq(SqStack S)
|
||||
{
|
||||
if(S.top==S.base)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int StackLength_Sq(SqStack S)
|
||||
{
|
||||
return S.top - S.base;
|
||||
}
|
||||
|
||||
Status GetTop_Sq(SqStack S, SElemType_Sq *e)
|
||||
{
|
||||
if(S.top==S.base)
|
||||
return ERROR;
|
||||
|
||||
*e = *(S.top - 1); //并不破坏栈
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
Status Push_Sq(SqStack *S, SElemType_Sq e)
|
||||
{
|
||||
if((*S).top-(*S).base>=(*S).stacksize) //栈满,追加存储空间
|
||||
{
|
||||
(*S).base = (SElemType_Sq *)realloc((*S).base, ((*S).stacksize+STACKINCREMENT)*sizeof(SElemType_Sq));
|
||||
if(!(*S).base)
|
||||
exit(OVERFLOW); //存储分配失败
|
||||
(*S).top = (*S).base + (*S).stacksize;
|
||||
(*S).stacksize += STACKINCREMENT;
|
||||
}
|
||||
|
||||
*(S->top) = e; //进栈先赋值,栈顶指针再自增
|
||||
(S->top)++;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Status Pop_Sq(SqStack *S, SElemType_Sq *e)
|
||||
{
|
||||
if((*S).top==(*S).base)
|
||||
return ERROR;
|
||||
|
||||
(*S).top--; //出栈栈顶指针先递减,再赋值
|
||||
*e = *((*S).top);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Status StackTraverse_Sq(SqStack S, void(Visit)(SElemType_Sq))
|
||||
{ //遍历不应该破坏栈
|
||||
SElemType_Sq *p = S.base;
|
||||
|
||||
while(p<S.top)
|
||||
Visit(*p++);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
/******************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\01 SequenceStack *
|
||||
* *
|
||||
* 文件名: SequenceStack.h *
|
||||
* *
|
||||
* 内 容: 顺序栈相关操作列表 *
|
||||
* *
|
||||
******************************************/
|
||||
|
||||
#ifndef SEQUENCESTACK_H
|
||||
#define SEQUENCESTACK_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> //提供malloc、realloc、free、exit原型
|
||||
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
|
||||
|
||||
/* 宏定义 */
|
||||
#define STACK_INIT_SIZE 100 //顺序栈存储空间的初始分配量
|
||||
#define STACKINCREMENT 10 //顺序栈存储空间的分配增量
|
||||
|
||||
/* 顺序栈类型定义 */
|
||||
/*在迷宫、表达式、二叉树二叉链表、孩子兄弟树等算法中,此类型需要重新定义*/
|
||||
#if !defined MAZE_H && \
|
||||
!defined EXPRESSION_H && \
|
||||
!defined BINARYTREE_H && \
|
||||
!defined CHILDSIBLINGTREE_H && \
|
||||
!defined Question_8
|
||||
typedef int SElemType_Sq;
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
SElemType_Sq *base; //在栈构造之前和销毁之后,base的值为NULL
|
||||
SElemType_Sq *top; //栈顶指针
|
||||
int stacksize; //当前已分配的存储空间,以元素为单位
|
||||
}SqStack;
|
||||
|
||||
/* 顺序栈函数列表 */
|
||||
Status InitStack_Sq(SqStack *S);
|
||||
/*━━━━━━━━┓
|
||||
┃(01)构造空栈S。 ┃
|
||||
┗━━━━━━━━*/
|
||||
|
||||
Status DestroyStack_Sq(SqStack *S);
|
||||
/*━━━━━━┓
|
||||
┃(02)销毁S。 ┃
|
||||
┗━━━━━━*/
|
||||
|
||||
Status ClearStack_Sq(SqStack *S);
|
||||
/*━━━━━━┓
|
||||
┃(03)置空S。 ┃
|
||||
┗━━━━━━*/
|
||||
|
||||
Status StackEmpty_Sq(SqStack S);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(04)判断S是否为空。 ┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
int StackLength_Sq(SqStack S);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(05)返回S元素个数。 ┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
Status GetTop_Sq(SqStack S, SElemType_Sq *e);
|
||||
/*━━━━━━━━━━━┓
|
||||
┃(06)用e获取栈顶元素。 ┃
|
||||
┗━━━━━━━━━━━*/
|
||||
|
||||
Status Push_Sq(SqStack *S, SElemType_Sq e);
|
||||
/*━━━━━━━━┓
|
||||
┃(07)元素e进栈。 ┃
|
||||
┗━━━━━━━━*/
|
||||
|
||||
Status Pop_Sq(SqStack *S, SElemType_Sq *e);
|
||||
/*━━━━━━━━┓
|
||||
┃(08)元素e出栈。 ┃
|
||||
┗━━━━━━━━*/
|
||||
|
||||
Status StackTraverse_Sq(SqStack S, void(Visit)(SElemType_Sq));
|
||||
/*━━━━━━┓
|
||||
┃(09)访问栈。┃
|
||||
┗━━━━━━*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/***************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\02 Conversion *
|
||||
* *
|
||||
* 内 容: 进制转换相关函数测试 *
|
||||
* *
|
||||
***************************************/
|
||||
|
||||
#include "Conversion.c" //**▲03 栈和队列**//
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i = 342391;
|
||||
|
||||
printf("将十进制数转换为八进制数...\n");
|
||||
|
||||
conversion(i);
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/***************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\02 Conversion *
|
||||
* *
|
||||
* 文件名: Conversion.c *
|
||||
* *
|
||||
* 算 法: 3.1 *
|
||||
* *
|
||||
***************************************/
|
||||
|
||||
#ifndef CONVERSION_C
|
||||
#define CONVERSION_C
|
||||
|
||||
#include "Conversion.h" //**▲03 栈和队列**//
|
||||
|
||||
/*════╗
|
||||
║ 算法3.1║
|
||||
╚════*/
|
||||
void conversion(int i)
|
||||
{
|
||||
SqStack S;
|
||||
SElemType_Sq e;
|
||||
|
||||
InitStack_Sq(&S);
|
||||
|
||||
printf("十进制数 %d 转换为八进制数后为:0", i);
|
||||
|
||||
while(i)
|
||||
{
|
||||
Push_Sq(&S, i%8); //进栈时从低位到高位
|
||||
i = i/8;
|
||||
}
|
||||
|
||||
while(!StackEmpty_Sq(S))
|
||||
{
|
||||
Pop_Sq(&S, &e); //出栈时从高位到低位
|
||||
printf("%d", e);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
/***************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\02 Conversion *
|
||||
* *
|
||||
* 文件名: Conversion.h *
|
||||
* *
|
||||
* 内 容: 进制转换相关操作列表 *
|
||||
* *
|
||||
***************************************/
|
||||
|
||||
#ifndef CONVERSION_H
|
||||
#define CONVERSION_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../01 SequenceStack/SequenceStack.c" //**▲03 栈和队列**//
|
||||
|
||||
/* 进制转换函数列表 */
|
||||
void conversion(int i);
|
||||
/*━━━━━━━━━━━━━━━━━┓
|
||||
┃(01)算法3.1:十进制数转八进制数。 ┃
|
||||
┗━━━━━━━━━━━━━━━━━*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
/*************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\03 LineEdit *
|
||||
* *
|
||||
* 内 容: 行编辑程序相关函数测试 *
|
||||
* *
|
||||
*************************************/
|
||||
|
||||
#include "LineEdit.c" //**▲03 栈和队列**//
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *buf = "whli##ilr#e(s#*s)\noutcha@ putchar(*s=#++);"; //需要录入的内容
|
||||
|
||||
printf("作为示范,用户输入的文本内容为:\n");
|
||||
printf("%s\n", buf);
|
||||
printf("\n");
|
||||
printf("进入行编辑程序...\n");
|
||||
printf("特殊符号:“#” 代表删除上一元素,“@”代表删除当前输入行,\n");
|
||||
printf(" “\\n”代表确认此行无误,“\\0”代表输入结束。\n");
|
||||
printf("最终存储的内容为:\n");
|
||||
LineEdit(buf);
|
||||
printf("\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\03 LineEdit *
|
||||
* *
|
||||
* 文件名: LineEdit.c *
|
||||
* *
|
||||
* 算 法: 3.2 *
|
||||
* *
|
||||
*************************************/
|
||||
|
||||
#ifndef LINEEDIT_C
|
||||
#define LINEEDIT_C
|
||||
|
||||
#include "LineEdit.h" //**▲03 栈和队列**//
|
||||
|
||||
/*════╗
|
||||
║ 算法3.2║
|
||||
╚════*/
|
||||
/* 与严蔚敏课本所述算法略有差别,但算法思想一致 */
|
||||
void LineEdit(char Buffer[])
|
||||
{
|
||||
SqStack S; //接收输入的字符
|
||||
SElemType_Sq e;
|
||||
int i;
|
||||
char ch;
|
||||
|
||||
InitStack_Sq(&S);
|
||||
|
||||
i = 0;
|
||||
ch = Buffer[i++];
|
||||
while(ch!='\0')
|
||||
{
|
||||
while(ch!='\0' && ch!='\n')
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case '#': Pop_Sq(&S, &e);
|
||||
break;
|
||||
case '@': ClearStack_Sq(&S);
|
||||
break;
|
||||
default : Push_Sq(&S, ch);
|
||||
}
|
||||
ch = Buffer[i++];
|
||||
}
|
||||
|
||||
if(ch=='\n')
|
||||
{
|
||||
Push_Sq(&S, ch);
|
||||
StackTraverse_Sq(S, Print);
|
||||
ClearStack_Sq(&S);
|
||||
ch = Buffer[i++];
|
||||
}
|
||||
}
|
||||
|
||||
if(ch=='\0')
|
||||
{
|
||||
StackTraverse_Sq(S, Print);
|
||||
DestroyStack_Sq(&S);
|
||||
}
|
||||
}
|
||||
|
||||
void Print(SElemType_Sq e)
|
||||
{
|
||||
printf("%c", e);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
/*************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\03 LineEdit *
|
||||
* *
|
||||
* 文件名: LineEdit.h *
|
||||
* *
|
||||
* 内 容: 行编辑程序相关操作列表 *
|
||||
* *
|
||||
*************************************/
|
||||
|
||||
#ifndef LINEEDIT_H
|
||||
#define LINEEDIT_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../01 SequenceStack/SequenceStack.c" //**▲03 栈和队列**//
|
||||
|
||||
/* 行编辑程序函数列表 */
|
||||
void LineEdit(char Buffer[]);
|
||||
/*━━━━━━━━━━━━━┓
|
||||
┃(01)算法3.2:行编辑程序。 ┃
|
||||
┗━━━━━━━━━━━━━*/
|
||||
|
||||
void Print(SElemType_Sq e);
|
||||
/*━━━━━━━━┓
|
||||
┃(02)打印元素e。 ┃
|
||||
┗━━━━━━━━*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
/*********************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\04 Maze *
|
||||
* *
|
||||
* 内 容: 迷宫相关函数测试 *
|
||||
* *
|
||||
*********************************/
|
||||
|
||||
#include "Maze.c" //**▲03 栈和队列**//
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MazeType maze[N][N];
|
||||
PosType start, end;
|
||||
SElemType_Sq e;
|
||||
char Re = 'Y';
|
||||
|
||||
while(Re=='Y' || Re=='y')
|
||||
{
|
||||
InitMaze(maze, &start, &end); //初始化迷宫,包括出入口
|
||||
ShowMaze(maze); //显示迷宫的初始状态
|
||||
MazePath(maze,start,end); //迷宫寻路
|
||||
|
||||
printf("重置?(Y/N):");
|
||||
scanf("%c", &Re);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*********************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\04 Maze *
|
||||
* *
|
||||
* 文件名: Maze.c *
|
||||
* *
|
||||
* 算 法: 3.3 *
|
||||
* *
|
||||
*********************************/
|
||||
|
||||
#ifndef MAZE_C
|
||||
#define MAZE_C
|
||||
|
||||
#include "Maze.h" //**▲03 栈和队列**//
|
||||
|
||||
/*════╗
|
||||
║ 算法3.3║
|
||||
╚════*/
|
||||
Status MazePath(MazeType maze[][N], PosType start, PosType end)
|
||||
{
|
||||
SqStack S;
|
||||
SElemType_Sq nodeInf; //nodeInf存储当前通道块信息
|
||||
PosType curPos; //当前位置
|
||||
int curStep; //当前通道块序号
|
||||
|
||||
InitStack_Sq(&S);
|
||||
curPos = start; //设定当前位置为"出口位置"
|
||||
curStep = 1;
|
||||
|
||||
do
|
||||
{
|
||||
if(Pass(curPos, maze)) //当前位置可通过,即是未曾访问的通道块
|
||||
{
|
||||
FootPrint(curPos, maze); //留下足迹
|
||||
ShowMaze(maze);
|
||||
|
||||
SetSElemType(&nodeInf, curStep, curPos, East); //设置通道块信息
|
||||
Push_Sq(&S, nodeInf); //加入路径
|
||||
|
||||
if(EqualPosType(curPos, end)) //到达终点
|
||||
{
|
||||
printf("\n寻路成功!!\n\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
curPos = NextPos(curPos, East); //下一位置是当前位置的东邻
|
||||
curStep++; //探索下一步
|
||||
}
|
||||
else //当前位置不能通过
|
||||
{
|
||||
if(!StackEmpty_Sq(S))
|
||||
{
|
||||
Pop_Sq(&S, &nodeInf); //修改结点指向
|
||||
|
||||
while(nodeInf.di==North && !StackEmpty_Sq(S)) //此通道块4个方向都遍历过
|
||||
{
|
||||
MarkPrint(nodeInf.seat, maze); //留下不能通过的标记,并退回一步
|
||||
ShowMaze(maze);
|
||||
|
||||
Pop_Sq(&S, &nodeInf);
|
||||
}
|
||||
|
||||
if(nodeInf.di<North)
|
||||
{
|
||||
maze[nodeInf.seat.x][nodeInf.seat.y] = ++nodeInf.di;//改变探索方向,在迷宫数组中留下标记
|
||||
ShowMaze(maze);
|
||||
|
||||
Push_Sq(&S, nodeInf);
|
||||
|
||||
curPos = NextPos(nodeInf.seat, nodeInf.di);
|
||||
}
|
||||
}
|
||||
}
|
||||
}while(!StackEmpty_Sq(S));
|
||||
|
||||
printf("\n寻路失败!!\n\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void InitMaze(MazeType maze[][N], PosType *start, PosType *end)
|
||||
{ //迷宫规模为N×N
|
||||
int i, j, tmp;
|
||||
|
||||
srand((unsigned)time(NULL)); //用系统时间做随机数种子
|
||||
|
||||
for(i=0; i<N; i++)
|
||||
{
|
||||
for(j=0; j<N; j++)
|
||||
{
|
||||
if(i==0 || j==0 || i==N-1 || j==N-1)
|
||||
maze[i][j] = Wall; //迷宫外墙
|
||||
else
|
||||
{
|
||||
tmp = rand()%X; //生成随机数填充迷宫
|
||||
if(!tmp)
|
||||
maze[i][j] = Obstacle; //1/X的概率生成障碍
|
||||
else
|
||||
maze[i][j] = Way; //其它地方加入路径
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*start).x = 1; //迷宫入口
|
||||
(*start).y = 0;
|
||||
(*end).x = N-2; //迷宫出口
|
||||
(*end).y = N-1;
|
||||
|
||||
maze[1][0] = maze[N-2][N-1] = Way; //开放入口和出口
|
||||
maze[1][1] = maze[N-2][N-2] = Way; //为了提高成功率,入口处和出口处临近的结点一直设为通路
|
||||
}
|
||||
|
||||
void PaintMaze(MazeType maze[][N])
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for(i=0; i<N; i++)
|
||||
for(j=0; j<N; j++)
|
||||
{
|
||||
if(maze[i][j]==Wall) //外墙
|
||||
printf("▇");
|
||||
else if(maze[i][j]==Obstacle) //内部障碍
|
||||
printf("▓");
|
||||
else if(maze[i][j]==East) //朝东探索
|
||||
printf("→");
|
||||
else if(maze[i][j]==South) //朝南探索
|
||||
printf("↓");
|
||||
else if(maze[i][j]==West) //朝西探索
|
||||
printf("←");
|
||||
else if(maze[i][j]==North) //朝北探索
|
||||
printf("↑");
|
||||
else if(maze[i][j]==DeadLock) //访问过且不能通过的结点
|
||||
printf("★");
|
||||
else //未访问过的路径结点
|
||||
printf(" ");
|
||||
|
||||
if(j!=0 && j%(N-1)==0) //每隔N个结点换行
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ShowMaze(MazeType maze[][N]) //相当于刷新操作
|
||||
{
|
||||
Wait(SleepTime); //暂停
|
||||
system("cls"); //先清除屏幕现有内容
|
||||
PaintMaze(maze); //在屏幕上画出迷宫
|
||||
}
|
||||
|
||||
Status EqualPosType(PosType seat1, PosType seat2)
|
||||
{
|
||||
if(seat1.x==seat2.x && seat1.y==seat2.y)
|
||||
return TRUE; //两通道块坐标相等返回1
|
||||
else
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
Status Pass(PosType seat, MazeType maze[][N])
|
||||
{
|
||||
int x = seat.x;
|
||||
int y = seat.y;
|
||||
|
||||
if(!IsCross(seat) && maze[x][y]==Way) //结点不能越界
|
||||
return TRUE;
|
||||
else
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
void FootPrint(PosType seat, MazeType maze[][N]) //所谓留下足迹即设置其下一次访问方向
|
||||
{
|
||||
maze[seat.x][seat.y] = East; //初始设置向东探索
|
||||
}
|
||||
|
||||
void SetSElemType (SElemType_Sq *e, int ord, PosType seat, int di)
|
||||
{
|
||||
(*e).ord = ord;
|
||||
(*e).seat = seat;
|
||||
(*e).di = di;
|
||||
}
|
||||
|
||||
PosType NextPos(PosType seat, int di)
|
||||
{
|
||||
PosType tmp = seat;
|
||||
|
||||
switch(di)
|
||||
{
|
||||
case East: tmp.y++; //向东
|
||||
break;
|
||||
case South: tmp.x++; //向南
|
||||
break;
|
||||
case West: tmp.y--; //向西
|
||||
break;
|
||||
case North: tmp.x--; //向北
|
||||
break;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Status IsCross(PosType seat)
|
||||
{
|
||||
int x = seat.x;
|
||||
int y = seat.y;
|
||||
|
||||
if(x<0 || y<0 || x>N-1 || y>N-1)
|
||||
return TRUE; //越界
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void MarkPrint(PosType seat, MazeType maze[][N])
|
||||
{
|
||||
int x = seat.x;
|
||||
int y = seat.y;
|
||||
|
||||
maze[x][y] = DeadLock; //留下不能通过的标记
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
/*********************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\04 Maze *
|
||||
* *
|
||||
* 文件名: Maze.h *
|
||||
* *
|
||||
* 内 容: 迷宫相关操作列表 *
|
||||
* *
|
||||
*********************************/
|
||||
|
||||
#ifndef MAZE_H
|
||||
#define MAZE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> //提供system、rand、srand原型
|
||||
#include <time.h> //提供time原型
|
||||
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
|
||||
|
||||
/* 宏定义 */
|
||||
#define N 15 //迷宫的大小为N×N
|
||||
#define X 4 //X用于随机数取余,其生成的随机数范围是0到X-1
|
||||
//X越大,生成可通行迷宫的概率就越大
|
||||
#define SleepTime 3 //SleepTime代表休眠时间间隔
|
||||
|
||||
/* 迷宫类型定义 */
|
||||
typedef enum //迷宫通道块类型
|
||||
{
|
||||
Wall, //外墙
|
||||
Obstacle, //迷宫障碍
|
||||
Way, //路径
|
||||
DeadLock, //路径上的“死胡同”
|
||||
East,South,West,North //访问方向-东南西北
|
||||
}MazeNode;
|
||||
typedef struct //迷宫通道块坐标
|
||||
{
|
||||
int x; //通道块的横、纵坐标定义
|
||||
int y;
|
||||
}PosType;
|
||||
typedef struct //通道块信息
|
||||
{
|
||||
int ord; //通道块的“序号”
|
||||
PosType seat; //通道块的“坐标位置”
|
||||
int di; //下一个该访问的“方向”
|
||||
}SElemType_Sq;
|
||||
#include "../01 SequenceStack/SequenceStack.c" //**▲03 栈和队列**//
|
||||
typedef int MazeType; //迷宫元素类型
|
||||
|
||||
/* 迷宫函数列表 */
|
||||
Status MazePath(MazeType maze[][N], PosType start, PosType end);
|
||||
/*━━━━━━━━━━━━━━━━┓
|
||||
┃(01)算法3.3:迷宫寻路(穷举法) ┃
|
||||
┗━━━━━━━━━━━━━━━━*/
|
||||
|
||||
void InitMaze(MazeType maze[][N], PosType *start, PosType *end);
|
||||
/*━━━━━━━━━━━━━━━━━━┓
|
||||
┃(02)迷宫的初始化,包括出入口的初始化 ┃
|
||||
┗━━━━━━━━━━━━━━━━━━*/
|
||||
|
||||
void PaintMaze(MazeType maze[][N]);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(03)在屏幕上画出迷宫┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
void ShowMaze(MazeType maze[][N]);
|
||||
/*━━━━━━━┓
|
||||
┃(04)迷宫的显示┃
|
||||
┗━━━━━━━*/
|
||||
|
||||
Status EqualPosType(PosType a, PosType b);
|
||||
/*━━━━━━━━━━━━━━━━━━━┓
|
||||
┃(05)比较迷宫中两个通道块是否为同一通道块┃
|
||||
┗━━━━━━━━━━━━━━━━━━━*/
|
||||
|
||||
Status Pass(PosType seat, MazeType maze[][N]);
|
||||
/*━━━━━━━━━━━━━┓
|
||||
┃(06)判定此通道块是否未访问┃
|
||||
┗━━━━━━━━━━━━━*/
|
||||
|
||||
void FootPrint(PosType seat, MazeType maze[][N]);
|
||||
/*━━━━━━━━━━━━━━━━┓
|
||||
┃(07)遇到未访问结点时留下初始足迹┃
|
||||
┗━━━━━━━━━━━━━━━━*/
|
||||
|
||||
void SetSElemType(SElemType_Sq *e, int ord, PosType seat, int di);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(08)更新通道块的信息┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
PosType NextPos(PosType seat, int di);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(09)当前通道块的后继┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
Status IsCross(PosType seat);
|
||||
/*━━━━━━━━━━━━┓
|
||||
┃(10)判断当前位置是否越界┃
|
||||
┗━━━━━━━━━━━━*/
|
||||
|
||||
void MarkPrint(PosType seat, MazeType maze[][N]);
|
||||
/*━━━━━━━━━━━━━━━━━┓
|
||||
┃(11)标记当前位置上的通道块不可访问┃
|
||||
┗━━━━━━━━━━━━━━━━━*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
/***************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\05 Expression *
|
||||
* *
|
||||
* 内 容: 表达式求值相关函数测试 *
|
||||
* *
|
||||
***************************************/
|
||||
|
||||
#include "Expression.c" //**▲03 栈和队列**//
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char opnd;
|
||||
char *exp = "(2+3)*4*6#";
|
||||
|
||||
opnd = EvaluateExpression(exp);
|
||||
|
||||
printf("作为示例,%s 的计算结果为:%d\n", exp, opnd-'0');
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/***************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\05 Expression *
|
||||
* *
|
||||
* 文件名: Expression.c *
|
||||
* *
|
||||
* 算 法: 3.4 *
|
||||
* *
|
||||
***************************************/
|
||||
|
||||
#ifndef EXPRESSION_C
|
||||
#define EXPRESSION_C
|
||||
|
||||
#include "Expression.h" //**▲03 栈和队列**//
|
||||
|
||||
/*════╗
|
||||
║ 算法3.4║
|
||||
╚════*/
|
||||
OperandType EvaluateExpression(char exp[]) //从exp读入表达式
|
||||
{
|
||||
SqStack OPTR, OPND; //符号栈和数字栈
|
||||
SElemType_Sq e, ch;
|
||||
OperatorType theta, x; //符号
|
||||
OperandType a, b; //数字
|
||||
int i;
|
||||
|
||||
InitStack_Sq(&OPTR);
|
||||
Push_Sq(&OPTR, '#');
|
||||
InitStack_Sq(&OPND);
|
||||
|
||||
i = 0;
|
||||
ch = exp[i++];
|
||||
while(ch!='#' || GetTop_OPTR(OPTR)!='#')
|
||||
{
|
||||
if(!In(ch)) //c不是符号则入栈
|
||||
{
|
||||
Push_Sq(&OPND, ch);
|
||||
ch = exp[i++];
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(Precede(GetTop_OPTR(OPTR), ch))
|
||||
{
|
||||
case '<': //栈中符号优先级低,继续进栈
|
||||
Push_Sq(&OPTR, ch);
|
||||
ch = exp[i++];
|
||||
break;
|
||||
|
||||
case '=': //优先级相等时,说明遇到括号,需要脱括号
|
||||
Pop_Sq(&OPTR, &x);
|
||||
ch = exp[i++];
|
||||
break;
|
||||
|
||||
case '>':
|
||||
Pop_Sq(&OPTR, &theta); //栈中操作符优先级高时,先计算,再降计算结果压入栈,
|
||||
Pop_Sq(&OPND, &b);
|
||||
Pop_Sq(&OPND, &a);
|
||||
Push_Sq(&OPND, Operate(a, theta, b));
|
||||
break; //这儿没有读字符,c保留的还是刚才读到的字符
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GetTop_OPTR(OPND);
|
||||
}
|
||||
|
||||
OperatorType GetTop_OPTR(SqStack OPTR)
|
||||
{
|
||||
SElemType_Sq e;
|
||||
|
||||
GetTop_Sq(OPTR, &e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
Status In(SElemType_Sq c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '+':
|
||||
case '-':
|
||||
case '*':
|
||||
case '/':
|
||||
case '(':
|
||||
case ')':
|
||||
case '#':
|
||||
return TRUE;
|
||||
default :
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
OperatorType Precede(OperatorType o1, OperatorType o2)
|
||||
{
|
||||
OperatorType f;
|
||||
|
||||
switch(o2)
|
||||
{
|
||||
case '+':
|
||||
case '-':
|
||||
if(o1=='(' || o1=='#')
|
||||
f = '<';
|
||||
else
|
||||
f = '>';
|
||||
break;
|
||||
|
||||
case '*':
|
||||
case '/':
|
||||
if(o1=='*' || o1=='/' || o1==')')
|
||||
f = '>';
|
||||
else
|
||||
f = '<';
|
||||
break;
|
||||
|
||||
case '(':
|
||||
if(o1==')')
|
||||
{
|
||||
printf("括号匹配错误!\n");
|
||||
exit(ERROR);
|
||||
}
|
||||
else
|
||||
f = '<';
|
||||
break;
|
||||
|
||||
case ')':
|
||||
switch(o1)
|
||||
{
|
||||
case '(':
|
||||
f = '=';
|
||||
break;
|
||||
case '#':
|
||||
printf("输入了错误的括号!\n");
|
||||
exit(ERROR);
|
||||
default:
|
||||
f = '>';
|
||||
}
|
||||
break;
|
||||
|
||||
case '#':
|
||||
switch(o1)
|
||||
{
|
||||
case '#':
|
||||
f = '=';
|
||||
break;
|
||||
case '(':
|
||||
printf("表达式中有多余括号!\n");
|
||||
exit(ERROR);
|
||||
default:
|
||||
f = '>';
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
OperandType Operate(OperandType a, OperatorType theta, OperandType b)
|
||||
{
|
||||
int x, y, z;
|
||||
|
||||
x = a - 48;
|
||||
y = b - 48;
|
||||
|
||||
switch(theta)
|
||||
{
|
||||
case '+':
|
||||
return x+y+48;
|
||||
break;
|
||||
case '-':
|
||||
return x-y+48;
|
||||
break;
|
||||
case '*':
|
||||
return x*y+48;
|
||||
break;
|
||||
case '/':
|
||||
return x/y+48;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/***************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\05 Expression *
|
||||
* *
|
||||
* 文件名: Expression.h *
|
||||
* *
|
||||
* 内 容: 表达式求值相关操作列表 *
|
||||
* *
|
||||
***************************************/
|
||||
|
||||
#ifndef EXPRESSION_H
|
||||
#define EXPRESSION_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* 类型定义 */
|
||||
typedef char SElemType_Sq;
|
||||
#include "../01 SequenceStack/SequenceStack.c" //**▲03 栈和队列**//
|
||||
|
||||
typedef SElemType_Sq OperandType; //操作数类型
|
||||
typedef SElemType_Sq OperatorType; //运算符类型
|
||||
|
||||
OperandType EvaluateExpression(char exp[]);
|
||||
/*━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃(01)算法3.4:表达式求值,假设表达式中操作数均只有一位。 ┃
|
||||
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
|
||||
|
||||
OperatorType GetTop_OPTR(SqStack OPTR);
|
||||
/*━━━━━━━━━━━━━━┓
|
||||
┃(02)获取操作符栈的栈顶元素。┃
|
||||
┗━━━━━━━━━━━━━━*/
|
||||
|
||||
Status In(SElemType_Sq c);
|
||||
/*━━━━━━━━━━━━━━┓
|
||||
┃(03)判断c是否属于操作符集。 ┃
|
||||
┗━━━━━━━━━━━━━━*/
|
||||
|
||||
OperatorType Precede(OperatorType o1, OperatorType o2);
|
||||
/*━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃(04)判断栈中操作符o1与表达式中的操作符o2的优先级。┃
|
||||
┗━━━━━━━━━━━━━━━━━━━━━━━━━*/
|
||||
|
||||
OperandType Operate(OperandType a, OperatorType theta, OperandType b);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(05)计算表达式的值。┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/**********************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\06 Hanoi *
|
||||
* *
|
||||
* 内 容: 汉诺塔相关函数测试 *
|
||||
* *
|
||||
**********************************/
|
||||
|
||||
#include "Hanoi.c" //**03 栈和队列**//
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
char x = 'x';
|
||||
char y = 'y';
|
||||
char z = 'z';
|
||||
|
||||
n = 3; //为控制时间,n不要超过10
|
||||
|
||||
printf("作为示例,假设圆盘个数为 %d ,操作步骤如下...\n", n);
|
||||
|
||||
hanoi(n,x,y,z);
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**********************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\06 Hanoi *
|
||||
* *
|
||||
* 文件名: Hanoi.c *
|
||||
* *
|
||||
* 算 法: 3.5 *
|
||||
* *
|
||||
**********************************/
|
||||
|
||||
#ifndef HANOI_C
|
||||
#define HANOI_C
|
||||
|
||||
#include "Hanoi.h" //**03 栈和队列**//
|
||||
|
||||
/*════╗
|
||||
║ 算法3.5║
|
||||
╚════*/
|
||||
void hanoi(int n, char x, char y, char z)
|
||||
{
|
||||
if(n==1) //欲移动n个圆盘,需先移动其上的n-1个圆盘
|
||||
move(x, 1, z); //将编号为1的圆盘从x移到z
|
||||
else
|
||||
{
|
||||
hanoi(n-1, x, z, y); //将x上编号为1至n-1的圆盘移到y,z作辅助塔
|
||||
move(x, n, z); //将编号为n的圆盘从x移到z
|
||||
hanoi(n-1, y, x, z); //将y上编号为1至n-1的圆盘移动到z,x作辅助塔
|
||||
}
|
||||
}
|
||||
|
||||
void move(char x, int n, char z)
|
||||
{
|
||||
gStep++; //step为全局变量,在main函数之外定义
|
||||
printf("第%2d步:将第 %d 个圆盘从 %c 移到 %c \n", gStep, n, x, z);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/**********************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\06 Hanoi *
|
||||
* *
|
||||
* 文件名: Hanoi.h *
|
||||
* *
|
||||
* 内 容: 汉诺塔相关操作列表 *
|
||||
* *
|
||||
**********************************/
|
||||
|
||||
#ifndef HANOI_H
|
||||
#define HANOI_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* 全局变量 */
|
||||
int gStep; //统计移动步数
|
||||
|
||||
/* 汉诺塔函数列表 */
|
||||
void hanoi(int n, char x, char y, char z);
|
||||
/*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃(1)算法3.5:汉诺塔求解。以y为辅助,将x上前n个圆盘移动到z。┃
|
||||
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
|
||||
|
||||
void move(char x, int n, char z);
|
||||
/*━━━━━━━━━━━━┓
|
||||
┃(2)将第n个圆盘从x移到z。┃
|
||||
┗━━━━━━━━━━━━*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
/**************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\07 LinkQueue *
|
||||
* *
|
||||
* 内 容: 链队相关函数测试 *
|
||||
* *
|
||||
*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "LinkQueue.c" //**03 栈和队列**//
|
||||
|
||||
void PrintElem(QElemType_L e); //测试函数,打印整型
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
LinkQueue Q;
|
||||
int i;
|
||||
QElemType_L e;
|
||||
|
||||
printf("▼1\n▲函数 InitQueue_L 测试...\n"); //1.函数InitQueue_L测试
|
||||
{
|
||||
printf("初始化链队 Q ...\n");
|
||||
InitQueue_L(&Q);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼4\n▲函数 QueueEmpty_L 测试...\n"); //4.函数QueueEmpty_L测试
|
||||
{
|
||||
QueueEmpty_L(Q) ? printf(" Q 为空!!\n") : printf(" Q 不为空!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼7\n▲函数 EnQueue_L 测试...\n"); //7.函数EnQueue_L测试
|
||||
{
|
||||
for(i=1; i<=6; i++)
|
||||
{
|
||||
printf("元素 \"%2d\" 入队,", 2*i);
|
||||
EnQueue_L(&Q, 2*i);
|
||||
printf("(累计第 %d 个元素)...\n", QueueLength_L(Q));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼9\n▲函数 QueueTraverse_L 测试...\n");//9.函数QueueTraverse_L测试
|
||||
{
|
||||
printf(" Q 中的元素为:Q = ");
|
||||
QueueTraverse_L(Q, PrintElem);
|
||||
printf("\n\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼8\n▲函数 DeQueue_L 测试...\n"); //8.函数DeQueue_L测试
|
||||
{
|
||||
DeQueue_L(&Q, &e);
|
||||
printf("队头元素 \"%d\" 出队...\n", e);
|
||||
printf(" Q 中的元素为:Q = ");
|
||||
QueueTraverse_L(Q, PrintElem);
|
||||
printf("\n\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼5\n▲函数 QueueLength_L 测试...\n"); //5.函数QueueLength_L测试
|
||||
{
|
||||
i = QueueLength_L(Q);
|
||||
printf(" Q 的长度为 %d \n", i);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼6\n▲函数 GetHead_L 测试...\n"); //6.函数GetHead_L测试
|
||||
{
|
||||
GetHead_L(Q, &e);
|
||||
printf("队头元素的值为 \"%d\" \n", e);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼3\n▲函数 ClearQueue_L 测试...\n"); //3.函数ClearQueue_L测试
|
||||
{
|
||||
printf("清空 Q 前:");
|
||||
QueueEmpty_L(Q) ? printf(" Q 为空!!\n") : printf(" Q 不为空!\n");
|
||||
ClearQueue_L(&Q);
|
||||
printf("清空 Q 后:");
|
||||
QueueEmpty_L(Q) ? printf(" Q 为空!!\n") : printf(" Q 不为空!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼2\n▲函数 DestroyQueue_L 测试...\n"); //2.函数DestroyQueue_L测试
|
||||
{
|
||||
printf("销毁 Q 前:");
|
||||
Q.front!=NULL && Q.rear!=NULL ? printf(" Q 存在!\n") : printf(" Q 不存在!!\n");
|
||||
DestroyQueue_L(&Q);
|
||||
printf("销毁 Q 后:");
|
||||
Q.front!=NULL && Q.rear!=NULL ? printf(" Q 存在!\n") : printf(" Q 不存在!!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PrintElem(QElemType_L e)
|
||||
{
|
||||
printf("%d ", e);
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/**************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\07 LinkQueue *
|
||||
* *
|
||||
* 文件名: LinkQueue.c *
|
||||
* *
|
||||
*************************************/
|
||||
|
||||
#ifndef LINKQUEUE_C
|
||||
#define LINKQUEUE_C
|
||||
|
||||
#include "LinkQueue.h" //**▲03 栈和队列**//
|
||||
|
||||
Status InitQueue_L(LinkQueue *Q)
|
||||
{
|
||||
(*Q).front = (*Q).rear = (QueuePtr)malloc(sizeof(QNode));
|
||||
if(!(*Q).front)
|
||||
exit(OVERFLOW);
|
||||
|
||||
(*Q).front->next = NULL;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ClearQueue_L(LinkQueue *Q)
|
||||
{
|
||||
(*Q).rear = (*Q).front->next;
|
||||
|
||||
while((*Q).rear)
|
||||
{
|
||||
(*Q).front->next = (*Q).rear->next;
|
||||
free((*Q).rear);
|
||||
(*Q).rear = (*Q).front->next;
|
||||
}
|
||||
|
||||
(*Q).rear = (*Q).front;
|
||||
}
|
||||
|
||||
void DestroyQueue_L(LinkQueue *Q)
|
||||
{
|
||||
while((*Q).front)
|
||||
{
|
||||
(*Q).rear = (*Q).front->next;
|
||||
free((*Q).front);
|
||||
(*Q).front = (*Q).rear;
|
||||
}
|
||||
}
|
||||
|
||||
Status QueueEmpty_L(LinkQueue Q)
|
||||
{
|
||||
if(Q.front==Q.rear)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int QueueLength_L(LinkQueue Q)
|
||||
{
|
||||
int count = 0;
|
||||
QueuePtr p = Q.front;
|
||||
|
||||
while(p!=Q.rear)
|
||||
{
|
||||
count++;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
Status GetHead_L(LinkQueue Q, QElemType_L *e)
|
||||
{
|
||||
QueuePtr p;
|
||||
|
||||
if(Q.front==Q.rear)
|
||||
return ERROR;
|
||||
|
||||
p = Q.front->next;
|
||||
*e = p->data;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Status EnQueue_L(LinkQueue *Q, QElemType_L e)
|
||||
{
|
||||
QueuePtr p;
|
||||
|
||||
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_L(LinkQueue *Q, QElemType_L *e)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void QueueTraverse_L(LinkQueue Q, void (Visit)(QElemType_L))
|
||||
{
|
||||
QueuePtr p;
|
||||
|
||||
p = Q.front->next;
|
||||
|
||||
while(p)
|
||||
{
|
||||
Visit(p->data);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
/**************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\07 LinkQueue *
|
||||
* *
|
||||
* 文件名: LinkQueue.h *
|
||||
* *
|
||||
* 内 容: 链队相关操作列表 *
|
||||
* *
|
||||
*************************************/
|
||||
|
||||
#ifndef LINKQUEUE_H
|
||||
#define LINKQUEUE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> //提供malloc、realloc、free、exit原型
|
||||
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
|
||||
|
||||
/* 链队类型定义 */
|
||||
/* 在模拟银行排队、二叉树三叉链表存储的算法中,QElemType_L需重新定义*/
|
||||
#if !defined BANKQUEUING_H && \
|
||||
!defined TRI_BINARYTREE_H
|
||||
typedef int QElemType_L;
|
||||
#endif
|
||||
typedef struct QNode
|
||||
{
|
||||
QElemType_L data;
|
||||
struct QNode *next;
|
||||
}QNode;
|
||||
typedef QNode* QueuePtr;
|
||||
typedef struct
|
||||
{
|
||||
QueuePtr front; //头指针
|
||||
QueuePtr rear; //尾指针
|
||||
}LinkQueue; //队列的链式存储表示
|
||||
|
||||
/* 链栈函数列表 */
|
||||
Status InitQueue_L(LinkQueue *Q);
|
||||
/*━━━━━━━━━┓
|
||||
┃(01)初始化链队Q。 ┃
|
||||
┗━━━━━━━━━*/
|
||||
|
||||
void ClearQueue_L(LinkQueue *Q);
|
||||
/*━━━━━━┓
|
||||
┃(02)置空Q。 ┃
|
||||
┗━━━━━━*/
|
||||
|
||||
void DestroyQueue_L(LinkQueue *Q);
|
||||
/*━━━━━━┓
|
||||
┃(03)销毁Q。 ┃
|
||||
┗━━━━━━*/
|
||||
|
||||
Status QueueEmpty_L(LinkQueue Q);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(04)判断Q是否为空。 ┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
int QueueLength_L(LinkQueue Q);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(05)返回Q元素个数。 ┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
Status GetHead_L(LinkQueue Q, QElemType_L *e);
|
||||
/*━━━━━━━━━━━┓
|
||||
┃(06)用e获取队头元素。 ┃
|
||||
┗━━━━━━━━━━━*/
|
||||
|
||||
Status EnQueue_L(LinkQueue *Q, QElemType_L e);
|
||||
/*━━━━━━━━┓
|
||||
┃(07)元素e入队。 ┃
|
||||
┗━━━━━━━━*/
|
||||
|
||||
Status DeQueue_L(LinkQueue *Q, QElemType_L *e);
|
||||
/*━━━━━━━━┓
|
||||
┃(08)元素e出队。 ┃
|
||||
┗━━━━━━━━*/
|
||||
|
||||
void QueueTraverse_L(LinkQueue Q, void(Visit)(QElemType_L));
|
||||
/*━━━━━━━┓
|
||||
┃(09)访问队列。┃
|
||||
┗━━━━━━━*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
/****************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\08 CylSeqQueue *
|
||||
* *
|
||||
* 内 容: 循环队列相关函数测试 *
|
||||
* *
|
||||
****************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "CylSeqQueue.c" //**▲03 栈和队列**//
|
||||
|
||||
void PrintElem(QElemType_CSq e); //测试函数,打印整型
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CSqQueue Q;
|
||||
int i;
|
||||
QElemType_CSq e;
|
||||
|
||||
printf("▼1\n▲函数 InitQueue_CSq 测试...\n"); //1.函数InitQueue_CSq测试
|
||||
{
|
||||
printf("初始化循环顺序队列 Q ...\n");
|
||||
InitQueue_CSq(&Q);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼4\n▲函数 QueueEmpty_CSq 测试...\n"); //4.函数QueueEmpty_CSq测试
|
||||
{
|
||||
QueueEmpty_CSq(Q) ? printf(" Q 为空!!\n") : printf(" Q 不为空!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼7\n▲函数 EnQueue_CSq 测试...\n"); //7.函数EnQueue_CSq测试
|
||||
{
|
||||
for(i=1; i<=6; i++)
|
||||
{
|
||||
printf("元素 \"%2d\" 入队Q,", 2*i);
|
||||
EnQueue_CSq(&Q, 2*i);
|
||||
printf("(累计第 %d 个元素)...\n", QueueLength_CSq(Q));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼9\n▲函数 QueueTraverse_CSq 测试...\n"); //9.函数QueueTraverse_CSq测试
|
||||
{
|
||||
printf(" Q 中的元素为:Q = ");
|
||||
QueueTraverse_CSq(Q, PrintElem);
|
||||
printf("\n\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼8\n▲函数 DeQueue_CSq 测试...\n"); //8.函数DeQueue_CSq测试
|
||||
{
|
||||
DeQueue_CSq(&Q, &e);
|
||||
printf("队头元素 \"%d\" 出队...\n", e);
|
||||
printf(" Q 中的元素为:Q = ");
|
||||
QueueTraverse_CSq(Q, PrintElem);
|
||||
printf("\n\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼5\n▲函数 QueueLength_CSq 测试...\n"); //5.函数QueueLength_CSq测试
|
||||
{
|
||||
i = QueueLength_CSq(Q);
|
||||
printf(" Q 的长度为 %d \n", i);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼6\n▲函数 GetHead_CSq 测试...\n"); //6.函数GetHead_CSq测试
|
||||
{
|
||||
GetHead_CSq(Q, &e);
|
||||
printf("队头元素的值为 \"%d\" \n", e);
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼3\n▲函数 ClearQueue_CSq 测试...\n"); //3.函数ClearQueue_CSq测试
|
||||
{
|
||||
printf("清空 Q 前:");
|
||||
QueueEmpty_CSq(Q) ? printf(" Q 为空!!\n") : printf(" Q 不为空!\n");
|
||||
ClearQueue_CSq(&Q);
|
||||
printf("清空 Q 后:");
|
||||
QueueEmpty_CSq(Q) ? printf(" Q 为空!!\n") : printf(" Q 不为空!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
printf("▼2\n▲函数 DestroyQueue_CSq 测试...\n"); //2.函数DestroyQueue_CSq测试
|
||||
{
|
||||
printf("销毁 Q 前:");
|
||||
Q.base!=NULL ? printf(" Q 存在!\n") : printf(" Q 不存在!!\n");
|
||||
DestroyQueue_CSq(&Q);
|
||||
printf("销毁 Q 后:");
|
||||
Q.base!=NULL ? printf(" Q 存在!\n") : printf(" Q 不存在!!\n");
|
||||
printf("\n");
|
||||
}
|
||||
PressEnter;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PrintElem(QElemType_CSq e)
|
||||
{
|
||||
printf("%d ", e);
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/****************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\08 CylSeqQueue *
|
||||
* *
|
||||
* 文件名: CylSeqQueue.c *
|
||||
* *
|
||||
****************************************/
|
||||
|
||||
#ifndef CYLSEQQUEUE_C
|
||||
#define CYLSEQQUEUE_C
|
||||
|
||||
#include "CylSeqQueue.h" //**▲03 栈和队列**//
|
||||
|
||||
Status InitQueue_CSq(CSqQueue *Q)
|
||||
{
|
||||
(*Q).base = (QElemType_CSq *)malloc(MAXQSIZE*sizeof(QElemType_CSq));
|
||||
if(!(*Q).base)
|
||||
exit(OVERFLOW);
|
||||
|
||||
(*Q).front = (*Q).rear = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ClearQueue_CSq(CSqQueue *Q)
|
||||
{
|
||||
(*Q).front = (*Q).rear = 0;
|
||||
}
|
||||
|
||||
void DestroyQueue_CSq(CSqQueue *Q)
|
||||
{
|
||||
if((*Q).base)
|
||||
free((*Q).base);
|
||||
|
||||
(*Q).base = NULL;
|
||||
(*Q).front = (*Q).rear = 0;
|
||||
}
|
||||
|
||||
Status QueueEmpty_CSq(CSqQueue Q)
|
||||
{
|
||||
if(Q.front==Q.rear) //队列空的标志
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int QueueLength_CSq(CSqQueue Q)
|
||||
{
|
||||
return (Q.rear-Q.front+MAXQSIZE) % MAXQSIZE;//队列长度
|
||||
}
|
||||
|
||||
Status GetHead_CSq(CSqQueue Q, QElemType_CSq *e)
|
||||
{
|
||||
if(Q.front==Q.rear) //队列空
|
||||
return ERROR;
|
||||
|
||||
*e = Q.base[Q.front];
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Status EnQueue_CSq(CSqQueue *Q, QElemType_CSq e)
|
||||
{
|
||||
if(((*Q).rear+1)%MAXQSIZE == (*Q).front) //队列满
|
||||
return ERROR;
|
||||
|
||||
(*Q).base[(*Q).rear] = e;
|
||||
(*Q).rear = ((*Q).rear+1)%MAXQSIZE;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Status DeQueue_CSq(CSqQueue *Q, QElemType_CSq *e)
|
||||
{
|
||||
if((*Q).front==(*Q).rear) //队列空
|
||||
return ERROR;
|
||||
|
||||
*e = (*Q).base[(*Q).front];
|
||||
(*Q).front = ((*Q).front+1)%MAXQSIZE;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void QueueTraverse_CSq(CSqQueue Q, void(Visit)(QElemType_CSq))
|
||||
{
|
||||
int i = Q.front;
|
||||
|
||||
while(i!=Q.rear)
|
||||
{
|
||||
Visit(Q.base[i]);
|
||||
i = (i+1)%MAXQSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
/****************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\08 CylSeqQueue *
|
||||
* *
|
||||
* 文件名: CylSeqQueue.h *
|
||||
* *
|
||||
* 内 容: 循环队列相关操作列表 *
|
||||
* *
|
||||
****************************************/
|
||||
|
||||
#ifndef CYLSEQQUEUE_H
|
||||
#define CYLSEQQUEUE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> //提供malloc、realloc、free、exit原型
|
||||
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
|
||||
|
||||
/* 宏定义 */
|
||||
#define MAXQSIZE 1000 //最大队列长度
|
||||
|
||||
/* 循环队列类型定义 */
|
||||
typedef int QElemType_CSq;
|
||||
typedef struct //队列的顺序存储结构
|
||||
{
|
||||
QElemType_CSq *base; //初始化的动态分配存储空间
|
||||
int front; //头指针,若队列不空,指向队头元素
|
||||
int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
|
||||
}CSqQueue;
|
||||
|
||||
/* 循环队列函数列表 */
|
||||
Status InitQueue_CSq(CSqQueue *Q);
|
||||
/*━━━━━━━━━━━┓
|
||||
┃(01)初始化循环队列Q。 ┃
|
||||
┗━━━━━━━━━━━*/
|
||||
|
||||
void ClearQueue_CSq(CSqQueue *Q);
|
||||
/*━━━━━━┓
|
||||
┃(02)置空Q。 ┃
|
||||
┗━━━━━━*/
|
||||
|
||||
void DestroyQueue_CSq(CSqQueue *Q);
|
||||
/*━━━━━━┓
|
||||
┃(03)销毁Q。 ┃
|
||||
┗━━━━━━*/
|
||||
|
||||
Status QueueEmpty_CSq(CSqQueue Q);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(04)判断Q是否为空。 ┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
int QueueLength_CSq(CSqQueue Q);
|
||||
/*━━━━━━━━━━┓
|
||||
┃(05)返回Q元素个数。 ┃
|
||||
┗━━━━━━━━━━*/
|
||||
|
||||
Status GetHead_CSq(CSqQueue Q, QElemType_CSq *e);
|
||||
/*━━━━━━━━━━━┓
|
||||
┃(06)用e获取队头元素。 ┃
|
||||
┗━━━━━━━━━━━*/
|
||||
|
||||
Status EnQueue_CSq(CSqQueue *Q, QElemType_CSq e);
|
||||
/*━━━━━━━━┓
|
||||
┃(07)元素e入队。 ┃
|
||||
┗━━━━━━━━*/
|
||||
|
||||
Status DeQueue_CSq(CSqQueue *Q, QElemType_CSq *e);
|
||||
/*━━━━━━━━┓
|
||||
┃(08)元素e出队。 ┃
|
||||
┗━━━━━━━━*/
|
||||
|
||||
void QueueTraverse_CSq(CSqQueue Q, void(Visit)(QElemType_CSq));
|
||||
/*━━━━━━━┓
|
||||
┃(09)访问队列。┃
|
||||
┗━━━━━━━*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
/****************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\09 BankQueuing *
|
||||
* *
|
||||
* 内 容: 模拟银行排队相关函数测试 *
|
||||
* *
|
||||
****************************************/
|
||||
|
||||
#include "BankQueuing.c" //**▲03 栈和队列**//
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
getchar();
|
||||
Bank_Simulation_1(); //算法3.6
|
||||
|
||||
// Bank_Simulation_2(); //算法3.7,另一种算法
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/****************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\09 BankQueuing *
|
||||
* *
|
||||
* 文件名: BankQueuing.c *
|
||||
* *
|
||||
* 算 法: 3.6、3.7 *
|
||||
* *
|
||||
****************************************/
|
||||
|
||||
#ifndef BANKQUEUING_C
|
||||
#define BANKQUEUING_C
|
||||
|
||||
#include "BankQueuing.h" //**▲03 栈和队列**//
|
||||
|
||||
/*════╗
|
||||
║ 算法3.6║
|
||||
╚════*/
|
||||
void Bank_Simulation_1() //银行业务模拟,统计一天内客户在银行逗留的平均时间
|
||||
{
|
||||
char eventType;
|
||||
|
||||
OpenForDay(); //初始化
|
||||
|
||||
while(MoreEvent())
|
||||
{
|
||||
EventDrived(&eventType); //事件驱动
|
||||
|
||||
switch(eventType)
|
||||
{
|
||||
case 'A':
|
||||
CustomerArrived();
|
||||
break;
|
||||
case 'D':
|
||||
CustomerDeparture();
|
||||
break;
|
||||
default :
|
||||
Invalid();
|
||||
}
|
||||
}
|
||||
|
||||
CloseForDay();
|
||||
}
|
||||
|
||||
void OpenForDay()
|
||||
{
|
||||
int i;
|
||||
|
||||
gTotalTime = 0; //初始化累计时间和客户数为0
|
||||
gCustomerNum = 0;
|
||||
|
||||
InitList_L(&gEv); //初始化事件链表为空表
|
||||
|
||||
gEn.OccurTime = 0; //设定第一个客户到达事件
|
||||
gEn.NType = Arrive;
|
||||
|
||||
OrderInsert(gEv, gEn, cmp); //插入事件表
|
||||
|
||||
for(i=1; i<=4; ++i)
|
||||
InitQueue_L(&gQ[i]); //置空队列
|
||||
|
||||
Show();
|
||||
}
|
||||
|
||||
Status MoreEvent()
|
||||
{
|
||||
if(!ListEmpty_L(gEv))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void EventDrived(char *event)
|
||||
{
|
||||
ListDelete_L(gEv, 1, &gEn);
|
||||
|
||||
if(gEn.NType==Arrive)
|
||||
*event = 'A';
|
||||
else
|
||||
*event = 'D';
|
||||
}
|
||||
|
||||
void CustomerArrived() //处理客户到达事件,gEn.NType=0
|
||||
{
|
||||
int durtime, intertime;
|
||||
int cur_LeftTime, suc_ArrivalTime;
|
||||
int i;
|
||||
|
||||
++gCustomerNum; //总客户数增一
|
||||
|
||||
Random(&durtime, &intertime); //生成当前客户办理业务需要的时间和下一个客户达到时间间隔
|
||||
cur_LeftTime = gEn.OccurTime + durtime; //当前客户的离开时间
|
||||
suc_ArrivalTime = gEn.OccurTime + intertime;//下一个客户到达时间
|
||||
|
||||
gCustomerRcd.ArrivedTime = gEn.OccurTime; //记录当前客户信息
|
||||
gCustomerRcd.Duration = durtime;
|
||||
gCustomerRcd.Count = gCustomerNum;
|
||||
|
||||
i = Minimum(gQ); //求长度最短队列
|
||||
EnQueue_L(&gQ[i], gCustomerRcd); //当前客户进入最短队列
|
||||
Show();
|
||||
|
||||
if(suc_ArrivalTime<gCloseTime) //银行尚未关门,将下一客户到达事件插入事件表
|
||||
{
|
||||
gEn.OccurTime = suc_ArrivalTime; //gEn的参数已经改变
|
||||
gEn.NType = Arrive;
|
||||
OrderInsert(gEv, gEn, cmp);
|
||||
}
|
||||
|
||||
if(QueueLength_L(gQ[i])==1) //设定第i队列的队头客户的离开事件并插入事件表
|
||||
{
|
||||
gEn.OccurTime = cur_LeftTime;
|
||||
gEn.NType = i;
|
||||
OrderInsert(gEv, gEn, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomerDeparture() //处理客户离开事件,gEn.NType>0
|
||||
{
|
||||
int i = gEn.NType;
|
||||
|
||||
DeQueue_L(&gQ[i], &gCustomerRcd); //删除第i队列的排头客户
|
||||
Show();
|
||||
|
||||
gTotalTime += gEn.OccurTime - gCustomerRcd.ArrivedTime; //累计客户逗留时间
|
||||
|
||||
if(!QueueEmpty_L(gQ[i])) //设定第i队列的第一个离开事件并插入事件表
|
||||
{
|
||||
GetHead_L(gQ[i], &gCustomerRcd);
|
||||
gEn.OccurTime += gCustomerRcd.Duration;
|
||||
gEn.NType = i;
|
||||
OrderInsert(gEv,gEn,cmp);
|
||||
}
|
||||
}
|
||||
|
||||
void Invalid()
|
||||
{
|
||||
printf("运行错误!");
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
void CloseForDay()
|
||||
{
|
||||
printf("当天总共有%d个客户,平均逗留时间为%d分钟。\n",gCustomerNum,gTotalTime/gCustomerNum);
|
||||
}
|
||||
|
||||
int cmp(Event a, Event b) //比较两事件发生次序
|
||||
{
|
||||
if(a.OccurTime<b.OccurTime) //a晚于b发生
|
||||
return -1;
|
||||
if(a.OccurTime==b.OccurTime) //a、b同时发生
|
||||
return 0;
|
||||
if(a.OccurTime>b.OccurTime) //a早于b发生
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Random(int *durtime, int *intertime)
|
||||
{
|
||||
srand((unsigned)time(NULL));
|
||||
*durtime = rand()%DurationTime+1; //办业务时间持续1到20分钟
|
||||
*intertime = rand()%IntervalTime+1; //下一个顾客来的时间为间隔1到10分钟
|
||||
}
|
||||
|
||||
Status OrderInsert(EventList gEv, Event gEn, int (cmp)(Event,Event))
|
||||
{
|
||||
int i;
|
||||
EventList p, pre, s;
|
||||
|
||||
pre = gEv;
|
||||
p = gEv->next; //p指向第一个事件
|
||||
|
||||
while(p && cmp(gEn, p->data)==1) //查找gEn在事件表中应该插入的位置
|
||||
{
|
||||
pre = p;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
s = (LinkList)malloc(sizeof(LNode));
|
||||
if(!s)
|
||||
exit(OVERFLOW);
|
||||
|
||||
s->data = gEn; //将gEn插入事件表
|
||||
s->next = pre->next;
|
||||
pre->next = s;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int Minimum()
|
||||
{
|
||||
int i1 = QueueLength_L(gQ[1]);
|
||||
int i2 = QueueLength_L(gQ[2]);
|
||||
int i3 = QueueLength_L(gQ[3]);
|
||||
int i4 = QueueLength_L(gQ[4]);
|
||||
|
||||
if(i1<=i2 && i1<=i3 && i1<=i4)
|
||||
return 1;
|
||||
if(i2<i1 && i2<=i3 && i2<=i4)
|
||||
return 2;
|
||||
if(i3<i1 && i3<i2 && i3<=i4)
|
||||
return 3;
|
||||
if(i4<i1 && i4<i2 && i4<i3 )
|
||||
return 4;
|
||||
}
|
||||
|
||||
void Show()
|
||||
{
|
||||
int i;
|
||||
QueuePtr p; //记录到来的客户是第几个
|
||||
|
||||
system("cls");
|
||||
|
||||
for(i=1; i<=4; i++)
|
||||
{
|
||||
for(p=gQ[i].front; p; p=p->next)
|
||||
{
|
||||
if(p==gQ[i].front)
|
||||
{
|
||||
if(i==1)
|
||||
printf("柜台①●");
|
||||
if(i==2)
|
||||
printf("柜台②●");
|
||||
if(i==3)
|
||||
printf("柜台③●");
|
||||
if(i==4)
|
||||
printf("柜台④●");
|
||||
}
|
||||
else
|
||||
printf("(%03d)",p->data.Count);
|
||||
|
||||
|
||||
if(p==gQ[i].rear)
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
Wait(SleepTime);
|
||||
}
|
||||
|
||||
/*════╗
|
||||
║ 算法3.7║
|
||||
╚════*/
|
||||
void Bank_Simulation_2()
|
||||
{
|
||||
OpenForDay(); //初始化
|
||||
|
||||
while(!ListEmpty_L(gEv))
|
||||
{
|
||||
ListDelete_L(gEv, 1, &gEn);
|
||||
|
||||
if(gEn.NType==Arrive)
|
||||
CustomerArrived(); //处理客户到达事件
|
||||
else
|
||||
CustomerDeparture(); //处理客户离开事件
|
||||
}
|
||||
|
||||
printf("当天总共有%d个客户,平均逗留时间为%d分钟。\n",gCustomerNum,gTotalTime/gCustomerNum);//计算平均逗留时间
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
/****************************************
|
||||
* *
|
||||
* 文件夹: ▲03 栈和队列\09 BankQueuing *
|
||||
* *
|
||||
* 文件名: BankQueuing.h *
|
||||
* *
|
||||
* 内 容: 模拟银行排队相关操作列表 *
|
||||
* *
|
||||
****************************************/
|
||||
|
||||
#ifndef BANKQUEUING_H
|
||||
#define BANKQUEUING_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> //提供malloc、realloc、free、exit原型
|
||||
#include <time.h> //提供time原型
|
||||
#include "../../▲01 绪论/Status.h" //**▲01 绪论**//
|
||||
|
||||
/* 宏定义 */
|
||||
#define SleepTime 1 //SleepTime代表休眠时间
|
||||
#define DurationTime 20 //办理业务持续时间从1到DurationTime分钟不等
|
||||
#define IntervalTime 10 //下一个客户到来时间间隔为1到IntervalTime分钟不等
|
||||
|
||||
/* 类型定义 */
|
||||
typedef enum
|
||||
{
|
||||
Arrive,Leave_1,Leave_2,Leave_3,Leave_4
|
||||
}EventType; //事件类型,0代表到达事件,1至4表示四个窗口的离开事件
|
||||
typedef struct //事件链表
|
||||
{
|
||||
int OccurTime; //事件发生时刻
|
||||
EventType NType; //事件类型
|
||||
}Event;
|
||||
typedef Event LElemType_L; //事件链表元素
|
||||
typedef struct LNode
|
||||
{
|
||||
LElemType_L data;
|
||||
struct LNode *next;
|
||||
}LNode;
|
||||
typedef LNode* LinkList;
|
||||
typedef LinkList EventList; //事件链表类型,定义为有序链表
|
||||
#include "../../▲02 线性表/04 SinglyLinkedList/SinglyLinkedList.c" //**▲02 线性表**//
|
||||
typedef struct
|
||||
{
|
||||
int ArrivedTime; //客户到达时间
|
||||
int Duration; //办理事务所需的时间
|
||||
int Count; //此变量记录来到每个队列的客户是第几个
|
||||
}QElemType_L; //队列的数据元素类型
|
||||
#include "../07 LinkQueue/LinkQueue.c" //**▲03 栈和队列**//
|
||||
|
||||
/* 全局变量 */
|
||||
int gTotalTime, gCustomerNum; //累计客户逗留时间,客户数
|
||||
int gCloseTime = 480; //关门时间,假设银行每天营业8小时,480分
|
||||
EventList gEv; //事件表
|
||||
Event gEn; //事件
|
||||
LinkQueue gQ[5]; //4个客户队列,0号单元弃用
|
||||
QElemType_L gCustomerRcd; //客户记录
|
||||
|
||||
/* 模拟银行排队函数列表 */
|
||||
void Bank_Simulation_1();
|
||||
/*━━━━━━━━━━━━━━━━┓
|
||||
┃(01)算法3.6:模拟银行排队事件。 ┃
|
||||
┗━━━━━━━━━━━━━━━━*/
|
||||
|
||||
void OpenForDay();
|
||||
/*━━━━━━━━━━━━━━┓
|
||||
┃(02)银行开门,初始化各变量。┃
|
||||
┗━━━━━━━━━━━━━━*/
|
||||
|
||||
Status MoreEvent();
|
||||
/*━━━━━━━━━━━━┓
|
||||
┃(03)判断事件表是否为空。┃
|
||||
┗━━━━━━━━━━━━*/
|
||||
|
||||
void EventDrived(char *event);
|
||||
/*━━━━━━━━━━━━━━━━┓
|
||||
┃(04)事件驱动,获取当前事件类型。┃
|
||||
┗━━━━━━━━━━━━━━━━*/
|
||||
|
||||
void CustomerArrived();
|
||||
/*━━━━━━━━━━━┓
|
||||
┃(05)处理客户到达事件。┃
|
||||
┗━━━━━━━━━━━*/
|
||||
|
||||
void CustomerDeparture();
|
||||
/*━━━━━━━━━━━┓
|
||||
┃(06)处理客户离开事件。┃
|
||||
┗━━━━━━━━━━━*/
|
||||
|
||||
void Invalid();
|
||||
/*━━━━━━━━━┓
|
||||
┃(07)事件类型错误。┃
|
||||
┗━━━━━━━━━*/
|
||||
|
||||
void CloseForDay();
|
||||
/*━━━━━━━┓
|
||||
┃(08)银行关门。┃
|
||||
┗━━━━━━━*/
|
||||
|
||||
int cmp(Event a, Event b);
|
||||
/*━━━━━━━━━━━━━━━━┓
|
||||
┃(09)比较事件a和b发生的先后次序。┃
|
||||
┗━━━━━━━━━━━━━━━━*/
|
||||
|
||||
void Random(int *durtime, int *intertime);
|
||||
/*━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
┃(10)生成随机数,包括当前客服办理业务所需时间和下一客户到达间隔的时间。┃
|
||||
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━*/
|
||||
|
||||
Status OrderInsert(EventList gEv, Event gEn, int(cmp)(Event,Event));
|
||||
/*━━━━━━━━━━━━━━━┓
|
||||
┃(11)将事件插入事件表正确位置。┃
|
||||
┗━━━━━━━━━━━━━━━*/
|
||||
|
||||
int Minimum();
|
||||
/*━━━━━━━━━━━━━┓
|
||||
┃(12)求长度最短队列的序号。┃
|
||||
┗━━━━━━━━━━━━━*/
|
||||
|
||||
void Show();
|
||||
/*━━━━━━━━━━━━━━━━┓
|
||||
┃(13)显示当前队列的客户排队情况。┃
|
||||
┗━━━━━━━━━━━━━━━━*/
|
||||
|
||||
void Bank_Simulation_2();
|
||||
/*━━━━━━━━━━━━━━━━┓
|
||||
┃(14)算法3.7:模拟银行排队事件。 ┃
|
||||
┗━━━━━━━━━━━━━━━━*/
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user