当前位置:首页 > 技术分析 > 正文内容

n*n的二维四向链表,初始化、遍历、最短路径、旋转

一、定义四向链表节点类Node:

public class Node<T> {
	private T value;
	private Node<T> up;
	private Node<T> down;
	private Node<T> left;
	private Node<T> right;
	
	public Node() {
	}
	public Node(T value) {
		this.value = value;
	}
	public T getValue() {
		return value;
	}
	public void setValue(T value) {
		this.value = value;
	}
	public Node<T> getUp() {
		return up;
	}
	public void setUp(Node<T> up) {
		this.up = up;
	}
	public Node<T> getDown() {
		return down;
	}
	public void setDown(Node<T> down) {
		this.down = down;
	}
	public Node<T> getLeft() {
		return left;
	}
	public void setLeft(Node<T> left) {
		this.left = left;
	}
	public Node<T> getRight() {
		return right;
	}
	public void setRight(Node<T> right) {
		this.right = right;
	}
	
	public String toString() {
		String s = "{v:"+this.value+", u:"+ 
				(up==null?null:up.value) +", d:"+
				(down==null?null:down.value)+", l:"+
				(left==null?null:left.value)+",r:"+
				(right==null?null:right.value)+
				"}";
		return s;
	}
}

二、初始化n*n二维四向链表:genNode

public class NodeUtil {
	//生成n*n的二维四向链表,节点的value从1开始递增
	//节点的up、down、right、left和二维的结构相对应关联
	public Node<Integer> genNode(Integer n){
		Node<Integer> head;
		
		if(n<=0) return null;
		
		Integer val = 1;
		Node<Integer>[][] nodes = new Node[n][n];
		
		//new
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				nodes[i][j] = new Node<Integer>(val++);
				if(i>0) { 
					nodes[i][j].setUp(nodes[i-1][j]);
					nodes[i-1][j].setDown(nodes[i][j]);
				}
				if(j>0) {
					nodes[i][j].setLeft(nodes[i][j-1]);
					nodes[i][j-1].setRight(nodes[i][j]);
				}
			}
		}
		head = nodes[0][0];
		return head;
	}
}

三、遍历右下
在类NodeUtil里增加方法printToRightDown,打印该节点和它右下部分的二维节点

//打印该节点和它右下部分的二维节点
public void printToRightDown(Node<Integer> node) {
	Node<Integer> rowNode,colNode;
	
	System.out.println("#打印节点以及右下的二维节点:");
	
	rowNode = node;
	while(rowNode!=null) {
		colNode=rowNode;
		while(colNode!=null) {
			System.out.print(colNode.getValue()+"\t");
			colNode = colNode.getRight();
		}
		System.out.println("");
		rowNode = rowNode.getDown();
	}
}

四、遍历全部
从任意节点出发,遍历所有节点,不可重复遍历
在类NodeUtil里增加方法:visitWhole方法、visitNode方法

private void visitNode(Node<Integer> node) {
	if (node != null) {
		System.out.println(node.getValue());
	}
}

//给任意节点,遍历所有节点,不可重复遍历
public void visitWhole(Node<Integer> node) {
	
	System.out.println("#遍历所有节点:");
	
	if(node!=null) this.visitNode(node);
	
	Node<Integer> up, down, left, right;

	up = node.getUp();
	while(up!=null) {
		this.visitNode(up);
		up = up.getUp();
	}
	
	down = node.getDown();
	while(down!=null) {
		this.visitNode(down);
		down = down.getDown();
	}
	
	left = node.getLeft();
	while(left!=null) {
		this.visitNode(left);
		
		up = left.getUp();
		while(up!=null) {
			this.visitNode(up);
			up = up.getUp();
		}			
		
		down = left.getDown();
		while(down!=null) {
			this.visitNode(down);
			down = down.getDown();
		}
		
		left = left.getLeft();
	}

	right = node.getRight();
	while(right!=null) {
		this.visitNode(right);
		
		up = right.getUp();
		while(up!=null) {
			this.visitNode(up);
			up = up.getUp();
		}			
		
		down = right.getDown();
		while(down!=null) {
			this.visitNode(down);
			down = down.getDown();
		}
		
		right = right.getRight();
	}
}

