why is the average height of my BST so high? - java

im currently working on a uni project and i am having som edifficulty with my Binary search tree, each node has to have a value but also a random "balance value" which is between 0 and 1, if a nodes balance value is more than its parents then the tree needs to be rotated, either left or right depending on the side the child sits.
public class RandomBST {
class Node {
int x;
double balanceValue;
Node parent;
Node LChild;
Node RChild;
public Node(int i, double b) {
x = i;
balanceValue = b;
parent = this;
LChild = RChild = null;
}
}
Node root;
public double randomDouble() {
Random Ran = new Random();
return (0 + (1 - 0) * Ran.nextDouble());
}
public void insert(int i) {
double b = randomDouble();
root = Rec_insert(root, i, b);
Node p = findParent(root,i,-1);
if (p.balanceValue < b ){
if (p.x > i){
rotateLeft();
}else{
rotateRight();
}
}
}
Node Rec_insert(Node root, int i, double b) {
if (root == null) {
root = new Node(i, b);
return root;
}
if (i < root.x)
root.LChild = Rec_insert(root.LChild, i, b);
else if (i > root.x)
root.RChild = Rec_insert(root.RChild, i, b);
return root;
}
static Node findParent(Node node,int i, int parent) {
if (node == null)
return null;
if (node.x == i) {
return node.parent;
} else {
findParent(node.LChild, i, node.x);
findParent(node.RChild, i, node.x);
}
return node.parent;
}
int findMax(int a, int b){
if(a >= b)
return a;
else
return b;
}
int findHeight(Node root){
if(root == null)
return 0;
return findMax(findHeight(root.LChild), findHeight(root.RChild)) + 1;
}
public void rotateRight(){
Node previoius = root;
if (root.RChild!=null){
root = root.RChild;
}
previoius.RChild = root.LChild;
root.LChild = previoius;
}
public void rotateLeft(){
Node previoius = root;
if (root.LChild!=null){
root = root.LChild;
}
previoius.LChild = root.RChild;
root.RChild = previoius;
}
public static void main(String[] args) {
int total = 0;
for (int j = 0; j<1000;j++) {
RandomBST RBST = new RandomBST();
for (int i = 0; i < 1000; i++) {
RBST.insert(i);
}
int height = RBST.findHeight(RBST.root);
total =total + height;
}
System.out.println(total/1000);
}
}
any suggestions on where im goign wrong woukd be fantastic, the output is meant to be around 20 to 21, yet i get around 850.

Making a brand new random number generator with
Random Ran = new Random();
may make your random number ...little random.
Create one generator in your application and direct all calls to it.

Related

How to implement an AVL tree without storing height inside the node?

