队列的应用

来源:互联网 发布:回龙观矩阵托管 编辑:程序博客网 时间:2024/05/22 13:15

1.HANOI

/* algo3-10.c Hanoi塔问题,调用算法3.5的程序 */#include<stdio.h>int c = 0; /* 全局变量,搬动次数 */void move(char x, int n, char z){ /* 第n个圆盘从塔座x搬到塔座z */printf("第%i步: 将%i号盘从%c移到%c\n", ++c, n, x, z);}void hanoi(int n, char x, char y, char z) /* 算法3.5 */{ /* 将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘 *//* 按规则搬到塔座z上。y可用作辅助塔座 */if (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 main(){int n;printf("3个塔座为a、b、c,圆盘最初在a座,借助b座移到c座。请输入圆盘数:");scanf("%d", &n);hanoi(n, 'a', 'b', 'c');}

2.ackerman数

/* algo3-8.c 用递归调用求Ackerman(m,n)的值 */#include<stdio.h>int ack(int m, int n){int z;if (m == 0)z = n + 1;else if (n == 0)z = ack(m - 1, 1);elsez = ack(m - 1, ack(m, n - 1));return z;}void main(){int m, n;printf("Please input m,n:");scanf("%d,%d", &m, &n);printf("Ack(%d,%d)=%d\n", m, n, ack(m, n));}

3.递归解迷宫问题

/* algo3-9.c 用递归函数求解迷宫问题(求出所有解) */#include<stdio.h> /* 根据《PASCAL程序设计》(郑启华编著)中的程序改编 */struct PosType /* 迷宫坐标位置类型 */{int x; /* 行值 */int y; /* 列值 */};#define MAXLENGTH 25 /* 设迷宫的最大行列为25 */typedef int MazeType[MAXLENGTH][MAXLENGTH]; /* [行][列] *//* 全局变量 */struct PosType end; /* 迷宫终点位置 */MazeType m; /* 迷宫数组 */int x, y; /* 迷宫行数,列数 *//* 定义墙元素值为0,可通过路径为-1,通过路径为足迹 */void Print(int x, int y){ /* 输出解 */int i, j;for (i = 0; i<x; i++){for (j = 0; j<y; j++)printf("%3d", m[i][j]);printf("\n");}printf("\n");}void Try(struct PosType cur, int curstep){ /* 由当前位置cur、当前步骤curstep试探下一点 */int i;struct PosType next; /* 下一个位置 */struct PosType direc[4] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } }; /* {行增量,列增量} *//* 移动方向,依次为东南西北 */for (i = 0; i <= 3; i++) /* 依次试探东南西北四个方向 */{next.x = cur.x + direc[i].x;next.y = cur.y + direc[i].y;if (m[next.x][next.y] == -1) /* 是通路 */{m[next.x][next.y] = ++curstep;if (next.x != end.x || next.y != end.y) /* 没到终点 */Try(next, curstep); /* 试探下一点(递归调用) */elsePrint(x, y); /* 输出结果 */m[next.x][next.y] = -1; /* 恢复为通路,试探下一条路 */curstep--;}}}void main(){struct PosType begin;int i, j, x1, y1;printf("请输入迷宫的行数,列数(包括外墙):");scanf("%d,%d", &x, &y);for (i = 0; i<x; i++) /* 定义周边值为0(同墙) */{m[0][i] = 0; /* 行周边 */m[x - 1][i] = 0;}for (j = 1; j<y - 1; j++){m[j][0] = 0; /* 列周边 */m[j][y - 1] = 0;}for (i = 1; i<x - 1; i++)for (j = 1; j<y - 1; j++)m[i][j] = -1; /* 定义通道初值为-1 */printf("请输入迷宫内墙单元数:");scanf("%d", &j);if (j)printf("请依次输入迷宫内墙每个单元的行数,列数:\n");for (i = 1; i <= j; i++){scanf("%d,%d", &x1, &y1);m[x1][y1] = 0;}printf("迷宫结构如下:\n");Print(x, y);printf("请输入起点的行数,列数:");scanf("%d,%d", &begin.x, &begin.y);printf("请输入终点的行数,列数:");scanf("%d,%d", &end.x, &end.y);m[begin.x][begin.y] = 1;Try(begin, 1); /* 由第一步起点试探起 */}

4.BFS解迷宫

类型头文件

