Files
pixelheros/assets/script/game/map/view/map/road/BinaryTreeNode.ts
pan@work 2ef3bcf322 first
2024-07-17 16:14:14 +08:00

253 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import RoadNode from "./RoadNode";
/**
* 二堆叉结构存储
*/
export default class BinaryTreeNode {
/**
* 当前寻路标记,用于标记节点是否属于当前次寻路运算
*/
public seekTag: number = 0;
/**
* 开启列表根节点
*/
public openNode: RoadNode = null;
/**
* 计数当次寻路的运算代价(用于测试数据)
*/
public count: number = 0;
/**
* 刷新寻路tag标记用于标记当前是哪次的寻路
*/
public refleshTag() {
this.openNode = null;
this.count = 0;
this.seekTag++;
if (this.seekTag > 1000000000) {
this.seekTag = 0;
}
}
/**
* 二叉堆树是否为空,即没有任何节点加入
* @returns
*/
public isTreeNull() {
return this.openNode == null;
}
/**
* 把节点添加进二叉堆里
* @param roadNode 要添加的节点
* @param head 从哪个节点位置开始添加
* @returns
*/
public addTreeNode(roadNode: RoadNode, head: RoadNode = null) {
this.count++; //计数统计运算代价
if (head == null) {
if (this.openNode == null) //如果开启节点为空,则拿首次加二叉堆的节点作为开启节点
{
this.openNode = roadNode;
//console.log(this.count,"add root ",roadNode.f,roadNode.toString());
return;
} else //如果开启节点存在头节点为null,默认把开启节点用于头节点
{
head = this.openNode;
}
}
if (roadNode.f >= head.f) {
if (head.right == null) {
head.right = roadNode;
roadNode.treeParent = head;
//console.log(this.count,"add right ",roadNode.f,roadNode.toString());
} else {
this.addTreeNode(roadNode, head.right);
}
} else {
if (head.left == null) {
head.left = roadNode;
roadNode.treeParent = head;
//console.log(this.count,"add left ",roadNode.f,roadNode.toString());
} else {
this.addTreeNode(roadNode, head.left);
}
}
}
/**
* 删除树节点
* @param roadNode 要删除的节点
*/
public removeTreeNode(roadNode: RoadNode) {
this.count++; //计数统计运算代价
if (roadNode.treeParent == null && roadNode.left == null && roadNode.right == null) //节点不在树结构中
{
return;
}
if (roadNode.treeParent == null) //如果是根节点,优先把左子节点转换成根节点,左子节点不存在,则把右子节点转换成根节点
{
if (roadNode.left) {
this.openNode = roadNode.left;
roadNode.left.treeParent = null;
if (roadNode.right) {
roadNode.right.treeParent = null;
this.addTreeNode(roadNode.right, this.openNode);
}
} else if (roadNode.right) //如果没有左节点,只有右节点
{
this.openNode = roadNode.right;
roadNode.right.treeParent = null;
}
} else {
if (roadNode.treeParent.left == roadNode) //如果是左子节点
{
if (roadNode.right) {
roadNode.treeParent.left = roadNode.right;
roadNode.right.treeParent = roadNode.treeParent;
if (roadNode.left) {
roadNode.left.treeParent = null;
this.addTreeNode(roadNode.left, roadNode.right)
}
} else {
roadNode.treeParent.left = roadNode.left;
if (roadNode.left) {
roadNode.left.treeParent = roadNode.treeParent;
}
}
} else if (roadNode.treeParent.right == roadNode) //如果是右子节点
{
if (roadNode.left) {
roadNode.treeParent.right = roadNode.left;
roadNode.left.treeParent = roadNode.treeParent;
if (roadNode.right) {
roadNode.right.treeParent = null;
this.addTreeNode(roadNode.right, roadNode.left)
}
} else {
roadNode.treeParent.right = roadNode.right;
if (roadNode.right) {
roadNode.right.treeParent = roadNode.treeParent;
}
}
}
}
roadNode.resetTree();
}
/**
* 从二叉堆结构里快速查找除f值最小的路节点
* @param head 搜索的起始节点
* @returns
*/
public getMin_F_Node(head: RoadNode = null): RoadNode {
this.count++; //计数统计运算代价
if (head == null) {
if (this.openNode == null) {
return null;
} else {
head = this.openNode; //如果头节点为null并且开启节点不为空则头节点默认使用开启节点
}
}
if (head.left == null) {
var minNode: RoadNode = head;
if (head.treeParent == null) {
this.openNode = head.right;
if (this.openNode) {
this.openNode.treeParent = null;
}
} else {
head.treeParent.left = head.right;
if (head.right) {
head.right.treeParent = head.treeParent;
}
}
return minNode;
} else {
return this.getMin_F_Node(head.left);
}
}
/**
* 把节点加入开启列表,即打入开启列表标志
* @param node
*/
public setRoadNodeInOpenList(node: RoadNode) {
node.openTag = this.seekTag; //给节点打入开放列表的标志
node.closeTag = 0; //关闭列表标志关闭
}
/**
* 把节点加入关闭列表,即打入关闭列表标志
* @param node
*/
public setRoadNodeInCloseList(node: RoadNode) {
node.openTag = 0; //开放列表标志关闭
node.closeTag = this.seekTag; //给节点打入关闭列表的标志
}
/**
* 节点是否在开启列表
* @param node
* @returns
*/
public isInOpenList(node: RoadNode): Boolean {
return node.openTag == this.seekTag;
}
/**
* 节点是否在关闭列表
* @param node
* @returns
*/
public isInCloseList(node: RoadNode): Boolean {
return node.closeTag == this.seekTag;
}
public getOpenList(): RoadNode[] {
var openList: RoadNode[] = []
this.seachTree(this.openNode, openList);
return openList;
}
private seachTree(head: RoadNode, openList: RoadNode[]) {
if (head == null) {
return;
}
openList.push(head);
if (head.left) {
this.seachTree(head.left, openList);
}
if (head.right) {
this.seachTree(head.right, openList);
}
}
}