五、路径
给任意两节点,找出两点之间的所有最短路径,打印出所有这些最短路径
如下图,4x4的矩阵,从5到16的最短路线有10种
规律:5->16的所有最短路径 = 5->6->16, 5->9->16(这两种的合集)

在类NodeUtil里增加方法:minPath,findAllMinPath

//递归算全部最短路径
//全部的最短路径:A->B =  A-A1 & A1->B +  A-A2 & A2->B
//A  A1 #  #
//A2 #  #  #
//#  #  #  B
//#  #  #  #
private void findAllMinPath(Node<Integer> start ,Node<Integer> end, 
		int startRow, int startColumn,
		int endRow, int endColumn,
		Integer[] paths, int curpos) {

	Node<Integer> p = start;
	int pos;
	paths[curpos] = p.getValue(); //在路径上记下当前节点
	
	//达到终点
	if(startRow==endRow && startColumn==endColumn) {
		//打印路径
		for(int i=0;i<paths.length;i++) {
			System.out.print(paths[i]+"\t");
		}
		System.out.println("");
		return;
	}
	
	//根据相对位置,往左或往右
	pos = curpos;
	if(startColumn < endColumn ) { //往右一格
		findAllMinPath(p.getRight(),end,
				startRow,startColumn+1,
				endRow,endColumn,
				paths, pos+1);
	}else if(startColumn > endColumn) { //往左一格
		findAllMinPath(p.getLeft(),end,
				startRow,startColumn-1,
				endRow,endColumn,
				paths, pos+1);
	}
	
	//根据相对位置,往上或往下
	pos = curpos;
	if(startRow < endRow ) { //往下一格
		findAllMinPath(p.getDown(),end,
				startRow+1,startColumn,
				endRow,endColumn,
				paths, pos+1);
	}else if(startRow > endRow ) { //往上一格
		findAllMinPath(p.getUp(),end,
				startRow-1,startColumn,
				endRow,endColumn,
				paths, pos+1);
	}
}

public void minPath(Node<Integer> start ,Node<Integer> end) {
	
	Integer[] paths; //路径
	Node<Integer> p ;
	int startRow,startColumn; // 起点坐标
	int endRow,endColumn; //终点坐标
	
	//起点坐标
	p = start;
	startColumn = 0;
	while(p!=null) {
		startColumn++;
		p = p.getLeft();
	}
	startColumn--;
	
	p = start;
	startRow = 0;
	while(p!=null) {
		startRow++;
		p = p.getUp();
	}
	startRow--;
	
	//终点的坐标
	p = end;
	endColumn = 0;
	while(p!=null) {
		endColumn++;
		p = p.getLeft();
	}
	endColumn--;
	
	p = end;
	endRow = 0;
	while(p!=null) {
		endRow++;
		p = p.getUp();
	}
	endRow--;
	
	//最短路径长度=行差+列差+1
	int pathlength = (startRow<endRow?endRow-
						startRow:startRow-endRow) +
					(startColumn<endColumn?endColumn-
						startColumn:startColumn-endColumn)+1;
	
	//创建路径数组
	paths = new Integer[pathlength];

	//打印起点、终点的值和坐标
	System.out.println("#全部最短路径"+ 
						start.getValue() +
						":("+startRow+","+startColumn+") ->"+ 
						end.getValue() +
						":("+endRow+","+endColumn+")" );
	
	//全部最短路径
	this.findAllMinPath(start, end, 
						startRow, startColumn, 
						endRow, endColumn, 
						paths, 0);
}

六、顺时针旋转90度
举例:n*n(n=4)二维表,右转90°,如下图:

找出规律:节点坐标 [i][j] -> [j][n-i-1]

