数据结构之迷宫求通路《回溯法与栈》

关于回溯与栈的最初的迷茫之处:刚开始听完迷宫问题求通路的时候,我就有一个疑问:将文件的内容传递给数组,再进行压栈,这两个(数组与栈空间)明明不是同一块空间,为什么当我释放栈的时候,当前路径的尾节点能够变为上一个节点,从而使得上一个节点成为了新路径的尾节点 ?《希望你们能看懂我说的什么意思,嘿嘿》,如果就这么用文字描述答案虽然能说通但是印象并不会太深刻,所以不说废话了。直接上代码。

//Stack.h  :这里我自己实现的模板栈
#pragma once 
#include<iostream>
#include<assert.h>
using namespace std;

template<class T>
class Stack
{
public:
    Stack()
        :_a(new T[1])
        ,_sz(0)
        ,_capacity(0)
    {}
    ~Stack()
    {
        if(_a)
        {
            delete[] _a;
            _sz = 0;
            _capacity = 0;

        }
    }
public:
    void Push(const T& d);
    void CheckCapacity();   
    bool Empty();
    void Pop();
    T& Top();
    void Dislplay();
protected:
    T* _a;
    int _sz;
    int _capacity;
};

template<class T>

void Stack<T>::CheckCapacity ()
{
    if(_sz == _capacity )
    {
        T* tmp =new T[_capacity * 2+ 3];
        for(int i = 0; i < _sz;i++)
        {
            tmp[i] = _a[i];
        }
        delete[] _a;
        _capacity = _capacity * 2 + 3;
        _a = tmp;
    }
}

template<class T>

void Stack<T>::Push(const T& d)
{
    CheckCapacity();
    _a[_sz] = d;
     _sz++;
}



template<class T>

void Stack<T>::Pop()
{
    assert(_sz > 0);
    _sz--;

}

template<class T>

T& Stack<T>::Top()
{
    return _a[_sz-1];
}


template<class T>

bool Stack<T>::Empty()
{
    return _sz == 0;
}

template<class T>
void Stack<T>::Dislplay ()
{
    for(int i = 0;i<_sz ;i++)
    {
        cout<<_a[i]<<" ";
    }
    cout<<endl;
}
//Maze.h
#pragma once

#include"stack.h"
#define N 10
void InitMaze(int *m) //从文件中读取数据到数组Maze中
{
    FILE* fout = fopen("Maze.txt","r");
    for(int i = 0; i < N;i++)
    {
        for(int j = 0; j< N ;)
        {

            char value = fgetc(fout);
            if(value == 32|| value == 10)
                continue;
            m[i*N+j] =  value - '0';
            ++j;
        }
    }
}

struct Pos  
{
    int _row;
    int _col;

};

bool CheckPos(int row,int col,Pos p,int *m)//只有当数据为0的时候才考虑上下左右
{
    if((p._row >= 0) &&(p._row < row)&&(p._col >= 0)&&(p._col < col)&&(m[p._row * N+ p._col]==0))
        return true;
    return false;
}

bool Through(int row,int col,Pos next)
{
    if((next._row == row-1)||(next._col == col-1))
        return true;
    return false;
}

bool GetPath(int row,int col,int* m,Stack<Pos>& s,Pos enter)
{
    s.Push (enter);
    m[enter._row * N+enter._col ] = 2;
    while(!s.Empty ())
    {     
        Pos cur = s.Top ();//cur为最新压入栈中的数据,栈顶的元素就是迷宫目前能走的最后一步
        Pos next = cur;//是以当前节点为中心进行上下左右节点测试的坐标变量
        //上
        next._row = next._row -1;//next就是坐标,栈存放的就是数组的坐标,当路径被封死,就要释放栈顶,**每当pop()后**next要在该节点(此处不是pop()的节点)进行上下左右的分析,来判断是否有下一个可以走的节点,若没有,则继续pop(),不断的往该节点的上一个节点走,**这就是回溯**。直到某一个尾节点的上下左右有通路,再从新进行探索。
        //回到最前面的问题:压栈的是数组元素的坐标,当栈被释放,因为next发生改变。所以m[next._row *N+next._col ]就成为了上一个节点,所以当我释放栈的时候,当前路径的尾节点能够变为上一个节点,从而使得上一个节点成为了新路径的尾节点 
        if(CheckPos(row,col,next,m))
        {
            s.Push (next);
            m[next._row *N+next._col ]=2;
            continue;
        }
        next._row = next._row +1;

        next._row = next._row +1;         //if(CheckPos(row,col,next,m))
        {
            s.Push (next);
            m[next._row *N+next._col ]=2;
            continue;
        }
        next._row = next._row -1;

        next._col = next._col -1;         //if(CheckPos(row,col,next,m))
        {
            s.Push (next);
            m[next._row *N+next._col ]=2;
            continue;
        }
        next._col = next._col +1;

        next._col = next._col +1;        //if(CheckPos(row,col,next,m))
        {
            s.Push (next);
            m[next._row *N+next._col ]=2;
            continue;
        }
        next._col = next._col -1;        

        if(Through(row,col,next))
            return true;
        s.Pop ();                         //当上下左右都无法走的时候
    }
    return false;

}
void PrintMaze(int* m)
{
        for(int i = 0; i < N;i++)
    {
        for(int j = 0; j< N ;j++)
        {
            cout<<m[i*N+j]<<" "; 
        }
        cout<<endl;
    }
        cout<<endl;
}
//Maze.cpp

#include"stack.h"
#include"Maze.h"    
using namespace std;


void test()
{
    Stack<int> s1;
    s1.Push (1);
    s1.Push (2);
    s1.Push (3);
    s1.Push (4);
    s1.Push (5);
    s1.Dislplay ();
    cout<<s1.Empty() <<endl;
    cout<<s1.Top()<<endl;
    s1.Pop ();
    s1.Dislplay ();
}


void MazeTest()
{
    Stack<Pos> s1;
    Pos e ;
    e._row = 1;
    e._col = 0;
    int maze[N][N];
    InitMaze((int*)maze);
    PrintMaze((int*)maze);
    GetPath(N,N,(int*)maze,s1,e);
    PrintMaze((int*)maze);

}
int main()
{
    //test();
    MazeTest();
    return 0;
}

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值