A STAR的实现和应用(c++版) 下

下面是工程里的几个文件,我把他们贴上来(有谁能告诉我直接上传吗)

1.heap.h

#ifndef __HEAP_H_
#define __HEAP_H_
#define SIZE 51*51
#define LT( a,b) ( a < b)
#define BT( a,b) ( a > b)


namespace my {
     template 
<class T>
     
void sswap( T& a,T& b)
    
{
        T tmp 
= a;
        a 
= b;
        b 
= tmp;
    }

/*
heap.h
Copyright (c) 2006.10 by yuzehua
*/

    template
< class T>
    
class Heap
    
{
    
public:
        Heap(T
* First,T* End)
        
{
            
int dc =(char *)End - (char *)First;
            m_size 
= dc/sizeof(T) ;
            assert( m_size 
< SIZE);
            m_cur 
= m_size + 1;
            m_arry 
= new T[m_size +1];

            memcpy( m_arry
+1,First,dc); //copy
            
        }

        Heap( 
int size = SIZE)
        
{
            m_size 
= size;
            m_cur 
= 1;
            m_arry 
= new T[m_size +1];
        }

        
~Heap()
        
{
            delete[] m_arry;
            m_size 
= 0;
        }

        
void make_heap(int position,int len);
        
void push_heap(T &ele);
        
void pop_heap();
        T heap_front();
        
void sort_heap(int position,int len);
        
bool is_empty();
        
int  get_idx2( T& );
        
bool in_heap( const T& );
        
void change_content(int idx, const T& val);
        T 
operator[]( int idx){return m_arry[idx];}
    
protected:
        
void heap_adj_up(T *a, int position, int len);
        
void heap_adj_down( T *a, int position,int len);
    
private:
        Heap
& operator=const Heap& other){return *this;}
        Heap(Heap
& rth){ }
        T
* m_arry;
        
int m_size;
        
int m_cur;
    }
;

    template
<class T>
void Heap<T>::heap_adj_down(T *a, int position, int len)
{
        
forint i=position; i<=len;)
    
{
        
int j;
        
if( i*2 > len)           //no children
        {
            
break;
        }

        
else if( i*2 == len)    //have one child
        {
            j 
= 2*i;
        }

        
else    //( i*2 +1 <= len)      //have two child
        {
            
if( LT(a[i*2],a[i*2+1]) ) //record smaller one
                j = 2*i;
            
else
                j 
= 2*+1;
        }

        
        
if( BT(a[i],a[j]) )
        
{
            sswap
<T>(a[i],a[j]);
            i 
= j;
        }

        
else 
            
break;
    }

}


template
< class T>
void Heap<T>::heap_adj_up( T *a, int position,int len)
{
    
forint i=position; i>1; i/=2)
    
{
        
if( LT( a[i],a[i/2])) //cur node is smaller than father
        {
            sswap
<T>(a[i],a[i/2]);
        }

    }

}


template
< class T>
void Heap<T>::make_heap(int position,int len)
{
    m_cur 
= len +1;
    
if( len == 1)
        
return;
    
forint i=len/2; i>=position; i--//from breaf -1 to the top;
    {
        heap_adj_down( m_arry,i,len );
    }

}


