分享
 
 
 

关于堆栈与队列使用的小思考(1)

王朝other·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

关于堆栈与队列使用的小思考:

从经典的问题开始

1.走迷宫问题:

首先还是说说问题大概情况,走迷宫问题从入口出出发,顺着周围可走的通道向前探索,目的很简单到达出口就行了.估计你也许听得不耐烦了,好吧,接下来让我们直截了当地说明它在C语言里面的数据描述。

我们用一个二维的数组表示的矩阵来表示一个平面上的迷宫,其中数组的每一个元素代表了一个通道,如果值为1则表示有障碍,为0则表示可通。为了方便在迷宫的最外面设置一层设置了障碍。因此虽然迷宫的大小是10*15而数组的大小却是12*17。

其中迷宫的入口位于数组的(1,1)处,而出口位于(10,15)处。用dx,dy表示搜索方向上的变化。

OK!接下来就让我们一起来走这个抽象的迷宫~~~~

#define MU 10 //迷宫的行数

#define NU 15 //迷宫的列数

int Labyrinth[MU+2][NU+2]={{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1},

{1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

{1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}

};

//移动方向上的增量

// 东 东南 南 西南 西 西北 北 东北

int dx[DIRECTIONS]={ 0, 1, 1, 1, 0, -1, -1, -1};

int dy[DIRECTIONS]={ 1, 1, 0, -1, -1, -1, 0, 1};

解决方案:

一般采用穷举搜索这种通用比较强,却在某种程度上牺牲了不少时间和内存空间的方法。

简单地说就是可通的话就走,如果有障碍的话就拉倒,并且返回上一步换一个方向之后继续向前探索,直到出口。

因为问题中需要保存已经走过的路径,所以一般大家第一个想法也许都会想到了用堆栈来解决,我的教科书上也使用了用堆栈解决的方法,今天我们不用堆栈来解决,换用队列来解决。

#define MAX_SIZE 400;

Struct node

{

int x,y; //搜索时当前通道的位置

int pre; //上一个通道在队列中的位置

}Queue[MAX_SIZE];

int gotoLabyrinth ( )

{

int i, j, x, y, v ; //(i,j)

int front , rear, finded ;

Queue[1].x=1; Queue[1].y=1; Queue[1].pre=0;

front=1;rear=1; Labyrinth[1][1]=-1;

while(front<=rear)

{

x= Queue[front].x;

y= Queue[front].y;

for(v=1;v<=8;v++) //循环扫描每个方向

{

i=x+zx[v]; //选择一个前进方向i,j

j=x+zy[v];

if(Labyrinth[i][j]==0) //如果可走

{

rear++; //入队尾

Queue [rear].x=i;

Queue[rear].y=j;

Queue[rear].pre=front;

Labyrinth[i][j]=-1; //已经访问过了

} `

if(i==m&&j==n) return 1;

}

front++;

}

return 0;

}

接下来轮到我们经典堆栈的应用了

struct node

{

int x,y; //所在迷宫的当前的坐标位置

int direction; //下一个位置的方向

} Stack[MAX_SIZE]; // 程序中用到的堆栈

int gotoLabyrinth()

{

int i = 1,j = 1;

do

{

if( Labyrinth[i][j] == 0)

{

push(i,j,0);

Labyrinth[i][j] = -1;

if( i==MU && j==NU ) return (1);

else

{

i += dx[Stack[top].direction]; //向正东方继续搜索

j += dy[Stack[top].direction];

}

}

else

{

if( top!=0 && stack[top].direction< DIRECTIONS-1 )

{

Stack[top].direction++; //切换一个方向之后继续搜索

i=Stack[top].x+ dx[Stack[top].direction];

j=Stack[top].y+ dy[Stack[top].direction];

}

if(Stack[top].direction >= DIRECTIONS-1&&top!=0)

{

top--; //如果此路不通,退栈之后,换一条路

}

}

}while(top!=0);

return (0);

}

堆栈和队列在迷宫问题里面的应用,就是其在图的遍历问题中的应用,这些都反映了堆栈和队列应用的本质。

图的遍历

问题描述:

假设图采用邻接表的存储结构

定义如下:

#define MAXVEX 100

struct edgenode

{

int adjvex; //邻接点序号

char info; // 邻接点信息

struct edgenode *next;

};

struct vexnode

{

char data; //节点信息

struct edgenode *link;

};

typedef struct vex node adjlist[MAXVEX];

相信上面的图的描述方式大家都不会陌生

1. 深度优先搜索法

利用堆栈保存遍历过的节点信息

void dfs(adjlist g, int v, int n)

{

struct edgenode *stack[MAXVEX],*P;

int visited[MAXVEX] ,i;

int top=0;

for (i=o;i<n;i++) visited[i]=0;

printf(“%d”,v);

p=g[v].link;

while(top>0 || p!=NNLL)

{

while(p!=NULL)

if(visited[p->adjvex]==1) //如果已经访问过了

p=p->next;

else

{

printf(“%d”,p->adjvex);

visited[p->adjvex]=1;

top++; //将访问的节点入栈

stack[top]=p;

p=g[p->adjvex].link;

}

if(top>0)

{

p=stack[top];

top--; //退一步找,回溯查找被访问过的节点的未被访问过的邻接点

p=p->next;

}

}

}

2. 宽度优先搜索法

采用队列来解决问题

int visited[MAXVEX];

int queue[MAXVEX];

void bfs(adjlist adj, int vi )

{

int front=0,rear=1; //队列的头和尾部

int v,i;

struct edgenode *p;

for(i=0;i<MAXVEX;i++)

{

visited[vi]=1;

printf(“%d”,v);

queue[rear]=vi;

while(front!=rear)

{

front =(front+1) %MAXVEX;

v=queue[front];

p=adj[v].link; //找到V的邻接点并且访问所有未被访问过的邻接点

while(p!=NULL)

{

if(visited[p->adjvex]==0) //若未被访问则置访问标志且入队列尾

{

visited[p->adjvex.]==1;

printf(“%d”,p->adjvex);

rear=(rear+1) %MAXVEX;

queue[rear]=p->adjvex;

}

p=p->next;

}

}

}

}

小结:相信不用我说任何人都已经知道了,迷宫的堆栈解法就是图的深度遍历问题,迷宫的队列解法其实就是图的宽度遍历问题,在编程的过程中可以发现其实还有很多问题都可以抽象成对于图的操作问题,看来啊学好了数据结构真的可以解决不少实际问题。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有