#ifndef ELEMTYPE#define ELEMTYPEtypedef struct /* 定义队列元素和栈元素为同类型的结构体 */{int x, y; /* 当前点的行值,列值 */int pre; /* 前一点在队列中的序号 */}ElemType; /* 定义栈元素和队列元素 */#endif


stack1.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 "ElemType.h"/* 函数结果状态代码 */#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 char ElemType;#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */#define STACKINCREMENT 2 /* 存储空间分配增量 */typedef struct stack{ElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */ElemType *top; /* 栈顶指针 */int stacksize; /* 当前已分配的存储空间,以元素为单位 */}stack; /* 顺序栈 */Status screate(stack *S);Status sdestroy(stack *S);Status sclear(stack *S);Status sempty(stack S);int ssize(stack S);ElemType stop(stack S);Status spush(stack *S, ElemType e);Status spop(stack *S);Status straverse(stack S, Status(*visit)(ElemType));

实现文件

#include "stack1.h"Status screate(stack *S){ /* 构造一个空栈S */(*S).base = (ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType));if (!(*S).base)exit(OVERFLOW); /* 存储分配失败 */(*S).top = (*S).base;(*S).stacksize = STACK_INIT_SIZE;return OK;}Status sdestroy(stack *S){ /* 销毁栈S,S不再存在 */free((*S).base);(*S).base = NULL;(*S).top = NULL;(*S).stacksize = 0;return OK;}Status sclear(stack *S){ /* 把S置为空栈 */(*S).top = (*S).base;return OK;}Status sempty(stack S){ /* 若栈S为空栈,则返回TRUE,否则返回FALSE */if (S.top == S.base)return TRUE;elsereturn FALSE;}int ssize(stack S){ /* 返回S的元素个数,即栈的长度 */return S.top - S.base;}ElemType stop(stack S){ /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */if (S.top > S.base){return *(S.top - 1);}else{puts("try to get a elment from a empty stack");exit(0);}}Status spush(stack *S, ElemType e){ /* 插入元素e为新的栈顶元素 */if ((*S).top - (*S).base >= (*S).stacksize) /* 栈满,追加存储空间 */{(*S).base = (ElemType *)realloc((*S).base, ((*S).stacksize + STACKINCREMENT)*sizeof(ElemType));if (!(*S).base)exit(OVERFLOW); /* 存储分配失败 */(*S).top = (*S).base + (*S).stacksize;(*S).stacksize += STACKINCREMENT;}*((*S).top)++ = e;return OK;}Status spop(stack *S){ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */if ((*S).top == (*S).base)return ERROR;--(*S).top;return OK;}Status straverse(stack S, Status(*visit)(ElemType)){ /* 从栈底到栈顶依次对栈中每个元素调用函数visit()。 *//* 一旦visit()失败,则操作失败 */while (S.top>S.base)visit(*S.base++);printf("\n");return OK;}

queue1.h

#include "ElemType.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() *//* 函数结果状态代码 */#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 *//* c3-3.h 队列的顺序存储结构(可用于循环队列和非循环队列) */#define MAXQSIZE 5 /* 最大队列长度(对于循环队列,最大队列长度要减1) */typedef struct{ElemType *base; /* 初始化的动态分配存储空间 */int front; /* 头指针,若队列不空,指向队列头元素 */int rear; /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */}queue;Status qcreate(queue *Q);Status qdestroy(queue *Q);Status qclear(queue *Q);Status qempty(queue Q);int qsize(queue Q);ElemType qfront(queue Q);Status qpush(queue *Q, ElemType e);Status qpop(queue *Q);Status qtraverse(queue Q, void(*vi)(ElemType));

实现文件