template
< class T>
void Heap<T>::push_heap(T &ele)
{
    assert( m_cur 
<= SIZE);
    m_arry[m_cur
++= ele;
    heap_adj_up(m_arry,m_cur
-1,SIZE);
}


template
< class T>
void Heap<T>:: pop_heap()
{
    assert(m_cur 
>=1);
    m_arry[
1= m_arry[--m_cur];
    heap_adj_down(m_arry,
1,m_cur-1);
}


template
< class T>
T Heap
<T>::heap_front()
{
    
return m_arry[1];
}


template
< class T>
void Heap<T>::sort_heap(int position,int len)
{
    assert(position 
>=1);
    assert( len
<=SIZE);
    
int start = position;
    
while(len>position)
    
{
        sswap
<T>(m_arry[start],m_arry[len]);
        heap_adj_down( m_arry,start,len
-1);
        len
--;
    }

    
}


template
< class T>
bool Heap<T>::is_empty()
{
    
if(m_cur == 1)
        
return true;
    
else
        
return false;
}


template
< class T>
void Heap<T>::change_content(int idx,const T& val)
{
    assert(idx 
>=1);
    m_arry[idx] 
= val;
    heap_adj_up(m_arry,idx,SIZE);
    heap_adj_down(m_arry,idx,m_cur
-1);
}


template
<class T>
 
int Heap<T>::get_idx2( T& ele)
{
    
for(int i=1; i<m_cur; i++)
    
{
        
if(m_arry[i] == ele)
            
return i;
    }

    
return -1;
}


template
<class T>
bool Heap<T>::in_heap(const T& ele)
{
    
int idx = -1;
    
for(int i=1; i<m_cur; i++)
    
{
        
if(m_arry[i] == ele)
        
{
            idx 
= i;
            
break;
        }

    }

    
if( idx == -1)
        
return false;
    
else 
        
return true;
}

    
}
;//namespace my


#endif

 

2 maze.h和maze.cpp

//maze.h
#ifndef __MAZE_H__
#define __MAZE_H__


void GenerateMaze();
void ShowMaze();
extern char primal_maze[51][51];

#endif

//maze.cpp
#include <time.h>
#include 
<cstdlib>
#include 
<fstream>
#include 
<iostream>
#include 
<cassert>
using namespace std;


int row=25;
int col=25;
int SIZEX_MAZE=row*2+1;
int SIZEY_MAZE=col*2+1;
const int CONST_MAZEX=51;
const int CONST_MAZEY=51;

#define RIGHT 2
#define LEFT -2
#define DOWN  1
#define UP   -1

#define Road ' '
#define Wall '1'
#define Path '#'
#define DIR   4

char primal_maze[CONST_MAZEX][CONST_MAZEY]={0};

class offsets
{
public:
    
int vert;   //chuizhi
    int horiz;    //shuiping
    void GetValue(int cvert=0,int choriz=0)
    
{
        vert
=cvert;
        horiz
=choriz;
    }

}
;

void GenerateMaze();
bool IsNewCell(int x,int y);
bool IsCovered();
bool IsLegalArea(int x,int y);

bool IsNewCell(int x,int y)
{
    
if(primal_maze[y*2-1][x*2-1]==Road)
        
return false;
    
else
        
return true;
}


bool IsCovered()
{
    
for(int i=1;i<=col;i++)
    
{
        
for(int j=1;j<=row;j++)
        
{
            
if(IsNewCell(i,j)==true)
                
return false;
        }

    }

    
return true;
}


bool IsLegalArea(int x,int y)
{
    
if(x>col || x<1 || y>row || y<1)
        
return false;
    
return true;
}


void GenerateMaze()
{
    
//step1:  设置随机种子
    srand(time(NULL));
/*
    //step2:  初始化
    for(int i=0;i<SIZEX_MAZE;i++)
        for(int j=0;j<SIZEY_MAZE;j++)
            primal_maze[i][j]=1;
*/

    memset(primal_maze,Wall,
sizeof(primal_maze));
    
int currX,currY;
    
int temp1;
    
int dir=0;
    
//step3:  设置入迷宫口处(1,1) and the exit to be (row,col)
    primal_maze[1][1]=Road;
    currX
=currY=1;
    
for(int k=0;;k++)
    
{
        dir
=0;
        
if(IsCovered()==true)
            
break;
// if we do not cut some choice in the corner,it will take a lot of time to create
        if(currX==1)
        
{
            temp1
=rand();
            
if(currY==1)
            
{
                
if(temp1%2==0)
                    dir
=RIGHT;
                
else
                    dir
=DOWN;
            }

            
else if(currY==row)
            
{
                
if(temp1%2==0)
                    dir
=RIGHT;
                
else
                    dir
=UP;
            }

        }

        
if(currX==col)
        
{
            temp1
=rand();
            
if(currY==1)
            
{
                
if(temp1%2==0)
                    dir
=LEFT;
                
else
                    dir
=DOWN;
            }

            
else if(currY==row)
            
{
                
if(temp1%2==0)
                    dir
=LEFT;
                
else
                    dir
=UP;
            }
    
        }

        temp1
=rand()%4;
        
if(temp1==0 || dir==RIGHT)
        
{
            
if(dir==RIGHT)
                dir
=0;
            currX
++;
            
//如果当前位置在边界,则回退到刚才的位置
            if(IsLegalArea(currX,currY)==false)
            
{
                currX
--;
                
continue;
            }


            
//对角区域(currY*2-1,currX*2-1)是墙,则打通相应位置
            if(IsNewCell(currX,currY)==true)
            
{
                primal_maze[currY
*2-1][currX*2-1]=Road;    //set the newcell
                primal_maze[currY*2-1][currX*2-2]=Road;    //carved into from previous primal_maze
            }

            
continue;
        }

        
else if(temp1==1 || dir==LEFT)
        
{
            
if(dir==LEFT)
                dir
=0;
            currX
--;
            
//如果当前位置在边界,则回退到刚才的位置
            if(IsLegalArea(currX,currY)==false)
            
{
                currX
++;
                
continue;
            }

            
//对角区域(currY*2-1,currX*2-1)是墙,则打通相应位置
            if(IsNewCell(currX,currY)==true)
            
{
                primal_maze[currY
*2-1][currX*2-1]=Road;    //set the newcell
                primal_maze[currY*2-1][currX*2]=Road;        //carved into from previous primal_maze
            }

            
continue;
        }

        
else if(temp1==2 || dir==DOWN)
        
{
            
if(dir==DOWN)
                dir
=0;
            currY
++;
            
//如果当前位置在边界,则回退到刚才的位置
            if(IsLegalArea(currX,currY)==false)
            
{
                currY
--;
                
continue;
            }

            
//对角区域(currY*2-1,currX*2-1)是墙,则打通相应位置
            if(IsNewCell(currX,currY)==true)
            
{
                primal_maze[currY
*2-1][currX*2-1]=Road;    //set the newcell
                primal_maze[currY*2-2][currX*2-1]=Road;    //carved into from previous primal_maze
            }

            
continue;
        }

        
else if(temp1==3 || dir==UP)
        
{
            
if(dir==UP)
                dir
=0;
            currY
--;
            
//如果当前位置在边界,则回退到刚才的位置
            if(IsLegalArea(currX,currY)==false)
            
{
                currY
++;
                
continue;
            }

            
//对角区域(currY*2-1,currX*2-1)是墙,则打通相应位置
            if(IsNewCell(currX,currY)==true)
            
{
                primal_maze[currY
*2-1][currX*2-1]=Road;    //set the newcell
                primal_maze[currY*2][currX*2-1]=Road;    //carved into from previous primal_maze
            }

            
continue;
        }

    }

}



void ShowMaze()
{
    
int i,j;
    ofstream file(
"MazeData.txt",ios::out);
    assert(
!file.fail());
//    MarkPath();
    for(i=0;i<CONST_MAZEX;i++)
    
{
        
for(j=0;j<CONST_MAZEY;j++)
        
{
            cout
<<primal_maze[i][j];
            file
<<primal_maze[i][j];
        }

        cout
<<endl;
        file
<<endl;
    }

    file.close();
}

 

3 A-Star.cpp

//yuzehua_0708@163.com
#include <iostream>
#include 
<fstream>
#include 
<string>
#include 
<vector>
#include 
<queue>
#include 
<list>
#include 
<cassert>
#include 
<algorithm>

using namespace std;

#include 
"element.h"
#include 
"heap.h"
#include 
"maze.h"

#ifdef SIZE
#undef SIZE
#endif
#define SIZE 51

#define START 'S'
#define END   'E'
#define WAY   '#'
#define BLANK ' '
#define WALL  '1'
const int s_row = 1;
const int s_col = 1;
const int e_row = 49;//10;
const int e_col = 49;
//typedef vector<string> MAZE;

#define USE_LIST (0)
#define DYNAMIC_MAZE (0)

typedef priority_queue
<element,vector<element>,COMPARE<element> > PQ;
typedef list
<element> LE;
typedef vector
<element> VE;

typedef vector
<vector<element> > MAZE;
//PQ open_list;
#if(USE_LIST)
LE open_list;
#else
my::Heap
<element> hp;
#endif
VE close_list;

MAZE maze;

class offsets
{
public:
    
int vert;   //chuizhi
    int horiz;    //shuiping
    void GetValue(int cvert=0,int choriz=0)
    
{
        vert
=cvert;
        horiz
=choriz;
    }

}
;
offsets move[
8];

void InitMark()
{
 move[
0].GetValue(1,0);
 move[
1].GetValue(1,-1);
 move[
2].GetValue(0,-1);
 move[
3].GetValue(-1,-1);
 move[
4].GetValue(-1,0);
 move[
5].GetValue(-1,1);
 move[
6].GetValue(0,1);
 move[
7].GetValue(1,1);
// memset(mark,0,sizeof(mark));
}

bool is_out(const element& ele)
{
    
if( (ele.pos.x >=SIZE)||(ele.pos.x<0
        
||(ele.pos.y >= SIZE)||(ele.pos.y <0) )
    
{
        
return true;
    }

    
else 
        
return false;
}

bool is_wall(const element& ele)
{

    
int x = ele.pos.x ;
    
int y = ele.pos.y ;

    
if( maze[x][y].terrain== WALL)
    
{
        
return true;
    }

    
else 
        
return false;
}

bool in_closelist(const element& ele)
{
    vector
<element>::iterator result = find(close_list.begin(),close_list.end(),ele);
    
if( result == close_list.end())
        
return false;
    
else
        
return true;
}

bool in_openlist(const element& ele)
{
#if(USE_LIST)
    list
<element>::iterator result = find(open_list.begin(),open_list.end(),ele);
    
if(result == open_list.end())
    
{
        
return false;
    }

    
else
        
return true;
#else
    
return hp.in_heap(ele);
#endif
}

bool is_find()
{
    element ele(END,
0,0,0,0,location(e_row,e_col));
    
/*
    list<element>::iterator result = find(open_list.begin(),open_list.end(),ele);
    if(result == open_list.end())
    {
        return false;
    }
    else
        return true;
        
*/

    
return in_openlist(ele);
}

element make_next(
const element& ele, const int dir)
{
    element dec;
    
if( dir%2 == 0)
    
{
        dec.g 
= 10;
        dec.g 
+= ele.g;
    }

    
else
    
{
        dec.g 
= 14;
        dec.g 
+= ele.g;
    }

    
//    dec.h =10*( abs(e_row - ele.pos.x) + abs(e_col - ele.pos.y) );
    dec.pos.x = ele.pos.x + move[dir].horiz;
    dec.pos.y 
= ele.pos.y + move[dir].vert;
    dec.h 
= 10*( abs(e_row - dec.pos.x) + abs(e_col - dec.pos.y) );
    dec.father 
= &maze[ele.pos.x][ele.pos.y];
    dec.dir 
= 1;//flag;
    return dec;
}

void openlist_show()
{
#if(USE_LIST)
    copy(open_list.begin(),open_list.end(),ostream_iterator
<element>(cout," ") );
    cout
<<endl;
#else
    ;
#endif
}

bool search_path(MAZE& maze)
{
    
static int searched = 1;
    element start(START,
0,0,0,NULL,location(s_row,s_col) );
#if(USE_LIST)
    open_list.push_back(start);
#else
    hp.push_heap(start);
#endif

#if(USE_LIST)
    
while!open_list.empty())
#else
    
while(!hp.is_empty() )
#endif
    
{
#if(USE_LIST)
        open_list.sort(COMPARE
<element>());

#ifdef _DEBUG
        openlist_show();
#endif
        element cur 
= open_list.front();
        close_list.push_back(cur);
        open_list.pop_front();
#else
        element cur 
= hp.heap_front();
        close_list.push_back(cur);

        hp.pop_heap();

#endif
        
for(int i=0; i<8; i++)
        
{    
            element ele 
= make_next(cur,i);
            
if(!is_out(ele) )
            
{
                
if(!is_wall(ele) && !in_closelist(ele))
                
{
#if( USE_LIST)
                    list
<element>::iterator result = find(open_list.begin(),open_list.end(),ele);

                    
                    
if(result == open_list.end())
                    
{
                        searched
++;
                        open_list.push_back(ele);
                        maze[ele.pos.x][ele.pos.y] 
= ele;
                        
                    }

                    
else // already in openlist
                    {
                        
if( result->> ele.g  ) //a better way(choose)
                        {
                            result
->= ele.g;
                            result
->father = &maze[cur.pos.x][cur.pos.y];
                        }

                    }

//                    maze[ele.pos.x][ele.pos.y] = ele;
#else
                    
                    
int idx = hp.get_idx2(ele);
                    
if( idx == -1//not in open list
                    {
                        searched
++;
                        hp.push_heap(ele);
                        maze[ele.pos.x][ele.pos.y] 
= ele;
                    }

                    
else
                    
{
                        element temp 
= hp[idx];
                        
if( temp.g > ele.g)
                        
{
                            temp.g 
= ele.g;
                            temp.father 
= &maze[cur.pos.x][cur.pos.y];
                            hp.change_content(idx,temp);
                        }

                    }

#endif
                }

            }

        }
//for
        if( is_find() )
        
{
            
return true;
        }

#ifdef _DEBUG
        cout
<<"have search: "<<searched<<endl;
#endif
    }

    
return false;
}

template
<class T>
struct fuc
{
    
void operator()( T t)
    
{
        maze[t.pos.x][t.pos.y].terrain 
= WAY;
    }

}
;
void show_path()
{
    
    element 
*ele = &maze[e_row][e_col];
    
while(ele->father != NULL)
    
{
        ele
->father->terrain = WAY;
        ele 
= ele->father;
    }

    
//    for_each(close_list.begin(),close_list.end(),fuc<element>());
}


void init_maze(MAZE& maze)
{
    GenerateMaze();
    element ele;
    vector
<element> ve(SIZE,ele);

    
for(int i=0; i<SIZE; i++)
        maze.push_back(ve);
#if (DYNAMIC_MAZE)
    ofstream file(
"MazeData.txt",ios::out);
    assert(
!file.fail());    

    
for(int i=0; i<SIZE; i++)
    
{
        
for(int j=0; j<SIZE; j++)
        
{
            maze[i][j].terrain 
= primal_maze[i][j];
            file 
<< primal_maze[i][j];
        }

        file
<< endl;
    }

    maze[s_row][s_col].terrain 
= START;
    maze[e_row][e_col].terrain 
= END;

    file.close();
#else
    ifstream fin(
"MazeData.txt",ios::in);
    assert( 
!fin.fail());
    
char buf[SIZE*2];

    
forint i=0; i<SIZE; i++)
    
{
        memset(buf,
0,sizeof(buf));
        fin.getline(buf,SIZE
*2);
        
forint j=0; j<SIZE; j++)
        
{
            primal_maze[i][j] 
= maze[i][j].terrain = buf[j];
            cout
<<buf[j];
        }

        cout
<<endl;
    }


    fin.close();
#endif

}

