本文使用到的队列的实现。
列车重排问题、电路布线问题、图元识别问题,在以前都用过栈的数据结构来实现过(基于栈的应用–列车重拍问题、迷宫老鼠问题)。本文采用队列的实现,改变一些问题要求,但吸收、采用了上次同类型问题中的算法思想。
列车车厢重排问题
相较于使用栈来实现车厢重拍列的算法,主要区别有:
缓冲轨道的改变,在栈实现中,我们要求缓冲轨道先进后出(FILO),而在本文中,我们要求其先进先出(FIFO)。因此,用栈作缓冲轨道的话,缓冲轨道的选择原则是选择进入栈顶大于当前车厢序号中最小的一个轨道。而用队列作缓冲轨道,缓冲轨道的选择原则是选择进入队尾小于当前车厢序号中最大的一个轨道。
同时railroad函数应该做以下修改:
1.缓冲轨道数量减少1,留作输入轨道的车厢直接进入输出轨道。
2.轨道的类型改为queueArray
具体实现:
//=========================列车车厢重排=================================
//相较于使用栈来实现车厢重拍列的算法,主要区别有:
//用栈作缓冲轨道的话,选择原则是选择进入大于当前车厢序号中最小的一个轨道
//而用队列作缓冲轨道,选择原则是选择进入小于当前车厢序号中最大的一个轨道
//同时railroad函数应该做以下修改:1.缓冲轨道数量减少1,留作输入轨道的车厢直接进入输出轨道
//2.轨道的类型改为queueArray
namespace carriageRearrange {
//全局变量
queueArray<int>* tracks;//缓冲轨道数组
int numberOfCarriages; //输入车厢数量
int numberOfTracks; //缓冲轨道数量 相较于栈实现的轨道数量要减1
int smallestCarriage; //在缓冲轨道中最小的车厢号(位于队列的队首位置)
int itsTrack; //最小车厢对于的缓冲轨道
void outputFromHoldingTrack();
bool putIntoHoldingTrack(int carriage);
bool railroad(int input[],int _numberOfCarriages,int _numberOfTracks) {
numberOfCarriages = _numberOfCarriages;
numberOfTracks = _numberOfTracks-1;//留一条轨道,供车厢输入轨道直接进入输出轨道
tracks = new queueArray<int> [numberOfTracks+1];
int nextCarriageToOutput = 1;//下一节应该进入输出轨道的车厢序号
smallestCarriage = numberOfCarriages + 2;//初始缓冲轨道区没有车厢
for (int i = 0; i < numberOfCarriages;++i) {
if (nextCarriageToOutput == input[i]) {
cout << "Move carriage[" << input[i]
<< "] from input rail to output rail" << endl;
++nextCarriageToOutput;
//如果缓冲轨道存在可以输出的车厢号
while (smallestCarriage == nextCarriageToOutput) {
outputFromHoldingTrack();
++nextCarriageToOutput;
}
}
else
if (!putIntoHoldingTrack(input[i])) {
cout << "Rearranged failed!" << endl;
return false;//找不到合适的缓冲轨道了 则排序失败
}
}
delete[] tracks;
return true;
}
void outputFromHoldingTrack() {
tracks[itsTrack].pop();
cout << "Move carriage[" << smallestCarriage << "] from holding track["
<< itsTrack << "] to output rail" << endl;
//更新缓冲区中最小的车厢序号和所在缓冲轨道
smallestCarriage = numberOfCarriages + 2;
for (int i = 1; i <= numberOfTracks;++i) {
if (!tracks[i].empty() && tracks[i].front() < smallestCarriage) {
smallestCarriage = tracks[i].front();
itsTrack = i;
}
}
}
bool putIntoHoldingTrack(int carriage) {
int bestTrack=0;//缓冲区最适合入队列的轨道
int bestBack=0;//最适合轨道中的队尾车厢序号
//遍历缓冲轨道 找到最适合的bestTrack
for (int i = 1; i <= numberOfTracks;++i) {
if (!tracks[i].empty()) {
//当前缓冲轨道满足条件
if (carriage > tracks[i].back() && tracks[i].back()>bestBack) {
bestTrack = i;
bestBack = tracks[i].back();
}
}
else {
//当前轨道为空
if (bestTrack == 0)//只选择第一次的空轨道
bestTrack = i;
}
}
//没找到
if (bestTrack == 0)
return false;
//找到bestTrack后 将当前车厢放入它的队尾
tracks[bestTrack].push(carriage);
cout << "Move carriage[" << carriage << "] from input track"
<< " into holding track[" << bestTrack << "]" << endl;
//更新最小的车厢和它所在的缓冲轨道
if (carriage < smallestCarriage) {
smallestCarriage = carriage;
itsTrack = bestTrack;
}
return true;
}
}
int main() {
int train[]{
3,6,9,2,4,7,1,8,5 };
if (carriageRearrange::railroad(train, 9, 3))
cout << "Rearranged completed!";
return 0;
}
电路布线问题
m*n矩阵中,找到给定点a到给定点b的最短路径来布线,减少信号的延迟。我们采用了老鼠迷宫问题中许多重要的算法思想,比如同老鼠迷宫问题一样,我们同样给外围加墙、将走过的地点标记上距离信息。需要注意的是,因为需要标记距离信息,同时为了避免和我们用1表示路劲不可达的冲突,我们将所有距离+2,也就是起始点a的距离信息为2,a的周围四格(右、下、左、上)为3(如果可达的话)。
具体实现:
//========================电路布线问题 用到了很多迷宫老鼠的算法思想 在求解可达的同时求得最短路径========================
namespace findShortestPath {
size_t** maze;//0表示可达但没达到的位置;1表示不可达被封锁的位置;其余表示该点到起始点的距离
//(需要+2以防止出现起点周围距离为1和不可达点1的表达冲突
size_t mazeRow, mazeCol;
struct position {
//每个点的结构
size_t row;
size_t col;
position() = default;
position(size_t _row,size_t _col):row(_row),col(_col){
}
};
std::ostream& operator<<(std::ostream& os, const position& p) {
os << "(" << p.row << "," << p.col << ")" << ends;
return os;
}
stackArray<position> path;//存储最短路径 因为程序从终点倒回起点构造路径 因此选择LIFO的栈结构
queueArray<position> neighbors;//存储每个点周围的可达邻点
bool initialMaze(const string& filename) {
std::fstream ifs(filename);
if (!ifs)
return false;
ifs >> mazeRow >> mazeCol;
maze = new size_t *