Scriptum/Assets/_/Stuff/GridPathfinding/BinaryTree.cs
2022-11-07 22:18:28 +01:00

285 lines
12 KiB
C#

/*
------------------- Code Monkey -------------------
Thank you for downloading this package
I hope you find it useful in your projects
If you have any questions let me know
Cheers!
unitycodemonkey.com
--------------------------------------------------
*/
using UnityEngine;
using System.Collections;
namespace GridPathfindingSystem {
public class BinaryTree {
private class BinaryNode {
//public static int nextId = 0;
//public int id;
public PathNode pathNode;
public BinaryNode left;
public BinaryNode right;
public BinaryNode(PathNode _pathNode, BinaryNode _left, BinaryNode _right) {
//id = nextId++;
pathNode = _pathNode;
left = _left;
right = _right;
}
/*public override string ToString() {
return "n_" + id;
}*/
}
private BinaryNode root;
public int totalNodes = 0;
//private string debugString;
//private string debugCodePath;
public BinaryTree() {
//BinaryNode.nextId = 0;
root = null;
//debugCodePath = "NEW: ";
}
public void AddNode(PathNode pathNode) {
//debugCodePath += "AD; ";
if (root == null) {
root = new BinaryNode(pathNode, null, null);
totalNodes++;
} else {
// Has root
//debugString = "";
try {
addNode(root, pathNode, pathNode.fValue);
} catch (System.Exception e) {
Debug.Log(e);
//Debug.LogError("Error: "+debugString);
//Debug.LogError(debugCodePath);
}
totalNodes++;
}
}
private void addNode(BinaryNode node, PathNode pathNode, int pathFvalue) {
//debugString += node.id + " " + ((node.left == null) ? "-1" : ""+node.left.id) + " " + (node.right == null ? "-1" : ""+node.right.id) + " ";
if (pathFvalue <= node.pathNode.fValue) {
// Left
if (node.left == null) {
// Become left
//debugString += " LEFT" + "; \n";
node.left = new BinaryNode(pathNode, null, null);
//debugCodePath += "AD" + node.left + "; ";
} else {
// Check left
//debugString += "L; \n";
//debugString += node.id + " " + (node == (node.left));
addNode(node.left, pathNode, pathFvalue);
}
} else {
// Right
if (node.right == null) {
// Become right
//debugString += " RIGHT" + "; \n";
node.right = new BinaryNode(pathNode, null, null);
//debugCodePath += "AD" + node.right + "; ";
} else {
// Check right
//debugString += node.id + " ";
//debugString += "R; \n";
addNode(node.right, pathNode, pathFvalue);
}
}
}
public void RemoveNode(PathNode pathNode) {
if (root.pathNode == pathNode) {
// It's the root
//debugCodePath += "RR" + root + "; ";
BinaryNode prevRoot = root;
if (root.left == null && root.right == null) {
// Both are null
root = null;
// Tree is dead
} else {
// Atleast one has something
if (root.left == null && root.right != null) {
// Has right but no left
root = root.right;
} else {
if (root.right == null && root.left != null) {
// Has left but no right
root = root.left;
} else {
// Has both right and left
if (root.left.right == null) {
// Root left has no right
root.left.right = root.right;
root = root.left;
} else {
// Root left has a right
BinaryNode leafRight = getLeafRight(root.left);
root = leafRight.right;
if (leafRight.right.left != null) {
// This leaf has a left
leafRight.right = leafRight.right.left;
}
leafRight.right = null;
root.left = leafRight;
root.right = prevRoot.right;
}
}
}
}
} else {
int pathFvalue = pathNode.fValue;
removeNode(root, pathNode, pathFvalue);
}
totalNodes--;
}
private void removeNode(BinaryNode node, PathNode pathNode, int pathFvalue) {
if (pathFvalue <= node.pathNode.fValue) {
// Check left
// Is it this left?
if (node.left != null) {
if (node.left.pathNode == pathNode) {
// It's this left one!
BinaryNode del = node.left;
//debugCodePath += "RNL" + del + "; ";
if (del.left == null && del.right == null) {
// Both are null
node.left = null;
} else {
// Atleast one has something
if (del.left == null && del.right != null) {
// Has right but no left
node.left = del.right;
} else {
if (del.right == null && del.left != null) {
// Has left but no right
node.left = del.left;
} else {
// Has both right and left
if (del.left.right == null) {
// Root left has no right
del.left.right = del.right;
node.left = del.left;
} else {
// Root left has a right
BinaryNode leafRight = getLeafRight(del.left);
node.left = leafRight.right;
if (leafRight.right.left != null) {
// This leaf has a left
leafRight.right = leafRight.right.left;
}
leafRight.right = null;
node.left.left = leafRight;
node.left.right = del.right;
}
}
}
}
} else {
// Not this left
// Check next one
removeNode(node.left, pathNode, pathFvalue);
}
}
} else {
// Check right
// Is it this right?
if (node.right != null) {
if (node.right.pathNode == pathNode) {
// It's this right one!
BinaryNode del = node.right;
//debugCodePath += "RNR" + del + "; ";
if (del.left == null && del.right == null) {
// Both are null
node.right = null;
} else {
// Atleast one has something
if (del.left == null && del.right != null) {
// Has right but no left
node.right = del.right;
} else {
if (del.right == null && del.left != null) {
// Has left but no right
node.right = del.left;
} else {
// Has both right and left
if (del.left.right == null) {
// Root left has no right
del.left.right = del.right;
node.right = del.left;
} else {
// Root left has a right
BinaryNode leafRight = getLeafRight(del.left);
node.right = leafRight.right;
if (leafRight.right.left != null) {
// This leaf has a left
leafRight.right = leafRight.right.left;
}
leafRight.right = null;
node.right.left = leafRight;
node.right.right = del.right;
}
}
}
}
} else {
// Not this right
// Check next one
removeNode(node.right, pathNode, pathFvalue);
}
}
}
}
private BinaryNode getLeafRight(BinaryNode node) {
if (node.right.right == null)
return node;
else
return getLeafRight(node.right);
}
public int getTotalHeight() {
return getHeight(root);
}
private int getHeight(BinaryNode node) {
if (node == null) return 0;
else {
return 1 + (int)Mathf.Max(getHeight(node.left), getHeight(node.right));
}
}
public PathNode GetSmallest() {
PathNode pathNode = null;
int count = 0;
try {
pathNode = getSmallest(root, ref count);
} catch {
Debug.LogError("GetSmallest: " + count);
}
return pathNode;
//return getSmallest(root, 0);
}
private PathNode getSmallest(BinaryNode node, ref int count) {
if (node == null) return null;
if (node.left != null) {
count++;
return getSmallest(node.left, ref count);
} else {
// No more left nodes
return node.pathNode;
}
}
}
}