/// <summary> /// Pops a node from the heap, this node is always the node /// with the cheapest expected path cost /// </summary> public MinHeapNode Pop() { var top = this.head; this.head = this.head.Next; return(top); }
public List <Vector2Int> FindPath(Vector2Int start, Vector2Int end, int iterationLimit = 200) { // Convert start and end to working co-ordinates. start += new Vector2Int((int)(gridSize.x * 0.5f), (int)(gridSize.y * 0.5f)); end += new Vector2Int((int)(gridSize.x * 0.5f), (int)(gridSize.y * 0.5f)); Debug.Log(start); Debug.Log(end); // Clear step list. StepList.Clear(); // Check for start/end. if (start == end) { return(new List <Vector2Int> { start }); } MinHeapNode head = new MinHeapNode(start, ManhattanDistance(start, end)); MinHeap open = new MinHeap(); // Push head node to heap. open.Push(head); // Define total cost. float[] totalCost = new float[gridSize.x * gridSize.y]; Vector2Int[] cameFrom = new Vector2Int[gridSize.x * gridSize.y]; while (open.HasNext() && iterationLimit > 0) { // Get current position. Vector2Int current = open.Pop().Position; MessageCurrent(current, PartiallyReconstructPath(start, end, cameFrom)); if (current == end) { List <Vector2Int> path = ReconstructPath(start, end, cameFrom); path.Reverse(); return(path); } Step(open, cameFrom, totalCost, current, end); MessageClose(current); --iterationLimit; } return(null); }
public bool IfContainsRemove(Entity node) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckReadAndThrow(this.m_Safety); #endif if (head < 0) { return(false); } var current = Get(head); if (current.NodeEntity == node) { head = current.Next; return(true); } if (current.Next == -1) { return(false); } MinHeapNode prev = current; current = Get(current.Next); var currentPrev = head; while (current.Next > -1) { if (current.NodeEntity == node) { prev.Next = current.Next; UnsafeUtility.WriteArrayElement(buffer, currentPrev, prev); return(true); } currentPrev = prev.Next; prev = current; current = Get(current.Next); } if (current.NodeEntity == node) { prev.Next = -1; UnsafeUtility.WriteArrayElement(buffer, currentPrev, prev); return(true); } return(false); }
public MinHeapNode ExtractMinKey(MinHeap heap) { if (IsEmptyMinHeap(heap)) { return(null); } MinHeapNode first = heap.array[0]; MinHeapNode last = heap.array[heap.size - 1]; heap.array[0] = last; heap.pos[first.value] = heap.size - 1; heap.pos[last.value] = 0; heap.size--; MinHeapify(heap, 0); return(first); }
public static void MergeKSortedArrays(int[,] arr, int k) { MinHeapNode[] hArr = new MinHeapNode[k]; int resultSize = 0; for (int i = 0; i < arr.GetLength(0); i++) { MinHeapNode node = new MinHeapNode(arr[i, 0], i, 1); hArr[i] = node; resultSize += arr.GetLength(1); } // Create a min heap with k heap nodes. // Every heap node has first element of an array MinHeap mh = new MinHeap(hArr, k); int[] result = new int[resultSize]; // To store output array // Now one by one get the minimum element // from min heap and replace it with // next element of its array for (int i = 0; i < resultSize; i++) { // Get the minimum element and // store it in result MinHeapNode root = mh.getMin(); result[i] = root.element; // Find the next element that will // replace current root of heap. // The next element belongs to same // array as the current root. if (root.j < arr.GetLength(1)) { root.element = arr[root.i, root.j++]; } // If root was the last element of its array else { root.element = int.MaxValue; } // Replace root with next element of array mh.replaceMin(root); } }
public void DijkstraAlgorithm(int sourceVertex) { MinHeap minHeap = new MinHeap(Vertices); int[] distanceTable = new int[Vertices]; //Set all distances to max value initially for (int i = 0; i < distanceTable.Length; i++) { distanceTable[i] = Int32.MaxValue; } //Set source vertex's distance as 0; minHeap.DecreaseKey(sourceVertex, 0); distanceTable[sourceVertex] = 0; while (minHeap.HeapSize > 0) { //Extract min MinHeapNode minNode = minHeap.ExtractMin(); Console.WriteLine("Min value extraxted: " + minNode.Vertex); //Look for the node's neighbors in adjacency list LinkedListofGraphNodes neighbors = AdjacencyList[minNode.Vertex]; GraphNode p = neighbors.Head; while (p != null) { if (minHeap.IsinMinHeap(p.Key) && minNode.Distance != Int32.MaxValue) { int new_distance = minNode.Distance + p.EdgeWeight; if (distanceTable[p.Key] > new_distance) { minHeap.DecreaseKey(p.Key, new_distance); distanceTable[p.Key] = new_distance; } } p = p.Next; } } PrintDistanceTable(distanceTable); }
public void Push(MinHeapNode node) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (length == capacity) { throw new IndexOutOfRangeException($"Capacity of {capacity} Reached: {length}"); } AtomicSafetyHandle.CheckReadAndThrow(this.m_Safety); #endif if (head < 0) { head = length; } else if (node.F_Cost < Get(head).F_Cost || (node.F_Cost == Get(head).F_Cost&& node.H_Cost < Get(head).H_Cost)) { node.Next = head; head = length; } else { var currentPtr = head; var current = Get(head); while (current.Next >= 0 && Get(current.Next).F_Cost <= node.F_Cost) { if (node.F_Cost == Get(current.Next).F_Cost&& node.H_Cost < Get(current.Next).H_Cost) { break; } currentPtr = current.Next; current = Get(current.Next); } node.Next = current.Next; current.Next = length; UnsafeUtility.WriteArrayElement(buffer, currentPtr, current); } UnsafeUtility.WriteArrayElement(buffer, length, node); this.length += 1; }
public void Push(MinHeapNode <T> node) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (m_length == m_capacity) { throw new IndexOutOfRangeException($"Capacity Reached"); } CheckReadAndThrow(m_Safety); #endif if (m_head < 0) { m_head = m_length; } else if (node.Cost < this[m_head].Cost) { node.Next = m_head; m_head = m_length; } else { var currentPtr = m_head; var current = this[currentPtr]; while (current.Next >= 0 && this[current.Next].Cost <= node.Cost) { currentPtr = current.Next; current = this[current.Next]; } node.Next = current.Next; current.Next = m_length; UnsafeUtility.WriteArrayElement(m_Buffer, currentPtr, current); } UnsafeUtility.WriteArrayElement(m_Buffer, m_length, node); m_length += 1; }
/// <summary> /// Pushes a node onto the heap /// </summary> public void Push(MinHeapNode node) { // If the heap is empty, just add the item to the top if (this.head == null) { this.head = node; } else if (node.ExpectedCost < this.head.ExpectedCost) { node.Next = this.head; this.head = node; } else { var current = this.head; while (current.Next != null && current.Next.ExpectedCost <= node.ExpectedCost) { current = current.Next; } node.Next = current.Next; current.Next = node; } }
public void FindPrimsMSTAdjList(int[,] graph) { int vertext = V; int[] parent = new int[V]; int[] key = new int[V]; MinHeap minHeap = new MinHeap(vertext); for (int v = 1; v < vertext; v++) { parent[v] = -1; key[v] = Int32.MaxValue; minHeap.array[v] = new MinHeapNode(v, key[v]); minHeap.pos[v] = v; } key[0] = 0; minHeap.pos[0] = 0; minHeap.array[0] = new MinHeapNode(0, key[0]); minHeap.size = vertext; while (!minHeap.IsEmptyMinHeap(minHeap)) { MinHeapNode node = minHeap.ExtractMinKey(minHeap); int u = node.value; foreach (var item in AdjList[u]) { int v = item.dest; if (minHeap.IsInMinHeap(minHeap, v) && item.weight < key[v]) { key[v] = item.weight; parent[v] = u; minHeap.DecreaseKey(minHeap, key[v], v); } } } }
public void replaceMin(MinHeapNode root) { harr[0] = root; MinHeapify(0); }
public void Clear() => this.head = null;
private unsafe void AStarSolver(int2 start, int2 goal, int index, Entity agent) { // data containers sliced from shared data structures var openSet = OpenSet.Slice(index * _maxLength, _maxLength); var closedSet = ClosedSet.Slice(index * _maxLength, _maxLength); var G_Costs = Gcosts.Slice(index * _maxLength, _maxLength); var neighbours = new NativeList <int2>(8, Allocator.TempJob); // reset of data containers openSet.Clear(); void *buffer = closedSet.GetUnsafePtr(); UnsafeUtility.MemClear(buffer, (long)closedSet.Length * UnsafeUtility.SizeOf <MinHeapNode>()); buffer = G_Costs.GetUnsafePtr(); UnsafeUtility.MemClear(buffer, (long)G_Costs.Length * UnsafeUtility.SizeOf <int>()); var startNode = new MinHeapNode(GridGeneratorSystem.grid[start.x, start.y], start); openSet.Push(startNode); while (openSet.HasNext()) { var currentNode = openSet.Pop(); currentNode.IsClosed = 1; closedSet[GetIndex(currentNode.Position)] = currentNode; // if goal node is reached then the path is created and assigned to the agent entity if (currentNode.Position.x == goal.x && currentNode.Position.y == goal.y) { var path = new NativeList <int2>(Allocator.TempJob); var current = currentNode; while (current.ParentPosition.x != -1) { path.Add(current.Position); current = closedSet[GetIndex(current.ParentPosition)]; } path.Add(current.Position); CreatePath(agent, ref path); path.Dispose(); break; } GetNeighbours(currentNode.Position, ref neighbours); for (int i = 0; i < neighbours.Length; i++) { var neighbourEntity = GridGeneratorSystem.grid[neighbours[i].x, neighbours[i].y]; // if current neighbour is in closed list or is unwalkable then skip to next if (closedSet[GetIndex(neighbours[i])].IsClosed == 1 || !Walkables[neighbourEntity].Value) { continue; } int costSoFar = G_Costs[GetIndex(currentNode.Position)] + Heuristics.OctileDistance(currentNode.Position, neighbours[i]); if (G_Costs[GetIndex(neighbours[i])] == 0 || costSoFar < G_Costs[GetIndex(neighbours[i])]) { // update costs int h = Heuristics.OctileDistance(neighbours[i], goal); int f = costSoFar + h; G_Costs[GetIndex(neighbours[i])] = costSoFar; var node = new MinHeapNode(neighbourEntity, neighbours[i], currentNode.Position, f, h); // if openSet contains node => update node openSet.IfContainsRemove(node.NodeEntity); openSet.Push(node); } } } neighbours.Dispose(); }