void show_maze(MAZE& maze)
{
    show_path();
    maze[s_row][s_col] 
= START;
    maze[e_row][e_col] 
= END;
    
for(int i=0; i<maze.size(); i++)
    
{
        
for(int j=0; j<maze[i].size(); j++)
        
{
            cout
<<maze[i][j].terrain;
        }

        cout
<<endl;
    }

}

#ifdef TEST
template
<class T>
struct test_cmp{                    //默认是大顶锥;
    bool operator()(T a,T b)
    
{
        
return  a>b;
    }

}
;
//priority_queue<int,vector<int>,test_cmp<int> > ipq;
struct A{
    
int a;
    
int b;
    
int c;
    
bool operator==(const A& other){return other.a == this->a;}
}
;
vector
<A> aa;
#endif

int main()
{
    init_maze(maze);
//    show_maze(maze);
    InitMark();
cout
<< search_path(maze)<<endl;
    show_maze(maze);
    system(
"pause");  //并未对ia[]内容排序改变.
    return 0;
}

运行代码可以看到结果了.

总结:

1.为了体验a*算法走迷宫的优点,我特地用一般的压栈回溯算法实现了一遍.对比两者,发现各有特点.对有大块空旷的maze,a*算法具有明显的优势(效率).但对于有些maze(特别是本demo算法生成的比较均匀的maze),效率比回溯法低不少(从找到出口访问过的节点 和 算法复杂度考虑.).

2.用a*找到的通路绝大多数情况下比用压栈回溯法找到的路径要优越(短),但也不是最优的,因为上面提过对h的判断只是一种预估算,具体更maze的情况息息相关.所以你可以在运行结果下有可能看到局部

##### ##
          #           的情况.显然这不是最优的情况.

 ps 欢迎大家和我交流 我的qq是105677984

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值