I am currently learning binary search tree. For a school assignment, I want to implement an self-balancing binary search tree (I choose AVL tree); however, the Node class cannot be modified. I cannot use the common implementation of the AVL tree (I can't store height inside the node).
This is the source code that I implemented (using HashMap).
public class Tree {
static class Student {
String id;
String name;
public Student(String id, String name) {
this.id = id;
this.name = name;
}
public String toString() {return id + ", " + name;}
}
private class Node {
Student e;
public Node lc, rc; // left child; right child
#SuppressWarnings("unused")
public Node(Student data) {
this.e = data;
}
public String toString() {
return e.toString();
}
}
Node root;
public HashMap<Node, Integer> map = new HashMap<>();
public void insert(Student s) {
root = insert(root, s);
}
public Node insert(Node curNode, Student s){
if (curNode == null){
Node newNode = new Node(s);
map.put(newNode, 1);
return newNode;
}
else if (s.name.compareTo(curNode.e.name) < 0)
curNode.lc = insert(curNode.lc, s);
else if (s.name.compareTo(curNode.e.name) > 0)
curNode.rc = insert(curNode.rc, s);
else return curNode;
int l, r;
map.put(curNode, max(nheight(curNode.rc),
nheight(curNode.lc)) + 1);
int balance = getBalance(curNode);
if (balance > 1 && s.name.compareTo(curNode.e.name) < 0)
return rightRotate(curNode);
if (balance < -1 && s.name.compareTo(curNode.e.name) > 0)
return leftRotate(curNode);
if(balance > 1 && s.name.compareTo(curNode.e.name) > 0){
curNode.lc = leftRotate(curNode.lc);
return rightRotate(curNode);
}
if(balance < -1 && s.name.compareTo(curNode.e.name) < 0){
curNode.rc = rightRotate(curNode.rc);
return leftRotate(curNode);
}
return curNode;
}
public int max(int a, int b){
return a > b ? a : b;
}
public int nheight(Node curRoot){
if (curRoot == null) return 0;
return map.get(curRoot);
}
public int getBalance(Node curNode){
if (curNode == null) return 0;
return nheight(curNode.lc) - nheight(curNode.rc);
}
public Node rightRotate(Node y){
Node x = y.lc;
Node T2 = x.rc;
x.rc = y;
y.lc = T2;
map.put(y, max(nheight(y.lc), nheight(y.rc)) + 1);
map.put(x, max(nheight(x.lc), nheight(x.rc)) + 1);
return x;
}
public Node leftRotate(Node x){
Node y = x.rc;
Node T2 = y.lc;
y.lc = x;
x.rc = T2;
map.put(x, max(nheight(x.lc), nheight(x.rc)) + 1);
map.put(y, max(nheight(y.lc), nheight(y.rc)) + 1);
return y;
}
}
I tried using a HashMap<Node, Integer> to store the height of each node, and using recursive method to calculate the height and balance factor every time. For small number of nodes, the above two methods would work; however, for large node size (>=1000000) those methods will not work. Is there any other data structures I can use the keep track of the height of each node?
This is the code I used to test. I randomly created 1000000 students with names and ids and insert them into the AVL tree.
public class Main {
public static void main(String[] args) {
Tree tree = new Tree();
String[] surnames = {"Chan", "Leung", "Li", "Lai", "Cheung", "Yeung", "Tang", "Chow", "Fung", "Tsang", "Kwok", "Chu", "Liu", "Wong", "Mak"};
SecureRandom random = new SecureRandom();
String[] names = new String[1000000];
for (int j = 0; j < names.length; j++) {
StringBuilder a = new StringBuilder();
for(int i = 0; i < 5; i ++) {
a.append((char)('a' + random.nextInt(25)));
}
names[j] = surnames[random.nextInt(surnames.length)] + " " + a.toString();
}
int id = 22222222;
for (String name : names) {
id += random.nextInt(100);
tree.insert(new Tree.Student(String.valueOf(id), name));
}
}
}
The code works fine when the size of the String is 1000 (String[1000]). It gets error when the size of String gets larger. For example, when it gets to 1000000. The error code is below.
Exception in thread "main" java.lang.NullPointerException: Cannot read field "lc" because "y" is null
Problem found. A careless mistake. I was focusing too much on the size of the input. The actual problem is with the insertion and rotations.
The amended code.
public Node insert(Node curNode, Student s){
if (curNode == null){
Node newNode = new Node(s);
map.put(newNode, 1);
return newNode;
}
else if (s.name.compareTo(curNode.e.name) < 0)
curNode.lc = insert(curNode.lc, s);
else if (s.name.compareTo(curNode.e.name) > 0)
curNode.rc = insert(curNode.rc, s);
else return curNode;
int l, r;
map.put(curNode, max(nheight(curNode.rc), nheight(curNode.lc)) + 1);
int balance = getBalance(curNode);
if (balance > 1 && s.name.compareTo(curNode.lc.e.name) < 0)
return rightRotate(curNode);
if (balance < -1 && s.name.compareTo(curNode.rc.e.name) > 0)
return leftRotate(curNode);
if(balance > 1 && s.name.compareTo(curNode.lc.e.name) > 0){
curNode.lc = leftRotate(curNode.lc);
return rightRotate(curNode);
}
if(balance < -1 && s.name.compareTo(curNode.rc.e.name) < 0){
curNode.rc = rightRotate(curNode.rc);
return leftRotate(curNode);
}
return curNode;
}

Sorting sets of 4 ints in circular list

I am playing around with circular linked list to represent polynomials with it.
Here is what I have so far:
Class for parts of polynomial:
public class Wielomian {
int wsp;
int a;
int b;
int c;
public Wielomian(){
wsp=0;
a=-1;
b=-1;
c=-1;
}
public Wielomian(int wsp, int a, int b, int c){
this.wsp = wsp;
this.a = a;
this.b = b;
this.c = c;
}
public String toString(){
return wsp+"(x^"+a+")(y^"+b+")(z^"+c+")";
}
}
wsp is coefficient and a,b,c are exponents of x, y and z.
Node:
public class Node {
protected Object data;
protected Node link;
public Node() {
link = null;
data = 0;
}
public Node(Object d,Node n) {
data = d;
link = n;
}
public void setLink(Node n) {
link = n;
}
public void setData(Object d) {
data = d;
}
public Node getLink() {
return link;
}
public Object getData() {
return data;
}
}
List:
class linkedList {
protected Node start ;
protected Node end ;
public int size ;
public linkedList() {
start = null;
end = null;
size = 0;
}
public boolean isEmpty() {
return start == null;
}
public int getSize() {
return size;
}
public void insertAtStart(Object val) {
Node nptr = new Node(val,null);
nptr.setLink(start);
if(start == null) {
start = nptr;
nptr.setLink(start);
end = start;
}
else {
end.setLink(nptr);
start = nptr;
}
size++ ;
}
/* Function to insert element at end */
public void insertAtEnd(Object val) {
Node nptr = new Node(val,null);
nptr.setLink(start);
if(start == null) {
start = nptr;
nptr.setLink(start);
end = start;
}
else {
end.setLink(nptr);
end = nptr;
}
size++ ;
}
/* Function to insert element at position */
public void insertAtPos(Object val , int pos) {
Node nptr = new Node(val,null);
Node ptr = start;
pos = pos - 1 ;
for (int i = 1; i < size - 1; i++)
{
if (i == pos)
{
Node tmp = ptr.getLink() ;
ptr.setLink( nptr );
nptr.setLink(tmp);
break;
}
ptr = ptr.getLink();
}
size++ ;
}
/* Function to delete element at position */
public void deleteAtPos(int pos) {
if (size == 1 && pos == 1) {
start = null;
end = null;
size = 0;
return ;
}
if (pos == 1) {
start = start.getLink();
end.setLink(start);
size--;
return ;
}
if (pos == size) {
Node s = start;
Node t = start;
while (s != end) {
t = s;
s = s.getLink();
}
end = t;
end.setLink(start);
size --;
return;
}
Node ptr = start;
pos = pos - 1 ;
for (int i = 1; i < size - 1; i++) {
if (i == pos) {
Node tmp = ptr.getLink();
tmp = tmp.getLink();
ptr.setLink(tmp);
break;
}
ptr = ptr.getLink();
}
size-- ;
}
}
And I realised I need another add method that will and sort those parts of polynomial while adding - first by exponent of x, if 2 will have equal then by exponent of y and so on.
The elements of list will be parts of polynomial and there also will be "head" which will be linked to the part with highest exponent at "x" and the last part of polynomial will be linked to this "head" making whole list circular. Head will have coefficient that equals 0 and exponats that equal -1 each. But I have no idea how to implement such method without ruining all the links etc. etc. I hope You guys can help me :)
I would also like to know best way to display my polynomial later. Will it be some kind of iteration through parts of polynomial and adding them to String until i reach "head"?