//向右旋转90度
public Node<Integer> turnRight90(Node<Integer> node){
	if(node==null) return null;
	
	int n = 0;
	Node<Integer> head, tmp ,rowNode, colNode;  
	head = node;
	while(head.getLeft()!=null) head = head.getLeft();
	while(head.getUp()!=null) head = head.getUp();
	tmp = head;
	while(tmp!=null) {
		tmp = tmp.getRight();
		n++;
	}
	Node<Integer> nodes[][] = new Node[n][n];
	
	rowNode = head;
	for(int i=0;i<n;i++) {
		colNode = rowNode;
		for(int j=0;j<n;j++) {
			nodes[j][n-i-1] = colNode;
			colNode = colNode.getRight();
		}
		rowNode = rowNode.getDown();
	}
	
	for(int i=0;i<n;i++) {
		for(int j=0;j<n;j++) {
			if(i==0) {
				nodes[i][j].setUp(null);
			}
			if(i>0) { 
				nodes[i][j].setUp(nodes[i-1][j]);
				nodes[i-1][j].setDown(nodes[i][j]);
			}
			if(i==n-1) {
				nodes[i][j].setDown(null);
			}
			if(j==0) {
				nodes[i][j].setLeft(null);
			}
			if(j>0) {
				nodes[i][j].setLeft(nodes[i][j-1]);
				nodes[i][j-1].setRight(nodes[i][j]);
			}
			if(j==n-1) {
				nodes[i][j].setRight(null);
			}
		}
	}
	
	return nodes[0][0];
}


七、写个main方法执行下

public static void main(String[] args) {
	NodeUtil util = new NodeUtil();
	
	//创建4x4二维四项链表
	Node<Integer> head = util.genNode(4); 
	
	//打印
	util.printToRightDown(head);
	
	//取其中两节点
	Node<Integer> startNode = head.getDown();
	Node<Integer> endNode = head.getRight().getDown().getRight().getRight().getDown().getDown();
	
	//遍历,以startNode为起点遍历所有节点
	util.visitWhole(startNode);
	
	//从startNode到endNode的所有最短路径
	util.minPath(startNode, endNode);
	
	//从endNode到startNode的所有最短路径
	util.minPath(endNode, startNode);
	
	//向右旋转90度
	Node<Integer> newhead = util.turnRight90(startNode);
	//打印出旋转后的
	util.printToRightDown(newhead);
}

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/4532.html

标签: n node
分享给朋友:

“n*n的二维四向链表,初始化、遍历、最短路径、旋转” 的相关文章

亚马逊推出 Amazon Linux 2023 发行版,专为 AWS 云进行优化

稿源:IT之家3 月 19 日消息,本周早些时候,亚马逊宣布推出其第三代 Linux 发行版 Amazon Linux 2023(AL2023)。亚马逊表示,该版本将带来高安全性标准、可预测的生命周期和确定性更新。Amazon Linux 2023 针对 Amazon EC2 进行了优化,与最新的...

面试官:聊聊你知道的Vue与React的区别

最近面到很多大公司的时候,小编都会碰到一个很尴尬的问题,很多大公司的技术栈都是React,但是小编学的是Vue,其实从本质上来说两者都是比较优秀的前端框架,所以有些面试官会问到Vue和React的区别。小编认真整理了一些自己所知道的Vue和React的区别,给大家分享分享。1. 模板语法 vs JS...

掌握版本控制:Git的那些常见用法与技巧

Git作为现代开发中最常用的版本控制系统,它的普及和高效性使得程序员几乎每天都在与它打交道。无论是个人项目,还是团队协作,Git都能帮助我们追踪代码的修改历史,保证代码版本的管理井井有条,并在多人协作时有效地避免冲突。本文将分享一些常见的Git用法与技巧,帮助你更好地掌握Git的强大功能,并提升你在...

程序员开发必会之git常用命令,git配置、拉取、提交、分支管理

整理日常开发过程中经常使用的git命令![送心]git配置SSH刚进入项目开发中,我们首先需要配置git的config、配置SSH方式拉取代码,以后就免输入账号密码了!# 按顺序执行 git config --global user.name "自己的账号" git config -...

Vue实现动态路由

通常我们在vue项目中都是前端配置好路由的,但在一些项目中我们可能会遇到权限控制,这样我们就涉及到动态路由的设置了。动态路由设置一般有两种:(1)、简单的角色路由设置: 比如只涉及到管理员和普通用户的权限。通常直接在前端进行简单的角色权限设置(2)、复杂的路由权限设置: 比如OA系统、多种角色的权限...

vue.js 双向绑定如何理解,有什么好处!#云南小程序开发

Vue.js 的双向数据绑定是借助于 JavaScript 的一些特性,如对象的属性 getter 和 setter 以及 Vue 的依赖追踪系统实现的。简单来说,双向数据绑定就是数据与视图间的双向通信,也就是说数据的改变会马上反映到视图中,视图的改变也会立刻改变数据。具体来说,当你改变了数据时,视...