/* bo3-4.c 顺序队列(非循环,存储结构由c3-3.h定义)的基本操作(9个) */#include "queue1.h"Status qcreate(queue *Q){ /* 构造一个空队列Q */(*Q).base = (ElemType *)malloc(MAXQSIZE*sizeof(ElemType));if (!(*Q).base) /* 存储分配失败 */exit(OVERFLOW);(*Q).front = (*Q).rear = 0;return OK;}Status qdestroy(queue *Q){ /* 销毁队列Q,Q不再存在 */if ((*Q).base)free((*Q).base);(*Q).base = NULL;(*Q).front = (*Q).rear = 0;return OK;}Status qclear(queue *Q){ /* 将Q清为空队列 */(*Q).front = (*Q).rear = 0;return OK;}Status qempty(queue Q){ /* 若队列Q为空队列,则返回TRUE,否则返回FALSE */if (Q.front == Q.rear) /* 队列空的标志 */return TRUE;elsereturn FALSE;}int qsize(queue Q){ /* 返回Q的元素个数,即队列的长度 */return(Q.rear - Q.front);}ElemType qfront(queue Q){ /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */if (Q.front == Q.rear) /* 队列空 */exit(0);return *(Q.base + Q.front);}Status qpush(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 qpop(queue *Q){ /* 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */if ((*Q).front == (*Q).rear) /* 队列空 */return ERROR;(*Q).front = (*Q).front + 1;return OK;}Status qtraverse(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 "stack1.h"#include "queue1.h"#define M 5 /* 迷宫行数(包括外墙) */#define N 5 /* 迷宫列数(包括外墙) */#define D 8 /* 移动方向数,只能取4和8。(8个,可斜行;4个,只可直走) */struct /* 移动数组,移动方向由正东起顺时针转 */{int x, y;#if D==8}move[D] = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } };#endif#if D==4 }move[D] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };#endif Status Path(int maze[M][N]) /* 广度搜索法求一条迷宫路径 */ { queue q; /* 采用非循环顺序队列 */ ElemType qf, qt; /* 当前点和下一点 */ stack s; /* 采用顺序栈 */ int i, j, flag = 1; /* 当找到出口,flag=0 */ int x1, y1; /* 终点的坐标 */ printf("请输入入口的行,列(左上角为1,1)\n"); scanf("%d,%d", &qf.x, &qf.y); printf("请输入出口的行,列(右下角为%d,%d)\n", M - 2, N - 2); scanf("%d,%d", &x1, &y1); qf.pre = -1; /* 设入口(第一点)的上一点的序号=-1 */ maze[qf.x][qf.y] = -1; /* 初始点设为-1(已访问过) */ qcreate(&q); qpush(&q, qf); /* 起点入队 */ while (!qempty(q) && flag) { /* 队列中还有没被广度搜索过的点且还没找到出口 */ qf = qfront(q); /* 出队qf为当前点 */ qpop(&q); for (i = 0; i<D; i++) /* 向各个方向尝试 */ { qt.x = qf.x + move[i].x; /* 下一点的坐标 */ qt.y = qf.y + move[i].y; if (maze[qt.x][qt.y] == 1) { /* 此点是通道且不曾被访问过 */ maze[qt.x][qt.y] = -1; /* 已访问过 */ qt.pre = q.front - 1; /* 上一点处于队列中现队头减一的位置(没删除) */ qpush(&q, qt); /* 入队 */ if (qt.x == x1&&qt.y == y1) /* 到达终点 */ { flag = 0; break; } } } } if (flag) /* 搜索完整个队列还没到达终点 */ { printf("没有路径可到达终点!\n"); return ERROR; } else { screate(&s); /* 初始化s栈 */ i = q.rear - 1; /* i为待入栈元素在队列中的位置 */ while (i >= 0) /* 没到入口 */ { spush(&s, *(q.base + i)); i = (*(q.base + i)).pre; /* i为前一元素在队列中的位置 */ } i = 0; /* i为走出迷宫的步骤 */ while (!sempty(s)) { qf = stop(s); spop(&s); i++; maze[qf.x][qf.y] = i; } printf("走出迷宫的一个方案:\n"); for (i = 1; i<M - 1; i++) /* 输出maze[][],其值是走出迷宫的步骤 */ { for (j = 1; j<N - 1; j++) printf("%3d", maze[i][j]); printf("\n"); } return OK; } } void main() { int i, j; int maze[M][N]; /* 迷宫数组 */ printf("%d行%d列迷宫(不包括外墙)\n", M - 2, N - 2); for (i = 0; i<N; i++) { /* 0为墙,1为通道 */ maze[0][i] = 0; /* 北墙 */ maze[M - 1][i] = 0; /* 南墙 */ } for (i = 1; i<M - 1; i++) { maze[i][0] = 0; /* 西墙 */ maze[i][N - 1] = 0; /* 东墙 */ } printf("请按行输入迷宫结构(不包括周边,0为墙,1为通道),如1 0 0 1\n"); for (i = 1; i<M - 1; i++) for (j = 1; j<N - 1; j++) scanf("%d", &maze[i][j]); printf("迷宫结构(包括外墙):\n"); for (i = 0; i<M; i++) { for (j = 0; j<N; j++) printf("%3d", maze[i][j]); printf("\n"); } Path(maze); }



0 0