Actual path in maximum path sum in binary tree

I'm trying to store and print the actual path in the problem of finding maximum path sum in a binary tree. I already know how to find the maximum path sum (below), but how can we add a snippet to output the actual path?
private int maxSum;
public int maxPathSum(TreeNode root) {
maxSum = Integer.MIN_VALUE;
findMax(root);
return maxSum;
}
private int findMax(TreeNode p) {
if (p == null) return 0;
int left = findMax(p.left);
int right = findMax(p.right);
maxSum = Math.max(p.val + left + right, maxSum);
int ret = p.val + Math.max(left, right);
return ret > 0 ? ret : 0;
}
May you can try this.
static class Node {
int pathSum;
List<Integer> path;
Node(int pathSum) {
this.pathSum = pathSum;
this.path = new ArrayList<>();
}
}
public List<Integer> maxPathSum(TreeNode root) {
solve(root);
return maxPathTrace;
}
int maxPath = Integer.MIN_VALUE;
List<Integer> maxPathTrace = new ArrayList<>();
public Node solve(TreeNode root) {
if ( root == null) return new Node(0);
Node leftNode = solve(root.left);
Node rightNode = solve(root.right);
int leftGain = Math.max(leftNode.pathSum, 0);
int rightGain = Math.max(rightNode.pathSum, 0);
int resultGain = leftGain + rightGain + root.val;
// calculate max path and note it down
if ( resultGain > maxPath) {
maxPathTrace.clear();
if ( leftNode.pathSum >= 0) {
maxPathTrace.addAll(leftNode.path);
}
maxPathTrace.add(root.val);
if ( rightNode.pathSum >= 0) {
maxPathTrace.addAll(rightNode.path);
}
}
maxPath = Math.max(resultGain, maxPath);
//calculate return path
Node resultNode = new Node(Math.max(leftGain + root.val , rightGain + root.val));
if ( leftGain > rightGain ) {
if ( leftNode.pathSum >= 0) {
resultNode.path.addAll(leftNode.path);
}
resultNode.path.add(root.val);
} else {
resultNode.path.add(root.val);
if ( rightNode.pathSum >= 0) {
resultNode.path.addAll(rightNode.path);
}
}
return resultNode;
}

