大三上学期,使用Java不完整实现Lee寻址算法。

大三上学期,上了一门Data Structure and Algorithms 也就是数据结构与算法,当时刚来到国外,上课听讲也是半懂半晕的,基本都是靠课下自己重新看讲义,自己实践。

作为最后的结课项目,要求实现在电路设计中经常用的寻找路径算法,Lee算法虽然是一项比较早的技术,但是老师认为可以反映一下我们的学习情况。写下来用了一个星期多些,虽然代码短但是经常要在debug模式里跟着程序过着看问题,浪费了很多时间和脑子。


算法分析

Lee算法是在一个一定大小的表格中,从某点向外延展波形,当波形遇到目标点后停止,再根据波形backtracking到起点,画出路径。

这个算法的实现有很多衍生的改进方案,最基本的是单波寻址,波形只从出发点扩散,然后backtracking。

第一个改进方案是从起点与目的地两点同时扩散波形,当波形相遇后从中间点扩散。


这个解决两点扩散很容易,但当时遇到的问题其实并不在这里,问题在波形相遇后的backtracking问题上。在寻找路径中,转向次数是算进路径评分中的,具体如下图,两图都是用了5个单位,但是左图转向两次,右图转向一次,右图最优。这里需要对循环条件进行特殊判断。


第二个改进方案是每次波形扩大一圈,从新的一圈展开新波形,这个能很好的减少资源浪费,可以避免没有意义的点同时减少程序内的循环判断。这个从图上很难看出来,但是从代码上会发现他的益处。


实现及代码

具体的实现方法是利用int二维数组作为grid,并根据读取的文件初始化数组,如resize与赋值。可以通过的格子都会被赋值为0,芯片覆盖的以及其他路线经过的格子被赋值为固定数值来予以区分,因为老师还要求有对输入文件中规定的参数进行检测,还需检测芯片是否重合,给出的路线是否最短,最优,同时做一个基于grid大小变化的性能图。

最后的文件有4个,Lee, function, verification以及measurement。分别用来实现lee算法,提供定义grid功能,检验错误,测试性能。

Lee的实现方法如下:

package Test;

import static Test.functions.*;
import java.util.ArrayList;

public class Lee {
	ArrayList<int[]> wave = new ArrayList<int[]>();
	/*
	 * Start: x1,y1 are the coordinate of goal point; i,j is one point of the
	 * current wave front. grid[i][j] will tell the expandWave the current k
	 * value.
	 */
	void Start(int x0,int y0,int x1, int y1) {
		int[] q = {x0,y0};
		wave.add(q);
		for (int m = 0; m < 10000; m++) {
			int[] p = (int[]) wave.get(m);
			int i = p[0];
			int j = p[1];
			if (expandWave(grid[i][j], i, j, x1, y1) == 1)
				return;
		}
	}
	/*
	 * expandWave will expand from the current point grid[i][j]. For every
	 * successful expand on each direction, the ArrayList wave will store a
	 * small array q which contains the coordinate. If the goal was found, then
	 * return 1 and end the loop;
	 */
	int expandWave(int k, int i, int j, int x1, int y1) {
		if (i + 1 < gridW && grid[i + 1][j] == 0) {
			grid[i + 1][j] = k + 1;
			int[] q = { i + 1, j };
			wave.add(q);						//Store WaveFront
			if (i + 1 == x1 && j == y1)
				return 1;
		}
		
		if (j + 1 < gridH && grid[i][j + 1] == 0) {
			grid[i][j + 1] = k + 1;
			int[] q = { i, j + 1 };
			wave.add(q);
			if (i == x1 && j + 1 == y1)
				return 1;
		}

		if (i - 1 >= 0 && grid[i - 1][j] == 0) {
			grid[i - 1][j] = k + 1;
			int[] q = { i - 1, j };
			wave.add(q);
			if (i - 1 == x1 && j == y1)
				return 1;
		}

		if (j - 1 >=0 && grid[i][j - 1] == 0) {
			grid[i][j - 1] = k + 1;
			int[] q = { i, j - 1 };
			wave.add(q);
			if (i == x1 && j - 1 == y1)
				return 1;
		}
		return 0;
	}

