I want to understand the A* algorithm. I wrote by examples, but often it gets into an infinite loop.
What is the problem?
Please forgive me for the English language.
Path Search Code:
public Node GetPath(Vector2 goal,Vector2 start) {
List<Node> OpenNodes = new List<Node>(); //список с не просмотренными узлами
List<Node> ClosedNodes = new List<Node>(); //список с не просмотренными узлами
OpenNodes.Add(new Node
{
pos = start,
parent = null,
DistStart = 0,
DistOnGoal = GetDistOnGoal(Vector2.zero, goal)
});
while (OpenNodes.Count > 0) {
var FirstNode = OpenNodes.OrderBy(node => node.FullDist).First();
ClosedNodes.Add(FirstNode);
OpenNodes.Remove(FirstNode);
if (FirstNode.pos == goal) {
Debug.Log("путь есть");
return FirstNode;
}
foreach (Node n in NighBours(FirstNode, goal)) {
var chanel = false;
foreach (Node d in ClosedNodes) {
if (n == d) {
chanel = true;
continue;
}
}
if (chanel)
{
chanel = false;
continue;
}
var opennod = OpenNodes.FirstOrDefault(node => node.pos == n.pos);
if (opennod == null)
{
OpenNodes.Add(n);
}
else {
if (opennod.DistStart >n.DistStart) {
opennod.DistStart = n.DistStart;
opennod.parent = FirstNode;
}
}
}
}
return null;
}
public float GetDistOnGoal(Vector2 n, Vector2 goal) {//дистанция до цели
return Mathf.Abs((goal - n).magnitude);
}
public List<Node> NighBours(Node n,Vector2 goal)//соседи
{
var Point = new Vector2[4];
var Nodes = new List<Node>();
Point[0] = new Vector2(n.pos.x - 1, n.pos.y);
Point[1] = new Vector2(n.pos.x + 1, n.pos.y);
Point[2] = new Vector2(n.pos.x, n.pos.y + 1);
Point[3] = new Vector2(n.pos.x, n.pos.y - 1);
for (var i = 0; i < Point.Length; i++)
{
if (Point[i].x > 1 && Point[i].x < map.GetLength(0) - 2 && Point[i].y > 1 && Point[i].y < map.GetLength(1) - 2)
{
if (map[(int)Point[i].x, (int)Point[i].y] == 0)
{
Nodes.Add(
new Node
{
pos = Point[i],
parent = n,
DistStart = n.DistStart + 1,
DistOnGoal = GetDistOnGoal(Point[i],goal),
});
}
}
}
return Nodes;
}
public class Node {
public Vector2 pos;
public Node parent;
public float DistStart;
public float DistOnGoal;
public float FullDist
{
get
{
return DistStart + DistOnGoal;
}
}
}
This is the node code.
The function never returned null, although an example of this implies.
Debug also can't because Unity hangs tight
Related
I’ve written an implementation of A* that relies on sorting nodes by their F score in a sortedSet.
The sorting, in some cases, seems to insert a Node object at the 'Min' value when its compared 'F' value is actually the second lowest rather than the Min, as described. I'm completely baffled as to why this is happening. I believe it's causing the knock-on effect of causing nodeTree.Remove and nodeTree.RemoveWhere to fail, but that might be the actual cause of the issue, I'm honestly not sure - though I wouldn't know how to fix it if it is.
This is the comparer used. I assume it's relatively obvious that I'm not exactly sure how to implement these, but I think this should work as I intend.
public class FValueFirst : Comparer<PathfindingAgent.Node>
{
public override int Compare(PathfindingAgent.Node x, PathfindingAgent.Node y)
{
int result = x.F.CompareTo(y.F);
if (result == 0)
{
result = y.G.CompareTo(x.G);
}
if(x == y)
{
result = 0;
}
return result;
}
}
This is the Node object, for reference.
public class Node
{
public Cell cell;
public float G;
public float H;
public bool Opened;
public bool Closed;
public Node Previous;
public float F { get => G + H; }
}
This is the function it all occurs in. The result is deterministic, thankfully. Depending on the current destID and the particular layout of the grid's obstacles it will always get out of sort on the same iteration.
public void PathTo(Vector3Int destID)
{
SortedSet<Node> nodeTree = new SortedSet<Node>(new FValueFirst());
Vector3Int radius = PathfindingGrid.Instance.GridRadius;
NodeGrid = new Node[radius.x * 2 + 1, radius.y * 2 + 1, radius.z * 2 + 1];
Node startNode = new Node()
{
cell = PathfindingGrid.Cells[CurrentID.x, CurrentID.y, CurrentID.z],
G = 0,
H = 0
};
Node endNode = new Node()
{
cell = PathfindingGrid.Cells[destID.x, destID.y, destID.z],
G = 0,
H = 0
};
Vector3Int sID = startNode.cell.ID;
Vector3Int eID = endNode.cell.ID;
NodeGrid[sID.x, sID.y, sID.z] = startNode;
NodeGrid[eID.x, eID.y, eID.z] = endNode;
if (endNode.cell.IsOccupied) return;
nodeTree.Add(startNode);
int iterations = 0;
while(true)
{
Node node;
node = nodeTree.Min;
node.Closed = true;
nodeTree.RemoveWhere(n => n == node);
if(node == nodeTree.Min)
{
throw new Exception($"Incorrect node was removed from the tree");
}
if (node == endNode)
{
List<Node> chain = BacktraceChain(node);
Debug.Log($"Path found from {CurrentID} to {destID} with score {endNode.G} traversing {chain.Count} cells in {iterations} iterations");
DrawLine(chain, Color.white);
break;
}
List<Node> neighbours = GetNeighbours(node);
foreach(Node neighbour in neighbours)
{
if (neighbour == startNode || neighbour.Closed) continue;
float newg = Vector3Int.Distance(node.cell.ID, neighbour.cell.ID) + node.G;
if (!neighbour.Opened || newg < neighbour.G)
{
neighbour.G = newg;
neighbour.H = ManhattanHeuristic(neighbour, endNode);
neighbour.Previous = node;
if(!neighbour.Opened)
{
nodeTree.Add(neighbour);
neighbour.Opened = true;
}
else
{
nodeTree.RemoveWhere(n => n == neighbour);
nodeTree.Add(neighbour);
}
}
}
iterations++;
}
}
For posterity, I solved the issue - it was due to my inexperience with the SortedList type.
This code, found near the end of the function was to blame
if (!neighbour.Opened || newg < neighbour.G)
{
neighbour.G = newg;
neighbour.H = ManhattanHeuristic(neighbour, endNode);
neighbour.Previous = node;
if(!neighbour.Opened)
{
nodeTree.Add(neighbour);
neighbour.Opened = true;
}
else
{
nodeTree.RemoveWhere(n => n == neighbour);
nodeTree.Add(neighbour);
}
Specifically, an item in a tree cannot have its compared values modified to the point where it no longer compares correctly in that index. The item must first be removed from the list, modified, and readded.
My guess in hindsight is that, though removed immediately after modification, the tree is unable to be sufficiently traversed to access the target item due to the modification.
Thus my solution was to simply re-arrange the block so that the removal and addition occured on either side of the modification respectively, like so:
if (!neighbour.Opened || newg < neighbour.G)
{
if (neighbour.Opened)
{
if (!nodeTree.Remove(neighbour)) throw new Exception($"{neighbour} was not removed from tree");
}
else
{
neighbour.Opened = true;
}
neighbour.G = newg;
neighbour.H = ManhattanHeuristic(neighbour, endNode);
neighbour.Previous = node;
nodeTree.Add(neighbour);
}
I have a program which builds a very large tree from input data and traverses it, both by recursion. I have tested the program on smaller inputs (and thus smaller trees) and it functions as intended. However when the input data is much larger i run into 'Process is terminated due to StackOverflowException'. I assume this is due to the stack running out of space. Is there any way to prevent this or do I have to switch to building the tree via iteration instead? Or perhaps I am missing a case of infinite recursion somewhere?
Here is the code:
class Program
{
static int[] tileColors;
static Color[] colors;
static int totalTiles;
static void Main(string[] args)
{
Stopwatch s = new Stopwatch();
s.Start();
string[] data = File.ReadAllLines("colors.txt");
totalTiles = int.Parse(data[0].Split(' ')[0]);
int totalColors = int.Parse(data[0].Split(' ')[1]);
string[] colorsRaw = data[1].Split(' ');
tileColors = new int[totalTiles];
for (int i = 0; i < totalTiles; i++)
{
tileColors[i] = int.Parse(colorsRaw[i]) - 1;
}
colors = new Color[totalColors];
for (int i = 3; i < data.Length; i++)
{
string[] raw = data[i].Split(' ');
int[] pair = new int[] { int.Parse(raw[0]) - 1, int.Parse(raw[1]) - 1 };
if (colors[pair[0]] == null)
colors[pair[0]] = new Color(pair[1]);
else
colors[pair[0]].pairs.Add(pair[1]);
if (colors[pair[1]] == null)
colors[pair[1]] = new Color(pair[0]);
else
colors[pair[1]].pairs.Add(pair[0]);
}
Tree t = new Tree();
t.root = new Node(0);
PopulateTree(t.root);
long ans = t.CountMatchingLeaves(t.root, totalTiles - 1) % 1000000007;
Console.WriteLine(ans);
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
}
static void PopulateTree(Node root)
{
for (int i = root.tile + 1; i < totalTiles; i++)
{
if (colors[tileColors[i]] == null) continue;
if (colors[tileColors[i]].Compatible(tileColors[root.tile]))
{
var node = new Node(i);
root.children.Add(node);
PopulateTree(node);
}
}
}
}
class Color
{
public List<int> pairs = new List<int>();
public Color(int pair)
{
pairs.Add(pair);
}
public bool Compatible(int c)
{
return pairs.Contains(c);
}
}
class Node
{
public List<Node> children = new List<Node>();
public int tile;
public Node(int tile)
{
this.tile = tile;
}
}
class Tree
{
public Node root;
public List<Node> GetMatchingLeaves(Node root, int match)
{
if (root.children.Count == 0)
{
if (root.tile == match)
{
return new List<Node>() { root };
}
return new List<Node>();
}
List<Node> list = new List<Node>();
foreach(var c in root.children)
{
list.AddRange(GetMatchingLeaves(c, match));
}
return list;
}
public long CountMatchingLeaves(Node root, int match)
{
if (root.children.Count == 0)
{
if (root.tile == match)
{
return 1;
}
return 0;
}
long count = 0;
foreach (var c in root.children)
{
count += CountMatchingLeaves(c, match);
}
return count;
}
}
You can always rewrite recursion as iteration, usually by using a stack class rather than rely on your thread's stack. For your code it would look like this:
static void PopulateTree(Node start)
{
var nodes = new Stack<Node>();
nodes.Push(start);
while(nodes.Count != 0)
{
var root = nodes.Pop();
for (int i = root.tile + 1; i < totalTiles; i++)
{
if (colors[tileColors[i]] == null) continue;
if (colors[tileColors[i]].Compatible(tileColors[root.tile]))
{
var node = new Node(i);
root.children.Add(node);
nodes.Push(node);
}
}
}
}
The while loop checking for more items is the equivalent of your terminating condition in recursion.
I am trying to add nodes in a sorted manner to my linked list. My code just keeps adding to the end if the value is less than the end of the linked list. I am not sure how to fix this or if I am not fully checking for the right scenario.
I have tried to increment current until it is greater than the nodeToAdd to place the node between, but it always just places it at the end.
public void AddOrdered(int value)
{
LinkedListNode nodeToAdd = new LinkedListNode(value);
LinkedListNode cur = m_first;
if (m_first == null)
m_first = nodeToAdd;//new LinkedListNode(value);
else if (nodeToAdd.m_data < m_first.m_data)
{
AddAtFront(value);
}
else if (nodeToAdd.m_data < cur.m_next.m_data)
{
LinkedListNode temp = new LinkedListNode(value);
temp = m_first.m_next;
m_first.m_next = nodeToAdd;
nodeToAdd.m_next = temp;
}
else
{
AddAtEnd(value);
}
}
supplement add at end/front methods--which are working fine
public void AddAtEnd(int value)
{
LinkedListNode cur = m_first;
if (m_first == null)
{
LinkedListNode lnl = new LinkedListNode(value);
m_first = lnl;
}
while (cur.m_next != null)
{
cur = cur.m_next;
}
cur.m_next = new LinkedListNode(value);
}
public void AddAtFront(int value)
{
if (m_first == null)
{
LinkedListNode ln = new LinkedListNode(value);
m_first = ln;
}
else
{
LinkedListNode lnl = new LinkedListNode(value);
lnl.m_next = m_first;
m_first = lnl;
}
}
The values should get added in order but the output is placing them at the very end of the linked list unless new min/maxs are entered as values.
First I am assuming that m_first is your first node. With this as an assumption the code would be as follows:
public void AddOrdered(int value)
{
LinkedListNode nodeToAdd = new LinkedListNode(value);
LinkedListNode cur;
if (m_first == null || m_first.data >= nodeToAdd.data)
{
nodeToAdd.next = m_first;
m_first = nodeToAdd;
}
else
{
cur = m_first;
while (cur.next != null &&
cur.next.data < nodeToAdd.data)
cur = cur.next;
nodeToAdd.next = cur.next;
cur.next = nodeToAdd;
}
}
I have a simple path finding class using A*, however it only covers the four cardinal directions in a tile map. It obeys walls and avoids them, but in open spaces it creates a zig-zag pattern to get to it's destination.
I'd like to simplify that pattern to include diagonals - in open areas of the map, but so far if I use diagonals, it seems to ignore the walls entirely.
How can I solve this and correctly add the diagonals?
using UnityEngine;
using System.Collections.Generic;
public class AStar {
private List<Node> openList;
private List<Node> closeList;
private List<Node> neighbors;
private List<Node> finalPath;
private Node start;
private Node end;
public AStar()
{
openList = new List<Node>();
closeList = new List<Node>();
neighbors = new List<Node>();
finalPath = new List<Node>();
}
public void FindPath(MazeCell startCell, MazeCell goalCell)
{
start = new Node(0, 0, 0, null, startCell);
end = new Node(0, 0, 0, null, goalCell);
openList.Add(start);
bool keepSearching = true;
bool pathExists = true;
while(keepSearching && pathExists)
{
Node currentNode = ExtractBestNodeFromOpenList();
if (currentNode == null)
{
pathExists = false;
break;
}
closeList.Add(currentNode);
if (NodeIsGoal(currentNode))
{
keepSearching = false;
} else
{
FindValidFourNeighbors(currentNode);
}
foreach(Node neighbor in neighbors)
{
if (FindInList(neighbor, closeList) != null)
continue;
Node inOpenList = FindInList(neighbor, openList);
if (inOpenList == null)
{
openList.Add(neighbor);
} else
{
if (neighbor.G < inOpenList.G)
{
inOpenList.G = neighbor.G;
inOpenList.F = inOpenList.G + inOpenList.H;
inOpenList.parent = currentNode;
}
}
}
}
if (pathExists)
{
Node n = FindInList(end, closeList);
while (n != null)
{
finalPath.Add(n);
n = n.parent;
}
}
}
public bool ContainsCoordinates(IntVector2 coordinate)
{
return coordinate.x >= 0 && coordinate.x < GameConfig.mazeSize && coordinate.z >= 0 && coordinate.z < GameConfig.mazeSize;
}
private void FindValidFourNeighbors(Node node)
{
neighbors.Clear();
// Check South of this Cell //
int south = node.cell.mazeCellCoordinates.z - 1;
IntVector2 SouthNeighbor = new IntVector2(node.cell.mazeCellCoordinates.x , south);
int north = node.cell.mazeCellCoordinates.z + 1;
IntVector2 NorthNeighbor = new IntVector2(node.cell.mazeCellCoordinates.x, north);
int east = node.cell.mazeCellCoordinates.x + 1;
IntVector2 EastNeighbor = new IntVector2(east, node.cell.mazeCellCoordinates.z);
int west = node.cell.mazeCellCoordinates.x - 1;
IntVector2 WestNeighbor = new IntVector2(west, node.cell.mazeCellCoordinates.z);
IntVector2 SouthEastNeighbor = new IntVector2(south, east);
IntVector2 SouthWestNeighbor = new IntVector2(south, west);
IntVector2 NorthEastNeighbor = new IntVector2(north, east);
IntVector2 NorthWestNeighbor = new IntVector2(north, west);
if (ContainsCoordinates(SouthNeighbor))
{
if (Maze.Instance.cellStorage[SouthNeighbor.x, SouthNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[SouthNeighbor.x, SouthNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.North] is MazeCellWall))
{
Node vn = PrepareNewNode(node, 0, -1);
neighbors.Add(vn);
}
}
}
if (ContainsCoordinates(NorthNeighbor))
{
if (Maze.Instance.cellStorage[NorthNeighbor.x, NorthNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[NorthNeighbor.x, NorthNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.South] is MazeCellWall))
{
Node vn = PrepareNewNode(node, 0, 1);
neighbors.Add(vn);
}
}
}
if (ContainsCoordinates(WestNeighbor))
{
if (Maze.Instance.cellStorage[WestNeighbor.x, WestNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[WestNeighbor.x, WestNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.East] is MazeCellWall))
{
Node vn = PrepareNewNode(node, -1, 0);
neighbors.Add(vn);
}
}
}
if (ContainsCoordinates(EastNeighbor))
{
if (Maze.Instance.cellStorage[EastNeighbor.x, EastNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[EastNeighbor.x, EastNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.West] is MazeCellWall))
{
Node vn = PrepareNewNode(node, 1, 0);
neighbors.Add(vn);
}
}
}
}
private float Heuristic(Node n)
{
return Mathf.Sqrt((n.cell.mazeCellCoordinates.x - end.cell.mazeCellCoordinates.x) * (n.cell.mazeCellCoordinates.x - end.cell.mazeCellCoordinates.x) + (n.cell.mazeCellCoordinates.z - end.cell.mazeCellCoordinates.z) * (n.cell.mazeCellCoordinates.z - end.cell.mazeCellCoordinates.z));
}
private float MovementCost(Node a, Node b)
{
return Maze.Instance.cellStorage[b.cell.mazeCellCoordinates.x, b.cell.mazeCellCoordinates.z].movementCost();
}
private Node PrepareNewNode(Node n, int x, int z)
{
IntVector2 iv = new IntVector2(n.cell.mazeCellCoordinates.x + x, n.cell.mazeCellCoordinates.z + z);
Node node = new Node(0, 0, 0, n, Maze.Instance.cellStorage[iv.x, iv.z]);
node.G = n.G + MovementCost(n, node);
node.H = Heuristic(node);
node.F = node.G + node.H;
node.parent = n;
return node;
}
public List<MazeCell> CellsFromPath()
{
List<MazeCell> path = new List<MazeCell>();
foreach (Node n in finalPath)
{
path.Add(n.cell);
}
if (path.Count != 0)
{
path.Reverse();
path.RemoveAt(0);
}
return path;
}
public List<int> PointsFromPath()
{
List<int> points = new List<int>();
foreach (Node n in finalPath)
{
points.Add(n.cell.mazeCellCoordinates.x);
points.Add(n.cell.mazeCellCoordinates.z);
}
return points;
}
bool NodeIsGoal(Node node)
{
return ((node.cell.mazeCellCoordinates.x == end.cell.mazeCellCoordinates.x) && (node.cell.mazeCellCoordinates.z == end.cell.mazeCellCoordinates.z));
}
Node FindInList(Node n, List<Node> xl)
{
foreach (Node nn in xl)
{
if ((nn.cell.mazeCellCoordinates.x == n.cell.mazeCellCoordinates.x) && (nn.cell.mazeCellCoordinates.z == n.cell.mazeCellCoordinates.z))
return nn;
}
return null;
}
private Node ExtractBestNodeFromOpenList()
{
float minF = float.MaxValue;
Node bestNode = null;
foreach(Node n in openList)
{
if (n.F < minF)
{
minF = n.F;
bestNode = n;
}
}
if (bestNode != null)
openList.Remove(bestNode);
return bestNode;
}
}
I have implemented an A* before with diagonals and you just need to include them in the list of viable neighbors.
Technically you should do the costing/exclusion in your heuristic function rather, but just looking at your code surely you could just add 4 more checks in private void FindValidFourNeighbors(Node node):
if (ContainsCoordinates(SouthEastNeighbor))
{
if (Maze.Instance.cellStorage[SouthEastNeighbor.x, SouthEastNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[SouthEastNeighbor.x, SouthEastNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.South] is MazeCellWall) && !(c.cellEdges[(int)MazeDirection.East] is MazeCellWall))
{
Node vn = PrepareNewNode(node, 0, -1);
neighbors.Add(vn);
}
}
}
(Not too clear what the 'cellEdges' check is doing exactly but I assume you would need to check both sides for the diagonal and this is maybe where you are failing.)
I have null reference exception unhandled error in my red black tree code. I'm trying to remove it but I couldn't. The error is on this line
if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red)
Please can you people fix this error
Here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Algo_Project
{
class Program
{
public enum Color
{
Red = 0, Black = 1
}
public enum direction
{
Left, Right
}
public class Node
{
public IComparable data;
public Node left;
public Node right;
public Color color = Color.Black;
public Node(IComparable data): this(data, null, null)
{
}
public Node(IComparable data, Node left, Node right)
{
this.data = data;
this.left = left;
this.right = right;
}
}
public class Tree
{
protected Node root;
protected Node freshNode;
protected Node currentNode;
protected Tree()
{
freshNode = new Node(null);
freshNode.left = freshNode.right = freshNode;
root = new Node(null);
}
protected int Compare(IComparable item, Node node)
{
if (node != root)
return item.CompareTo(node.data);
else
return 1;
}
public IComparable Search(IComparable data)
{
freshNode.data = data;
currentNode = root.right;
while (true)
{
if (Compare(data, currentNode) < 0)
currentNode = currentNode.left;
else if (Compare(data, currentNode) > 0)
currentNode = currentNode.right;
else if (currentNode != freshNode)
return currentNode.data;
else
return null;
}
}
protected void Display(Node temp)
{
if (temp != freshNode)
{
Display(temp.left);
Console.WriteLine(temp.data);
Display(temp.right);
}
}
protected void Display()
{
this.Display(root.right);
}
}
public sealed class RedBlackTree : Tree
{
private Color Black = Color.Black;
private Color Red = Color.Red;
private Node parentNode;
private Node grandParentNode;
private Node tempNode;
public void Insert(IComparable item)
{
currentNode = parentNode = grandParentNode = root;
freshNode.data = item;
int returnValue = 0;
while (Compare(item, currentNode) != 0)
{
tempNode = grandParentNode;
grandParentNode = parentNode;
parentNode = currentNode;
returnValue = Compare(item, currentNode);
if (returnValue < 0)
currentNode = currentNode.left;
else
currentNode = currentNode.right;
if (currentNode.left.color == Color.Red && currentNode.right.color == Color.Red)
{
ReArrange(item);
}
}
if (currentNode == freshNode)
{
currentNode = new Node(item, freshNode, freshNode);
if (Compare(item, parentNode) < 0)
parentNode.left = currentNode;
else
parentNode.right = currentNode;
ReArrange(item);
}
}
private void ReArrange(IComparable item)
{
currentNode.color = Red;
currentNode.left.color = Color.Black;
currentNode.right.color = Color.Black;
if (parentNode.color == Color.Red)
{
grandParentNode.color = Color.Red;
bool compareWithGrandParenrNode = (Compare(item, grandParentNode) < 0);
bool compareWithParentNode = (Compare(item, parentNode) < 0);
if (compareWithGrandParenrNode != compareWithParentNode)
parentNode = Rotate(item, grandParentNode);
currentNode = Rotate(item, tempNode);
currentNode.color = Black;
}
root.right.color = Color.Black;
}
private Node Rotate(IComparable item, Node parentNode)
{
int value;
if (Compare(item, parentNode) < 0)
{
value = Compare(item, parentNode.left);
if (value < 0)
parentNode.left = this.Rotate(parentNode.left, direction.Left);
else
parentNode.left = this.Rotate(parentNode.left, direction.Right);
return parentNode.left;
}
else
{
value = Compare(item, parentNode.right);
if (value < 0)
parentNode.right = this.Rotate(parentNode.right, direction.Right);
else
parentNode.right = this.Rotate(parentNode.right, direction.Right);
return parentNode.right;
}
}
private Node Rotate(Node node, direction direction)
{
Node tempNode;
if (direction == direction.Left)
{
tempNode = node.left;
node.left = tempNode.right;
tempNode.right = node;
return tempNode;
}
else
{
tempNode = node.right;
node.right = tempNode.left;
tempNode.left = node;
return tempNode;
}
}
}
static void Main(string[] args)
{
RedBlackTree redBlackTree = new RedBlackTree();
Random random = new Random();
for (int i = 0; i < 100000; i++)
{
redBlackTree.Insert(random.Next(1, 100000));
random.Next();
}
redBlackTree.Insert(1000001);
DateTime startTime = DateTime.Now;
int p = (int)redBlackTree.Search(1000001);
DateTime endTime = DateTime.Now;
TimeSpan TimeElapsed = (TimeSpan)(endTime - startTime);
Console.WriteLine("The number " + p + "has been found in" + TimeElapsed.Milliseconds.ToString() + "milliseconds.");
Console.ReadLine();
Console.ReadLine();
}
}
}
Please can you tell something about this error I want it fixed up till thursday 6th June 2013
When your Insert method hits a leaf, currentNode.left or currentNode.right will be null. At this point, you're not checking for null, so you'll receive this exception on that line as you try to access the color.
You need to add null checks on insert to handle the leaf condition.