Binary Heap Implemented via a Binary Tree Structure

For an assignment, we were instructed to create a priority queue implemented via a binary heap, without using any built-in classes, and I have done so successfully by using an array to store the queued objects. However, I'm interested in learning how to implement another queue by using an actual tree structure, but in doing so I've run across a bit of a problem.
How would I keep track of the nodes on which I would perform insertion and deletion? I have tried using a linked list, which appends each node as it is inserted - new children are added starting from the first list node, and deleted from the opposite end. However, this falls apart when elements are rearranged in the tree, as children are added at the wrong position.
Edit: Perhaps I should clarify - I'm not sure how I would be able to find the last occupied and first unoccupied leaves. For example, I would always be able to tell the last inserted leaf, but if I were to delete it, how would I know which leaf to delete when I next remove the item? The same goes for inserting - how would I know which leaf to jump to next after the current leaf has both children accounted for?
A tree implementation of a binary heap uses a complete tree [or almost full tree: every level is full, except the deepest one].
You always 'know' which is the last occupied leaf - where you delete from [and modifying it is O(logn) after it changed so it is not a problem], and you always 'know' which is the first non-occupied leaf, in which you add elements to [and again, modifying it is also O(logn) after it changed].
The algorithm idea is simple:
insert: insert element to the first non-occupied leaf, and use heapify [sift up] to get this element to its correct place in the heap.
delete_min: replace the first element with the last occupied leaf, and remove the last occupied leaf. then, heapify [sift down] the heap.
EDIT: note that delete() can be done to any element, and not only the head, however - finding the element you want to replace with the last leaf will be O(n), which will make this op expensive. for this reason, the delete() method [besides the head], is usually not a part of the heap data structure.
I really wanted to do this for almost a decade.Finally sat down today and wrote it.Anyone who wants it can use it.I got inspired by Quora founder to relearn Heap.Apparently he was asked how would you find K near points in a set of n points in his Google phone screen.Apparently his answer was to use a Max Heap and to store K values and remove the maximum element after the size of the heap exceeds K.The approach is pretty simple and the worst case is nlog K which is better than n^2 in most sorting cases.Here is the code.
import java.util.ArrayList;
import java.util.List;
/**
* #author Harish R
*/
public class HeapPractise<T extends Comparable<T>> {
private List<T> heapList;
public List<T> getHeapList() {
return heapList;
}
public void setHeapList(List<T> heapList) {
this.heapList = heapList;
}
private int heapSize;
public HeapPractise() {
this.heapList = new ArrayList<>();
this.heapSize = heapList.size();
}
public void insert(T item) {
if (heapList.size() == 0) {
heapList.add(item);
} else {
siftUp(item);
}
}
public void siftUp(T item) {
heapList.add(item);
heapSize = heapList.size();
int currentIndex = heapSize - 1;
while (currentIndex > 0) {
int parentIndex = (int) Math.floor((currentIndex - 1) / 2);
T parentItem = heapList.get(parentIndex);
if (parentItem != null) {
if (item.compareTo(parentItem) > 0) {
heapList.set(parentIndex, item);
heapList.set(currentIndex, parentItem);
currentIndex = parentIndex;
continue;
}
}
break;
}
}
public T delete() {
if (heapList.size() == 0) {
return null;
}
if (heapList.size() == 1) {
T item = heapList.get(0);
heapList.remove(0);
return item;
}
return siftDown();
}
public T siftDown() {
T item = heapList.get(0);
T lastItem = heapList.get(heapList.size() - 1);
heapList.remove(heapList.size() - 1);
heapList.set(0, lastItem);
heapSize = heapList.size();
int currentIndex = 0;
while (currentIndex < heapSize) {
int leftIndex = (2 * currentIndex) + 1;
int rightIndex = (2 * currentIndex) + 2;
T leftItem = null;
T rightItem = null;
int currentLargestItemIndex = -1;
if (leftIndex <= heapSize - 1) {
leftItem = heapList.get(leftIndex);
}
if (rightIndex <= heapSize - 1) {
rightItem = heapList.get(rightIndex);
}
T currentLargestItem = null;
if (leftItem != null && rightItem != null) {
if (leftItem.compareTo(rightItem) >= 0) {
currentLargestItem = leftItem;
currentLargestItemIndex = leftIndex;
} else {
currentLargestItem = rightItem;
currentLargestItemIndex = rightIndex;
}
} else if (leftItem != null && rightItem == null) {
currentLargestItem = leftItem;
currentLargestItemIndex = leftIndex;
}
if (currentLargestItem != null) {
if (lastItem.compareTo(currentLargestItem) >= 0) {
break;
} else {
heapList.set(currentLargestItemIndex, lastItem);
heapList.set(currentIndex, currentLargestItem);
currentIndex = currentLargestItemIndex;
continue;
}
}
}
return item;
}
public static void main(String[] args) {
HeapPractise<Integer> heap = new HeapPractise<>();
for (int i = 0; i < 32; i++) {
heap.insert(i);
}
System.out.println(heap.getHeapList());
List<Node<Integer>> nodeArray = new ArrayList<>(heap.getHeapList()
.size());
for (int i = 0; i < heap.getHeapList().size(); i++) {
Integer heapElement = heap.getHeapList().get(i);
Node<Integer> node = new Node<Integer>(heapElement);
nodeArray.add(node);
}
for (int i = 0; i < nodeArray.size(); i++) {
int leftNodeIndex = (2 * i) + 1;
int rightNodeIndex = (2 * i) + 2;
Node<Integer> node = nodeArray.get(i);
if (leftNodeIndex <= heap.getHeapList().size() - 1) {
Node<Integer> leftNode = nodeArray.get(leftNodeIndex);
node.left = leftNode;
}
if (rightNodeIndex <= heap.getHeapList().size() - 1) {
Node<Integer> rightNode = nodeArray.get(rightNodeIndex);
node.right = rightNode;
}
}
BTreePrinter.printNode(nodeArray.get(0));
}
}
public class Node<T extends Comparable<?>> {
Node<T> left, right;
T data;
public Node(T data) {
this.data = data;
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class BTreePrinter {
public static <T extends Comparable<?>> void printNode(Node<T> root) {
int maxLevel = BTreePrinter.maxLevel(root);
printNodeInternal(Collections.singletonList(root), 1, maxLevel);
}
private static <T extends Comparable<?>> void printNodeInternal(
List<Node<T>> nodes, int level, int maxLevel) {
if (nodes.isEmpty() || BTreePrinter.isAllElementsNull(nodes))
return;
int floor = maxLevel - level;
int endgeLines = (int) Math.pow(2, (Math.max(floor - 1, 0)));
int firstSpaces = (int) Math.pow(2, (floor)) - 1;
int betweenSpaces = (int) Math.pow(2, (floor + 1)) - 1;
BTreePrinter.printWhitespaces(firstSpaces);
List<Node<T>> newNodes = new ArrayList<Node<T>>();
for (Node<T> node : nodes) {
if (node != null) {
String nodeData = String.valueOf(node.data);
if (nodeData != null) {
if (nodeData.length() == 1) {
nodeData = "0" + nodeData;
}
}
System.out.print(nodeData);
newNodes.add(node.left);
newNodes.add(node.right);
} else {
newNodes.add(null);
newNodes.add(null);
System.out.print(" ");
}
BTreePrinter.printWhitespaces(betweenSpaces);
}
System.out.println("");
for (int i = 1; i <= endgeLines; i++) {
for (int j = 0; j < nodes.size(); j++) {
BTreePrinter.printWhitespaces(firstSpaces - i);
if (nodes.get(j) == null) {
BTreePrinter.printWhitespaces(endgeLines + endgeLines + i
+ 1);
continue;
}
if (nodes.get(j).left != null)
System.out.print("//");
else
BTreePrinter.printWhitespaces(1);
BTreePrinter.printWhitespaces(i + i - 1);
if (nodes.get(j).right != null)
System.out.print("\\\\");
else
BTreePrinter.printWhitespaces(1);
BTreePrinter.printWhitespaces(endgeLines + endgeLines - i);
}
System.out.println("");
}
printNodeInternal(newNodes, level + 1, maxLevel);
}
private static void printWhitespaces(int count) {
for (int i = 0; i < 2 * count; i++)
System.out.print(" ");
}
private static <T extends Comparable<?>> int maxLevel(Node<T> node) {
if (node == null)
return 0;
return Math.max(BTreePrinter.maxLevel(node.left),
BTreePrinter.maxLevel(node.right)) + 1;
}
private static <T> boolean isAllElementsNull(List<T> list) {
for (Object object : list) {
if (object != null)
return false;
}
return true;
}
}
Please note that BTreePrinter is a code I took somewhere in Stackoverflow long back and I modified to use with 2 digit numbers.It will be broken if we move to 3 digit numbers and it is only for simple understanding of how the Heap structure looks.A fix for 3 digit numbers is to keep everything as multiple of 3.
Also due credits to Sesh Venugopal for wonderful tutorial on Youtube on Heap data structure
public class PriorityQ<K extends Comparable<K>> {
private class TreeNode<T extends Comparable<T>> {
T val;
TreeNode<T> left, right, parent;
public String toString() {
return this.val.toString();
}
TreeNode(T v) {
this.val = v;
left = null;
right = null;
}
public TreeNode<T> insert(T val, int position) {
TreeNode<T> parent = findNode(position/2);
TreeNode<T> node = new TreeNode<T>(val);
if(position % 2 == 0) {
parent.left = node;
} else {
parent.right = node;
}
node.parent = parent;
heapify(node);
return node;
}
private void heapify(TreeNode<T> node) {
while(node.parent != null && (node.parent.val.compareTo(node.val) < 0)) {
T temp = node.val;
node.val = node.parent.val;
node.parent.val = temp;
node = node.parent;
}
}
private TreeNode<T> findNode(int pos) {
TreeNode<T> node = this;
int reversed = 1;
while(pos > 0) {
reversed <<= 1;
reversed |= (pos&1);
pos >>= 1;
}
reversed >>= 1;
while(reversed > 1) {
if((reversed & 1) == 0) {
node = node.left;
} else {
node = node.right;
}
reversed >>= 1;
}
return node;
}
public TreeNode<T> remove(int pos) {
if(pos <= 1) {
return null;
}
TreeNode<T> last = findNode(pos);
if(last.parent.right == last) {
last.parent.right = null;
} else {
last.parent.left = null;
}
this.val = last.val;
bubbleDown();
return null;
}
public void bubbleDown() {
TreeNode<T> node = this;
do {
TreeNode<T> left = node.left;
TreeNode<T> right = node.right;
if(left != null && right != null) {
T max = left.val.compareTo(right.val) > 0 ? left.val : right.val;
if(max.compareTo(node.val) > 0) {
if(left.val.equals(max)) {
left.val = node.val;
node.val = max;
node = left;
} else {
right.val = node.val;
node.val = max;
node = right;
}
} else {
break;
}
} else if(left != null) {
T max = left.val;
if(left.val.compareTo(node.val) > 0) {
left.val = node.val;
node.val = max;
node = left;
} else {
break;
}
} else {
break;
}
} while(true);
}
}
private TreeNode<K> root;
private int position;
PriorityQ(){
this.position = 1;
}
public void insert(K val) {
if(val == null) {
return;
}
if(root == null) {
this.position = 1;
root = new TreeNode<K>(val);
this.position++;
return ;
}
root.insert(val, position);
position++;
}
public K remove() {
if(root == null) {
return null;
}
K val = root.val;
root.remove(this.position-1);
this.position--;
if(position == 1) {
root = null;
}
return val;
}
public static void main(String[] args) {
PriorityQ<Integer> q = new PriorityQ<>();
System.out.println(q.remove());
q.insert(1);
q.insert(11);
q.insert(111);
q.insert(1111);
q.remove();
q.remove();
q.remove();
q.remove();
q.insert(2);
q.insert(4);
}
}

Unable to implement A Star in java

I've been trying all day to get this algorithm up and running, but I cant for the life of me. I've read many tutorials on the net, and source code in AS3, javascript, and C++; but I cannot adapt what I am seeing to my own code.
I have created an AStar class that has a nested class named Node. The map is a 2D array named MAP.
The biggest problem that I am having is pulling the F value in the pathfind function.
I have implemented the F = G + H, my problem is the actual AStar algorithm. Can someone please help, this is how far I've got as of yet:
import java.util.ArrayList;
public class AStar
{
int MAP[][];
Node startNode, endNode;
public AStar(int MAP[][], int startXNode, int startYNode,
int endXNode, int endYNode)
{
this.MAP = MAP;
startNode = new Node(startXNode, startYNode);
endNode = new Node(endXNode, endYNode);
}
public void pathfinder()
{
ArrayList openList = new ArrayList();
ArrayList closedList = new ArrayList();
}
public int F(Node startNode, Node endNode)
{
return (H(startNode, endNode) + G(startNode));
}
//H or Heuristic part of A* algorithm
public int H(Node startNode, Node endNode)
{
int WEIGHT = 10;
int distance = (Math.abs(startNode.getX() - endNode.getX()) + Math.abs(startNode.getY() - endNode.getY()));
return (distance * WEIGHT);
}
public int G(Node startNode)
{
if(MAP[startNode.getX() - 1][startNode.getY()] != 1)
{
return 10;
}
if(MAP[startNode.getX() + 1][startNode.getY()] != 1)
{
return 10;
}
if(MAP[startNode.getX()][startNode.getY() -1] != 1)
{
return 10;
}
if(MAP[startNode.getX()][startNode.getY() + 1] != 1)
{
return 0;
}
return 0;
}
public class Node
{
private int NodeX;
private int NodeY;
private int gScore;
private int hScore;
private int fScore;
public Node(int NodeX, int NodeY)
{
this.NodeX = NodeX;
this.NodeY = NodeY;
}
public int getX()
{
return NodeX;
}
public int getY()
{
return NodeY;
}
public int getG()
{
return gScore;
}
public void setG(int gScore)
{
this.gScore = gScore;
}
public int getH()
{
return hScore;
}
public void setH(int hScore)
{
this.hScore = hScore;
}
public int getF()
{
return fScore;
}
public void setF(int fScore)
{
this.fScore = fScore;
}
}
}
This is the furthest I can ever get with the pathfinder function:
public void pathfinder()
{
LinkedList<Node> openList = new LinkedList();
LinkedList<Node> closedList = new LinkedList();
Node currentNode;
openList.add(startNode);
while(openList.size() > 0)
{
currentNode = (Node) openList.get(0);
closedList.add(currentNode);
for(int i = 0; i < openList.size(); i++)
{
int cost = F(currentNode, endNode);
}
}
}
I recently threw this A* code together to solve a Project Euler problem. You'll have to fill in the details for a matrix of Node objects. Use it at your own risk, however I can say it solved the problem :)
public class Node {
List<Node> neighbors = new ArrayList<Node>();
Node parent;
int f;
int g;
int h;
int x;
int y;
int cost;
}
public List<Node> aStar(Node start, Node goal) {
Set<Node> open = new HashSet<Node>();
Set<Node> closed = new HashSet<Node>();
start.g = 0;
start.h = estimateDistance(start, goal);
start.f = start.h;
open.add(start);
while (true) {
Node current = null;
if (open.size() == 0) {
throw new RuntimeException("no route");
}
for (Node node : open) {
if (current == null || node.f < current.f) {
current = node;
}
}
if (current == goal) {
break;
}
open.remove(current);
closed.add(current);
for (Node neighbor : current.neighbors) {
if (neighbor == null) {
continue;
}
int nextG = current.g + neighbor.cost;
if (nextG < neighbor.g) {
open.remove(neighbor);
closed.remove(neighbor);
}
if (!open.contains(neighbor) && !closed.contains(neighbor)) {
neighbor.g = nextG;
neighbor.h = estimateDistance(neighbor, goal);
neighbor.f = neighbor.g + neighbor.h;
neighbor.parent = current;
open.add(neighbor);
}
}
}
List<Node> nodes = new ArrayList<Node>();
Node current = goal;
while (current.parent != null) {
nodes.add(current);
current = current.parent;
}
nodes.add(start);
return nodes;
}
public int estimateDistance(Node node1, Node node2) {
return Math.abs(node1.x - node2.x) + Math.abs(node1.y - node2.y);
}
I dont know if you are trying only to use simple types, or if you just didn't think about it, but you need to have a PriorityQueue to get your A* working.
A good way to think is that you put your startpoint into a priority queue with distance 0, and then start a loop that only stops when the prioriy queue is empty.
In the loop you take the min-node out, and check to see if it hasnt been open before, or if it has, if you have now found a shorter way to it.
If either these are true, you add the distance to the new node, add the edge/from-square to a map, and then add the distance + heuristic to the priority queue.
I have written this to work on a grid of booleans, and a constant conversion between 1D and 2D arrays, but I hope it is readable:
public void AStarRoute()
{
gridDist = new double[rows][cols];
System.out.println("Start of AStarRoute");
MinPriorityQueue pq = new MinPriorityQueue(rows * cols);
edgeTo = new HashMap<Integer, Integer>();
gridDist[x1Dto2D(start)][y1Dto2D(start)] = 0;
pq.insert(start, 0);
int from;
while (!pq.isEmpty()) {
from = pq.delMin();
int x = x1Dto2D(from);
int y = y1Dto2D(from);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int newX = x + i;
int newY = y + j;
if (newX >= 0 && newY >= 0 && newX < cols && newY < rows && !(i == 0 && j == 0)) {
if (grid[newX][newY]) {
//System.out.println("NewDist: " + gridDist[newX][newY] + " - OldDist+dist: " + (gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 1.4 : 1.0)) + ":" + (int)(gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 1.4 : 1.0)));
if (!edgeTo.containsKey(convert2Dto1D(newX, newY)) || gridDist[newX][newY] > (gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 14 : 10))) {
gridDist[newX][newY] = (int)(gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 14 : 10));
maxDistToEnd = (int)Math.max(maxDistToEnd, gridDist[newX][newY]);
edgeTo.put(convert2Dto1D(newX, newY), convert2Dto1D(x, y));
pq.insert(convert2Dto1D(newX, newY), gridDist[newX][newY] + (int)Math.sqrt(Math.pow((newX - x1Dto2D(end))*10, 2) + Math.pow((newY - y1Dto2D(end))*10, 2)));
if(convert2Dto1D(newX, newY) == end){
System.out.println("End found at (" + newX + ", " + newY + ")");
paintGridDist = true;
route = new ArrayList<Integer>();
int n = convert2Dto1D(newX, newY);
route.add(n);
do{
n = edgeTo.get(n);
route.add(n);
}while(start != n);
repaint();
return;
}
}
}
}
}
}
}
paintGridDist = true;
repaint();
}

Categories