	/*
	 * backtracking will start from the goal point and back to the start point
	 */
	void backtracking(int x1, int y1, int n) {
		int k = grid[x1][y1];
		while (k > 1) {
			while (x1 + 1 < gridW && grid[x1 + 1][y1] == k - 1 && k!=1) {
				x1++;
				k--;
				grid[x1][y1] = T + n;
			}
			while (x1 > 0 && grid[x1 - 1][y1] == k - 1 && k!=1) {
				x1--;
				k--;
				grid[x1][y1] = T + n;
			}
			while (y1 + 1 < gridH && grid[x1][y1 + 1] == k - 1 && k!=1) {
				y1++;
				k--;
				grid[x1][y1] = T + n;
			}
			while (y1 > 0 && grid[x1][y1 - 1] == k - 1 && k!=1) {
				y1--;
				k--;
				grid[x1][y1] = T + n;
			}
		}
	}
}


另外单独写了一个function类来方便测试,如下:

package Test;

public class functions {
	static int gridW=77, gridH=77;
	static int [][] grid;
	final static int O = 1000; //Occupied;
	final static int T = 1500; //Tracks,Only for the backtracking;
	final static int J = 1200; //The start value of Joints;

	//This will reset the grid
	static int[][] createGrid(int W,int H){
		int[][] grid = new int[H][];
		for (int i=0;i<grid.length;i++)
			grid[i] = new int[W];
		return grid;
	}
	//This will clean the search numbers
	static void cleanGrid(){
		for (int x = 0; x < gridH; x++) {
			for (int z = 0; z < gridW; z++) {
				if (grid[z][x] <1000){
						grid[z][x] = 0;
					}
				}
			}
	}
	//This will print out the current grid.
	//0,print the current grid without clean
	//1,clean the grid
	static void printgrid(int i){
		for (int x = 0; x < gridH; x++) {
			for (int z = 0; z < gridW; z++) {
				if (grid[z][x] <1000){
					if (i == 1){
						grid[z][x]=0;
						System.out.print("-");
					}
					if (i == 0){
						if (grid[z][x] > 9)
							System.out.print((char)(grid[z][x]-10+'A'));
						else{
							if (grid[z][x]==0)
								System.out.print("-");
							if (grid[z][x]>0)
								System.out.print(grid[z][x]);
						}
					}
				}
				//print other kind of values
				if (grid[z][x] == O)
					System.out.print("*");
				if (grid[z][x] > T)
					System.out.print((char)(grid[z][x]-T+'A'-1));
				if (grid[z][x] > J && grid[z][x] < T)
					System.out.print((char)(grid[z][x]-J+'a'-1));
			}
			System.out.println(" "); 
		}
	}
	
}

使用例子:

if (w[0].equals("J")) {
				int x0 = Integer.parseInt(w[1]);
				int y0 = Integer.parseInt(w[2]);
				int x1 = Integer.parseInt(w[3]);
				int y1 = Integer.parseInt(w[4]);
				grid[x0][y0] = 1; 				// Set the start point as 1;																							
				n++;							// The n helps to distinguish different Tracks and joints;
				long startTime = System.nanoTime();
				Lee lee = new Lee(); 			// Initialize Lee and pass the start point;
				lee.Start(x0, y0, x1, y1); 		// Pass the goal point;
				lee.backtracking(x1, y1, n);
				long timeCost = (System.nanoTime() - startTime);
				time += timeCost;
				grid[x0][y0] = J + n;
				grid[x1][y1] = J + n;
				cleanGrid();
			}

 


另外两个文件与实现算法无关就不放了,给几张图吧。

图上不上来,有空再放吧。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值