c++ 数据结构 队列应用之电路布线

1.问题描述:

    把布线的区域画成一个网格,该网格用一个二维数组来存储,其中通路用0值表示,墙壁用1值表示,从该区域内的某一点向另一点布线,求布线的最短路径与路径长度。

2.解决办法:

    把起点的值设置为2(与0和1区分开),然后把它四周走的通的点赋值为3,然后把值为3的点的四周走得通的点赋值为4,依次类推,直到走不下去或者赋值到终点,然后从终点按照数值依次减小的路线往回走即可找到最短路径。实现该操作需要队列这种数据结构,因为它有先进先出的功能。

3.实现代码:

# include"LinkedQueue.h"
# include<iostream>
const int m=7;
bool FindPath(offsets& start,offsets& finish,int& pathLen,offsets *&path,offsets move[4],int grid[][m+2]);
using namespace std;
void main(){
	int pathLen;           //路径长度
	offsets* path;         //路径数组指针
	offsets move[4]={{-1,0},{0,1},{1,0},{0,-1}}; //移动数组:向四个方向移动
	int grid[m+2][m+2];    //电路网格数组:值为0,可布线;值为1,不可布线需绕行
	for(int i=0;i<=m+1;i++){      //把网格的四周元素都置为1,表示墙不可通过;
		grid[0][i]=grid[m+1][i]=1;
		grid[i][0]=grid[i][m+1]=1;
	}
	for(int i=1;i<=m;i++)    //赋值1与0:设置障碍与通路
		for(int j=1;j<=m;j++)
			cin>>grid[i][j];
	offsets start={3,2};      //起点与终点
	offsets finish={4,6};
	if(FindPath(start,finish,pathLen,path,move,grid)){  //调用找路函数:起点,终点,移动数组,与电路网格作为参数传递;路径与路径长度作为参数实现返回
		cout<<pathLen<<endl;
		for(int i=0;i<=pathLen-1;i++)
			cout<<path[i]<<" "<<endl;
}
	system("pause");
}
bool FindPath(offsets& start,offsets& finish,int& pathLen,offsets*& path,offsets move[4],int grid[][m+2]){   //找路函数
	if(start.col==finish.col&&start.cow==finish.cow) {      //起点恰好等于终点
		pathLen=0;
		return true;
	}
	offsets here,nbr; //here为此刻所处的位置,nbr为与here相邻的位置
	here.col=start.col;  //一开始处在起点
	here.cow=start.cow;
	grid[here.cow][here.col]=2; //赋值为2是为了与1和0分别开
	LinkedQueue Q;    
	do{
	for(int i=0;i<4;i++){     //往四个方向试探  先进先出,保证赋完所有3后在赋4,可保证找到的是最短路径
		nbr.cow=here.cow+move[i].cow; 
		nbr.col=here.col+move[i].col;
		if(grid[nbr.cow][nbr.col]==0){     //走得通
			grid[nbr.cow][nbr.col]=grid[here.cow][here.col]+1; //把此刻点的值+1赋给相邻点
			if(nbr.cow==finish.cow&&nbr.col==finish.col) break; //如果该点为终点 退出循环
			Q.EnQueue(nbr); //相邻点的位置进队
		}
	}
	if(nbr.cow==finish.cow&&nbr.col==finish.col) break;//内循环中找到终点,跳到此处,退出外循环
	if(Q.isEmpty())  //表示此刻所处的点被封锁,无路可走
		return false;
	Q.DeQueue(here); //栈顶元素退栈,并赋值给here,继续往下走
	}while(1);
	pathLen=grid[nbr.cow][nbr.col]-2; //因为起点为2,路径长度为终点值-2
	path=new offsets[pathLen];       //分配pathLen长度的储存空间来储存路径
	if(path==NULL){
		cerr<<"存储分配错误"<<endl;
		exit(1);
	}
	here.cow=finish.cow; //从终点回溯
	here.col=finish.col;
	for(int i=pathLen-1;i>=0;i--){ //存走过的路径
		path[i].cow=here.cow;
		path[i].col=here.col;
		for(int j=0;j<4;j++){
			nbr.col=here.col+move[j].col;
			nbr.cow=here.cow+move[j].cow;
			if(grid[nbr.cow][nbr.col]==i+2)  //该点是来时的点
				break;
		}
		here.cow=nbr.cow;     //从来时的点继续往回走
		here.col=nbr.col;
	}
	return true;
}
链式队列:

struct LinkNode{          //自定义数据类型:结点
	offsets date;    
	LinkNode* link;
	LinkNode(LinkNode* ptr=NULL):link(ptr){}
	LinkNode(const offsets x,LinkNode* ptr=NULL):date(x),link(ptr){}
};
class LinkedQueue{     //链式队列
private:
	LinkNode* front;      //队头指针
	LinkNode* rear;       //队尾指针
public:
	LinkedQueue():front(NULL),rear(NULL){}    //构造函数:构造空队列
	void makeEmpty();        //将表置空
	~LinkedQueue(){ makeEmpty();}   //析构函数:(*不能直接用delete清空全部存储空间的析构函数往往需要调用另一个函数帮助清空)
	bool EnQueue(offsets& x);    //进队函数
	bool DeQueue(offsets& x);    //出队函数
	bool getFront(offsets& x);    //取队头
	bool isEmpty(){ return (front==NULL)?true:false;}  //判断表空
	int getSize(); //求队列元素个数
	friend ostream& operator<<(ostream& ostr,LinkedQueue& Q);      //输出运算符重载
	friend ostream& operator<<(ostream& ostr,offsets& x);
};
实现细节:

# include<iostream>
# include"LinkedQueue.h"
using namespace std;
void LinkedQueue::makeEmpty(){
	LinkNode* ptr;
		while(isEmpty()==false){  
			ptr=front;
	        front=front->link;
	        delete ptr;
			rear=NULL; //删除尾结点后尾指针需要置空
		}
}
bool LinkedQueue::EnQueue(offsets& x){  
	if(isEmpty()){
		front=rear=new LinkNode(x);
		if(front==NULL) return false;
	}
	else{
		rear->link=new LinkNode(x);
		if(rear->link==NULL) return false;
		rear=rear->link;
	}
	return true;
}
bool LinkedQueue::DeQueue(offsets& x){
	if(isEmpty()) return false;
	else{
		x=front->date;
		LinkNode* current=front;
		front=front->link;
		delete current;
	}
	return true;
}
bool LinkedQueue::getFront(offsets& x){
	if(isEmpty()) return false;
	else{
		x=front->date;
		return true;
	}
}
int LinkedQueue::getSize(){
	int count=0;
	LinkNode* ptr=front;
	while(ptr!=NULL){
		count++;
		ptr=ptr->link;
	}
	return count;
}
ostream& operator<<(ostream& ostr,offsets& x){
	ostr<<x.cow<<" "<<x.col<<endl;
	return ostr;
}
ostream& operator<<(ostream& ostr,LinkedQueue& Q){
	LinkNode* current=Q.front;int i=0;
	while(current!=NULL){
		ostr<<++i<<":"<<current->date<<endl;
		current=current->link;
	}
	return ostr;
}



	


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值