I have implemented a depth first search (recursive) for the 8 puzzle problem in Java:
protected PuzzleState depthFirstSearch(PuzzleState state) {
PuzzleState start = this.getStartState();
PuzzleState goal = this.getGoalState();
PuzzleState stop = null;
int limit = 35;
int depth = state.getDepth();
boolean tooDeep = false;
if (state.equals(goal)) {
return state;
} else {
if (depth == limit) {
return stop;
} else {
Collection<Integer> actions = PuzzleAction.getPuzzleActions();
for (Integer action : actions) {
PuzzleState starter = start;
PuzzleState next = state.succ(action);
if (next != null) {
starter = depthFirstSearch(next);
}
if (starter == stop) {
tooDeep = true;
} else {
if (!starter.equals(start)) {
return starter;
}
}
}
}
}
if (tooDeep)
return stop;
else
return start;
}
I don't know what I have to change to transform it to a iterative deepening depth search. I know that there is no limit for the depth, because it increases in every round.
Tried this:
protected PuzzleState iterativeDeepSearch(PuzzleState state) {
int depth = state.getDepth();
for(int limit = 1; limit < depth; limit ++){
depthFirstSearch(state, limit);
}
}
Does anyone know how to change it to the needed IDS?
Thank you in advance!
Related
The evaluation function of A* Search is, according to AI: A Modern Approach, f(x) = h(x) + g(x), where f(x) is the evaluation function, h(x) the heuristic function (Euclidian straight line in my case), and g(x) the path-cost. f(x) for greedy search is simply f(x) = h(x).
To test these I made a visualization program.
With obstacle:
As you can see, the greedy search was far more effective than A*. This surprised me, so I wonder if this is expected and whether there is something wrong with my A*-code; either the heuristic or the priority queue.
int heuristic(Node n) {
int i=distanceFrom(n.state, grid.goalState) + n.state.pCost;
return i;
}
PriorityQueue<Node> front = new PriorityQueue<Node>(30, new Comparator<Node>() {
// override compare method
public int compare(Node i, Node j) {
if (heuristic(i) > heuristic(j)) {
return 1;
}
else if (heuristic(i) < heuristic(j)) {
return -1;
}
else {
return 0;
}
}
});
If I try making pCost less significant and more similar to Greedy by dividing it by an integer, it will perform better. Is A* supposed to perform like this?
The entire A* execute-function looks like this:
public void execute() {
SwingWorker worker = new SwingWorker() {
#Override
protected Void doInBackground() throws Exception {
boolean retGoal = false;
PriorityQueue<Node> front = new PriorityQueue<Node>(30, new Comparator<Node>() {
// override compare method
public int compare(Node i, Node j) {
if (heuristic(i) > heuristic(j)) {
return 1;
}
else if (heuristic(i) < heuristic(j)) {
return -1;
}
else {
return 0;
}
}
});
Hashtable<State,Node> reached = new Hashtable<State,Node>();
State s;
Node goal = null;
n = new Node(grid.startState, null);
int pCost = 0;
n.pathCost = pCost;
n.state.pCost = pCost;
front.add(n);
reached.put(n.state, n);
n.state.front=true;
panel.repaint();
while(!front.isEmpty()) {
Thread.sleep(Main.delay);
n.state.front=false;
n=front.poll();
if(grid.isGoal(n.state)) {
goal = n;
break;
}
pCost=n.state.pCost+1;
panel.repaint();
for (Node child : expand(n, grid)) {
s = child.state;
if(!reached.containsKey(s) && !s.isObstacle) {
s.pCost = pCost; //steps from goal
}
if((!reached.containsKey(s) || heuristic(child) < heuristic(reached.get(s))) && !s.isObstacle) {
s.reached = true;
s.front = true;
reached.put(s, child);
front.add(child);
}
panel.repaint();
}
}
if(goal != null) {
Node n = goal.parent;
while(n.parent != null) {
n.state.isPath=true;
n = n.parent;
}
}
panel.repaint();
return null;
}
};
worker.execute();
}
I'm asking because I basically just translate my python code to java and when I test in python the result is as expected (binary search faster than sequential search). It is not the case in Java though. Why is my binary search so inefficient?
import java.util.Arrays;
import java.util.stream.IntStream;
public class Chap5exe1 {
private static boolean sequential_search(int[] iterable, int item){
boolean found = false;
boolean stop = false;
int current_position = 0;
while ((current_position < iterable.length) & (!found) & (!stop)){ //!found is found == false
if (iterable[current_position] == item){
found = true;
}
else if (iterable[current_position] > item){
stop = true;
}
else {
current_position += 1;
}
}
return found;
}
private static boolean binary_search(int[] iterable, int item) {
if (iterable.length == 0) {
return false;
}
int mid_point = iterable.length / 2;
if (iterable[mid_point] == item){
return true;
}
else if (iterable[mid_point] > item){
return binary_search(Arrays.copyOfRange(iterable, 0, mid_point), item);
}
else {
return binary_search(Arrays.copyOfRange(iterable, mid_point+1, iterable.length), item);
}
}
public static void main(String[] args) {
for(int i = 1000; i <= 10000000; i += 1000){
int[] list = IntStream.range(0, i).toArray();
long startTime1 = System.nanoTime();
sequential_search(list, i);
long stopTime1 = System.nanoTime();
long startTime2 = System.nanoTime();
binary_search(list, i);
long stopTime2 = System.nanoTime();
String output = String.format("Sequential search:%d / Binary search:%d", stopTime1-startTime1, stopTime2-startTime2);
System.out.println(output);
}
}}
As said in comments, the Arrays.copyOfRange() method call causes the overhead. Try using the following code instead:
private static boolean binary_search(int[] iterable, int item) {
if (iterable.length == 0) {
return false;
}
return binary_search(iterable, item, 0, iterable.length);
}
private static boolean binary_search(int[] iterable, int item, int start, int end) {
int mid_point = (start + end) / 2;
if (iterable[mid_point] == item){
return true;
} else if (start == end) {
return false;
}
else if (iterable[mid_point] > item){
return binary_search(iterable, item, start, mid_point);
}
else {
return binary_search(iterable, item, mid_point+1, end);
}
}
I am working on a robot maze where the robot finds the target without bumping into walls. As a "backtrack" method, I need the robot to go in the opposite direction as it did when it first came across a junction. This is my code:
import uk.ac.warwick.dcs.maze.logic.IRobot;
import java.util.ArrayList;
import java.util.*;
import java.util.Iterator;
public class Explorer {
private int pollRun = 0; // Incremented after each pass.
private RobotData robotData; // Data store for junctions.
private ArrayList<Integer> nonWallDirections;
private ArrayList<Integer> passageDirections;
private ArrayList<Integer> beenbeforeDirections;
private Random random = new Random();
int [] directions = {IRobot.AHEAD, IRobot.LEFT, IRobot.RIGHT, IRobot.BEHIND};
public void controlRobot (IRobot robot) {
// On the first move of the first run of a new maze.
if ((robot.getRuns() == 0) && (pollRun ==0))
robotData = new RobotData();
pollRun++; /* Increment poll run so that the data is not reset
each time the robot moves. */
int exits = nonwallExits(robot);
int direction;
nonWallDirections = new ArrayList<Integer>();
passageDirections = new ArrayList<Integer>();
beenbeforeDirections = new ArrayList<Integer>();
// Adding each direction to the appropriate state ArrayList.
for(int item : directions) {
if(robot.look(item) != IRobot.WALL) {
nonWallDirections.add(item);
}
}
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
passageDirections.add(item);
}
}
for(int item : directions) {
if(robot.look(item) == IRobot.BEENBEFORE) {
beenbeforeDirections.add(item);
}
}
// Calling the appropriate method depending on the number of exits.
if (exits < 2) {
direction = deadEnd(robot);
} else if (exits == 2) {
direction = corridor(robot);
} else {
direction = junction(robot);
robotData.addJunction(robot);
robotData.printJunction(robot);
}
robot.face(direction);
}
/* The specification advised to have to seperate controls: Explorer and Backtrack
and a variable explorerMode to switch between them.
Instead, whenever needed I shall call this backtrack method.
If at a junction, the robot will head back the junction as to when it first approached it.
When at a deadend or corridor, it will follow the beenbefore squares until it
reaches an unexplored path. */
public int backtrack (IRobot robot) {
if (nonwallExits(robot) > 2) {
return robotData.reverseHeading(robot);
} else {
do {
return nonWallDirections.get(0);
} while (nonwallExits(robot) == 1);
}
}
// Deadend method makes the robot follow the only nonwall exit.
public int deadEnd (IRobot robot) {
return backtrack(robot);
}
/* Corridor method will make the robot follow the one and only passage.
The exception is at the start. Sometimes, the robot will start with
two passages available to it in which case it will choose one randomly.
If there is no passage, it will follow the beenbefore squares
until it reaches an unexplored path.*/
public int corridor (IRobot robot) {
if (passageExits(robot) == 1) {
return passageDirections.get(0);
} else if (passageExits(robot) == 2) {
int randomPassage = random.nextInt(passageDirections.size());
return passageDirections.get(randomPassage);
} else {
return backtrack(robot);
}
}
/* Junction method states if there is more than one passage, it will randomly select one.
This applies to crossroads as well as essentially they are the same.
If there is no passage, it will follow the beenbefore squares until it reaches an unexplored
path. */
public int junction(IRobot robot) {
if (passageExits(robot) == 1) {
return passageDirections.get(0);
} else if (passageExits(robot) > 1) {
int randomPassage = random.nextInt(passageDirections.size());
return passageDirections.get(randomPassage);
} else {
return backtrack(robot);
}
}
// Calculates number of exits.
private int nonwallExits (IRobot robot) {
int nonwallExits = 0;
for(int item : directions) {
if(robot.look(item) != IRobot.WALL) {
nonwallExits++;
}
}
return nonwallExits;
}
// Calculates number of passages.
private int passageExits (IRobot robot) {
int passageExits = 0;
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
passageExits++;
}
}
return passageExits;
}
// Calculates number of beenbefores.
private int beenbeforeExits (IRobot robot) {
int beenbeforeExits = 0;
for(int item : directions) {
if(robot.look(item) == IRobot.PASSAGE) {
beenbeforeExits++;
}
}
return beenbeforeExits;
}
// Resets Junction Counter in RobotData class.
public int reset() {
return robotData.resetJunctionCounter();
}
}
class RobotData {
/* It was advised in the specification to include the variable:
private static int maxJunctions = 10000;
However, as I am not using arrays, but ArrayLists, I do not
need this. */
private static int junctionCounter = 0;
private ArrayList<Junction> junctionList = new ArrayList<Junction>();
private Iterator<Junction> junctionIterator = junctionList.iterator();
// Resets the Junction counter.
public int resetJunctionCounter() {
return junctionCounter = 0;
}
// Adds the current junction to the list of arrays.
public void addJunction(IRobot robot) {
Junction newJunction = new Junction(robot.getLocation().x, robot.getLocation().y, robot.getHeading());
junctionList.add(newJunction);
junctionCounter++;
}
// Gets the junction counter for Junction info method in Junction class.
public int getJunctionCounter (IRobot robot) {
return junctionCounter;
}
// Prints Junction info.
public void printJunction(IRobot robot) {
String course = "";
switch (robot.getHeading()) {
case IRobot.NORTH:
course = "NORTH";
break;
case IRobot.EAST:
course = "EAST";
break;
case IRobot.SOUTH:
course = "SOUTH";
break;
case IRobot.WEST:
course = "WEST";
break;
}
System.out.println("Junction " + junctionCounter + " (x=" + robot.getLocation().x + ", y=" + robot.getLocation().y +") heading " + course);
}
/* Iterates through the junction arrayList to find the
heading of the robot when it first approached the junction. */
public int searchJunction(IRobot robot) {
Junction currentJunction = junctionIterator.next();
while (junctionIterator.hasNext()) {
if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y)))
break;
}
return currentJunction.arrived;
}
// Returns the reverse of the heading the robot had when first approaching the junction.
public int reverseHeading(IRobot robot) {
int firstHeading = searchJunction(robot);
int reverseHeading = 1; // Random integer to Iniitalise variable.
switch (firstHeading) {
case IRobot.NORTH:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.BEHIND;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.RIGHT;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.AHEAD;
else
reverseHeading = IRobot.LEFT;
break;
case IRobot.EAST:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.LEFT;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.BEHIND;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.RIGHT;
else
reverseHeading = IRobot.AHEAD;
break;
case IRobot.SOUTH:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.AHEAD;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.LEFT;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.BEHIND;
else
reverseHeading = IRobot.RIGHT;
break;
case IRobot.WEST:
if (robot.getHeading() == IRobot.NORTH)
reverseHeading = IRobot.RIGHT;
else if (robot.getHeading() == IRobot.EAST)
reverseHeading = IRobot.AHEAD;
else if (robot.getHeading() == IRobot.SOUTH)
reverseHeading = IRobot.LEFT;
else
reverseHeading = IRobot.BEHIND;
break;
}
return reverseHeading;
}
}
class Junction {
int x;
int y;
int arrived;
public Junction(int xcoord, int ycoord, int course) {
x = xcoord;
y = ycoord;
arrived = course;
}
}
Whenever it is backtracking and reaches a junction it has already visited, it freezes and this comes up.
`java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor41.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at uk.ac.warwick.dcs.maze.controllers.PolledControllerWrapper.start(PolledControllerWrapper.java:70)
at uk.ac.warwick.dcs.maze.logic.ControllerThread.run(ControllerThread.java:46)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at RobotData.searchJunction(Explorer.java:242)
at RobotData.reverseHeading(Explorer.java:255)
at Explorer.backtrack(Explorer.java:74)
at Explorer.junction(Explorer.java:122)
at Explorer.controlRobot(Explorer.java:56)
... 5 more`
I don't think your searchJunction() is right or safe, the ConcurrentModificationException might be thrown due to the incorrect iterator through junctionList . The problem should be more about the iterator rather than reflection.
You might try:
private Iterator<Junction> junctionIterator = junctionList.iterator(); doesn't make much sense since the list is empty when initialize a RobotData object. Try to move it into searchJunction()
Check hasNext() first then invoke next()
public int searchJunction(IRobot robot) {
Iterator<Junction> junctionIterator = junctionList.iterator();
while (junctionIterator.hasNext()) {
Junction currentJunction = junctionIterator.next();
if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y)))
break;
}
return currentJunction.arrived;
}
It looks like that issue is in following code -
`public int searchJunction(IRobot robot) {
Junction currentJunction = junctionIterator.next();
while (junctionIterator.hasNext()) {
if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y)))
break;
}
return currentJunction.arrived;
}
You are calling junctionIterator.next() before calling junctionIterator.hasNext(). Iterator specification says that you should call next() only after calling hasNext()
I'm quite new to pathfinding and recently got A-Star working for the first time in Java with Libgdx, but it has some flaws, it doesnt always find the fastest path , or the program simply kills itself(because it's too slow?) :/
(Input/Output here: Imgur album: White = untouched Node, green = start, red = target, blue = path, yellow = node is on closed list but unrelevant)
The rest of the code can be found on Github.
This is the code for the Algorithm itself:
Node lastNode;
Node[] neighborNodes;
int lowestF = 2000;
Node bestNode;
public void findPath() {
for(int x = 0; x < map.worldWidth; x++) {
for(int y = 0; y < map.worldHeight; y++) {
nodes[x][y].calculateHeuristic(targetNode);
}
}
lastNode = startNode;
while(lastNode != targetNode || !openList.isEmpty()) {
neighborNodes = map.getNeighbors(lastNode);
for(Node node:neighborNodes) {
if(node != null)
if(node.state != State.BLOCKED && !closedList.contains(node)) {
openList.add(node);
node.parentNode = lastNode;
}
}
lowestF = 1000;
for(Node node:openList) {
if(node.f <= lowestF) {
lowestF = node.f;
bestNode = node;
}
}
if(openList.isEmpty() && bestNode != targetNode) {
System.out.println("No Path possible");
return;
}
openList.remove(bestNode);
closedList.add(bestNode);
lastNode = bestNode;
lastNode.setState(State.SEARCHED);
}
reconstructPath();
}
public void reconstructPath() {
Node lastNode = targetNode;
while(lastNode != startNode) {
lastNode = lastNode.parentNode;
lastNode.setState(State.PATH);
}
setStartAndEnd();
}
And the Node Class:
public class Node {
public enum State {
NORMAL, BLOCKED, START, END, SEARCHED, PATH
}
public State state;
int xPos, yPos;
Color color;
Node parentNode;
int f;
int movementCost = 10;
int heuristic;
public Node(int x, int y) {
xPos = x;
yPos = y;
setState(State.NORMAL);
}
public void setState(State newState) {
state = newState;
}
public boolean isNodeClicked() {
int inputX = Gdx.input.getX();
int inputY = Gdx.graphics.getHeight() - Gdx.input.getY();
if(inputX > xPos*32 && inputX < xPos*32+32 &&
inputY > yPos*32 && inputY < yPos*32+32) {
return true;
}
return false;
}
public void calculateHeuristic(Node targetNode) {
heuristic = (Math.abs((xPos-targetNode.xPos)) + Math.abs((yPos-targetNode.yPos))) * movementCost;
f = movementCost+heuristic;
}
public int calculateHeuristic(Node finishNode, int useless) {
return (Math.abs((xPos-finishNode.xPos)) + Math.abs((yPos-finishNode.yPos))) * movementCost;
}
}
At the moment I'm using a 2-dimensional array for the map or nodes and Arraylist for open and closed list.
It'd be much appreciated if somebody could help me get my A-star to behave and explain to me what I did wrong, I would also be very grateful for any other criticism, since I want to improve my programming :)
Thanks for your help in Advance :)
Your problem is here:
public void calculateHeuristic(Node targetNode) {
heuristic = (Math.abs((xPos-targetNode.xPos)) + Math.abs((yPos- targetNode.yPos))) * movementCost;
f = movementCost+heuristic;
}
Your calculation of your heuristic is wrong, because your calculation of your movementCost is wrong. The cost of a node is not a fixed value. It's the summation of all of the costs to move between nodes along the path to that node so far. So your node should actually have a function,
public int calculateCost(){
if(parentNode != null){
return movementCost + parentNode.calculateCost();
} else{
return movementCost;
}
}
And your heuristic thus becomes:
public void calculateHeuristic(Node targetNode) {
heuristic = (Math.abs((xPos-targetNode.xPos)) + Math.abs((yPos- targetNode.yPos))) * movementCost;
f = calculateCost()+heuristic;
}
Your other problems look like they probably all come from the various typos/logical errors I mentioned in the comments (while(...||openSet.isEmpty()) instead of while(...|| !openSet.isEmpty()), etc)
My issue is more semantic than functional, As the code does seem to implement the deQueue and enQueue functions correctly.
The reheapDown and reheapUp functions are being used incorrectly, And i believe the issue lies in my heap function
package priqueue;
public class Hosheap{
private Patient[] elements;
private int numElements;
public Hosheap(int maxSize)
{
elements= new Patient[maxSize];
numElements=maxSize;
}
public void ReheapDown(int root,int bottom)
{
int maxChild;
int rightChild;
int leftChild;
leftChild=root*2+1;
rightChild=root*2+2;
if (leftChild<=bottom)
{
if(leftChild==bottom)
maxChild=leftChild;
else
{
if(elements[leftChild].getPriority() <= elements[rightChild].getPriority())
maxChild=rightChild;
else
maxChild=leftChild;
}
if(elements[root].getPriority()<elements[maxChild].getPriority())
{
Swap(root,maxChild);
ReheapDown(maxChild,bottom);
}
}
}
public void ReheapUp(int root,int bottom)
{
int parent;
if(bottom>root)
{
parent=(bottom-1)/2;
if(elements[parent].getPriority()<elements[bottom].getPriority())
{
Swap(parent,bottom);
ReheapUp(root,parent);
}
}
}
public void Swap(int Pos1, int Pos2)
{
Patient temp;
temp = elements[Pos1];
elements[Pos1]=elements[Pos2];
elements[Pos2]=temp;
}
public Patient getElement(int e)
{
return elements[e];
}
public void setElement(Patient p, int n)
{
elements[n]=p;
}
}
The idea is to rearrange a simple priority queue system so when a patient object is removed, ReheapUp or down correctly rearranges the queue, Which the code does not accomplish. Should i also include the priority queue code, Or is this already too lengthy?
I am using NetBeans IDE 6.0.1, If that helps.
Depending on your usage requirements, the answer relating to TreeSets will most probably do what you want.
However if you really need a queue, as opposed to a sorted collection, then the inbuilt PriorityQueue may be of use.
Not exactly answering your question, but with Java you may want to look into the built-in Collection classes. You can get priority queue behavior but using a TreeSet (a type of ordered-set) and implementing a custom Comparator for Patient instances. Depending what you're trying to achieve, this may be preferable. It would look something like this:
In Patient.java ...
class Patient implements Comparator {
...
public int compareTo(Patient other) {
return getPriority() > other.getPriority() ? 1 : 0;
}
Then in the place you want to use the queue
Set<Patient> queue = new TreeSet<Patient>();
queue.add(p1);
queue.add(p2);
//traverse in order of priority
for(Patient p : queue) {
doStuff();
}
Here is a simple implementation of a PriorityHeap. I coded it up pretty quick so it may have some flaws but I have implemented the pushUp() and pushDown() logic.
import java.util.Random;
public class Heap {
private Double[] data;
private int lastItem;
public Heap(int initialSize) {
// to simplify child/parent math leave the first index empty
// and use a lastItem that gives us the size
data = new Double[initialSize];
lastItem = 0;
}
public void insert(Double d) {
// double size if needed
// should have a matching shrink but this is example code
if (lastItem + 1 >= data.length) {
Double[] doubled = new Double[data.length * 2];
System.arraycopy(data, 0, doubled, 0, data.length);
data = doubled;
}
data[lastItem + 1] = d;
lastItem++;
pushUp(lastItem);
}
public void pushDown(int index) {
if (lastItem > 1) {
int leftChildIndex = index * 2;
int rightChildIndex = leftChildIndex + 1;
// assume that neither child will dominate (in priority)
// the item at index
int indexToPromote = index;
// there may not be a left child
if (leftChildIndex <= lastItem) {
Double leftChild = data[leftChildIndex];
Double tmp = data[index];
if (tmp.compareTo(leftChild) < 0) {
indexToPromote = leftChildIndex;
}
// there might not be a right child
if (rightChildIndex <= lastItem) {
Double rightChild = data[rightChildIndex];
tmp = data[indexToPromote];
if (tmp.compareTo(rightChild) < 0) {
indexToPromote = rightChildIndex;
}
}
}
// did either child dominate the item at index
// if so swap and push down again
if (indexToPromote != index) {
swap(index, indexToPromote);
pushDown(indexToPromote);
}
}
}
public void pushUp(int index) {
if (index > 1) {
// equivalent to floor((double)index/2.0d);
// if item at index is greater than its parent
// push the item up to until if finds a home
int parentIndex = index >>> 1;
Double parent = data[parentIndex];
Double item = data[index];
if (item.compareTo(parent) > 0) {
swap(parentIndex, index);
pushUp(parentIndex);
}
}
}
public Double removeTop() {
// assume size is zero then examine other cases
Double top = null;
if (lastItem > 1) {
// save the top item and take the bottom item and place it
// at the top the push the new top item down until it
// finds a home
top = data[1];
Double bottom = data[lastItem];
lastItem--;
data[1] = bottom;
pushDown(1);
} else if (lastItem == 1) {
top = data[1];
lastItem--;
}
return top;
}
public int size() {
return lastItem;
}
private void swap(int index1, int index2) {
Double temp = data[index1];
data[index1] = data[index2];
data[index2] = temp;
}
public static void main(String[] args) {
Heap heap = new Heap(4);
Random r = new Random();
for (int i = 0; i < 100000; i++) {
Double d = Double.valueOf(r.nextDouble() * 100.0d);
heap.insert(d);
}
double max = Double.MAX_VALUE;
while (heap.size() > 0) {
Double top = heap.removeTop();
if (top.doubleValue() > max) {
System.out.println("bad ordering...");
}
max = top.doubleValue();
System.out.println(max);
}
System.out.println("done...");
}
}