Directed graph and complexity - complexity-theory

I have a problem finding the complexity in my program.
It consists of one directed graph where each node has an arraylist of edges.
Do anyone know the complexsity of searching trough this directed graph?
My code:
class Project{
ArrayList<Task> subProject = null;
int manpower, maxNr;
Project(int maxNr, int manpower){
this.maxNr = maxNr;
this.manpower = manpower;
subProject = new ArrayList<Task>();
}
}
class Task {
int id, time, staff, slack;
String name;
int earliestStart, latestStart, finished;
ArrayList<Edge> outEdges = null;
int cntPredecessors;
Boolean rund;
Task(int n){
id = n;
cntPredecessors = 0;
outEdges = new ArrayList<Edge>();
rund = false;
}
}
class Edge {
int edges;
Edge(int edges){
this.edges = edges;
}
}
public void run(){
while(runTasks == false){
System.out.println("Time: " + runT);
for(Task t: subProject){
if(t.cntPredecessors == 0 && t.rund == false){ // Checks if there is no edges to the task and if the task hasen't started
System.out.println(" Starting: " + t.id);
ferdige.add(t);
t.rund = true;
t.earliestStart = runT;
t.finished = runT + t.time;
if(cirdep < t.finished){
cirdep = t.finished;
}
tId = t.id;
workers += t.staff;
System.out.println(" Current staff: " + workers);
}
if(t.cntPredecessors == 0 && t.finished == runT){
maxNr--;
System.out.println(" Finished: " + t.id);
minPre(t.id);
workers -= t.staff;
}
if((t.cntPredecessors == 0 && t.rund == false) || (t.cntPredecessors == 0 && t.finished == runT)){
System.out.println(" Current staff: " + workers);
}
}

With mo more information to go on, you can at least say it's $O(|V|)$ by using depth first search. But you have to do something to take care of isolated components, 'cause DFS can't get to a node if there's no path.

Related

How to find a path in a matrix which must pass through some cells

Given a 2d matrix, I have a start cell, end cell, cells that must be visited and cells that cannot be visited.
What would be the optimal way to find a path that:
starts at the start cell
ends at the end cell
passes through all must visit cell
does not pass through any cell that cannot be visited
does not pass any cell twice
we can only move left, right, up and down
The matrix size can be at most 10x10.
For example:
S - start
E - end
0 - can visit
X - can not visit
M - must visit
S 0 0 M 0
0 0 0 X 0
0 M 0 0 0
0 X 0 0 0
0 0 0 0 E
One solution would be:
* 0 * * *
* 0 * X *
* * * 0 *
0 X 0 0 *
0 0 0 0 *
The path doesn't necessarily should be the shortest one, but it would be nice if it can be, and it can be calculated quiet fast.
You can model the grid with a class Grid that would have a width and a height, and a set of must locations a set of mustNot locations:
public class Grid {
private final int width;
private final int height;
private final Set<Location> must = new HashSet<>();
private final Set<Location> mustNot = new HashSet<>();
public Grid(int width, int height,
Collection<Location> must, Collection<Location> mustNot) {
this.width = width;
this.height = height;
this.must.addAll(must);
this.mustNot.addAll(mustNot);
}
In that class, you would have a method solve that would take a start location and an end location, and would return the best path:
public PathNode solve(Location start, Location end) {
...
}
class Location looks like this:
public class Location {
public final int row;
public final int col;
public Location(int row, int col) {
this.row = row;
this.col = col;
}
#Override
public int hashCode() {
int hash = 7;
hash = 41 * hash + this.row;
hash = 41 * hash + this.col;
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Location other = (Location) obj;
if (this.row != other.row) {
return false;
}
return this.col == other.col;
}
#Override
public String toString() {
return "(" + row + ", " + col + ')';
}
}
Basically, it's a row and a col.
A path is a linked list of PathNodes:
public class PathNode {
public final Location loc;
public final PathNode link;
public PathNode(Location loc, PathNode link) {
this.loc = loc;
this.link = link;
}
public boolean contains(Location loc) {
PathNode n = this;
while (n != null) {
if (n.loc.equals(loc)) {
return true;
}
n = n.link;
}
return false;
}
}
I've added a contains method because of the condition that a path must not go through the same location twice.
Now, the algorithm is a breadth-first search:
public PathNode solve(Location start, Location end) {
List<PathNode> paths = new ArrayList<>();
if (validLoc(start.row, start.col) == null) {
return null;
}
paths.add(new PathNode(start, null));
for (int i = 0; i < paths.size(); ++i) {
PathNode path = paths.get(i);
Location loc = path.loc;
if (loc.equals(end)) {
// at the end point, we must still check the path goes through
// all the 'must' cells
if (allMustInPath(path)) {
// found a path
return path;
}
} else {
addToPaths(path, left(loc), paths);
addToPaths(path, right(loc), paths);
addToPaths(path, up(loc), paths);
addToPaths(path, down(loc), paths);
}
}
return null;
}
We still need a few more methods:
private Location left(Location loc) {
return validLoc(loc.row, loc.col-1);
}
private Location right(Location loc) {
return validLoc(loc.row, loc.col+1);
}
private Location up(Location loc) {
return validLoc(loc.row-1, loc.col);
}
private Location down(Location loc) {
return validLoc(loc.row+1, loc.col);
}
private Location validLoc(int row, int col) {
if (row >= 0 && row < height && col >= 0 && col < width) {
Location loc = new Location(row, col);
return mustNot.contains(loc) ? null : loc;
}
return null;
}
private boolean allMustInPath(PathNode path) {
for (Location loc: must) {
if (!path.contains(loc)) {
return false;
}
}
return true;
}
private void addToPaths(PathNode path, Location loc, List<PathNode> paths) {
if (loc == null) {
return;
}
loc = validLoc(loc.row, loc.col);
if (loc != null && !path.contains(loc)) {
paths.add(new PathNode(loc, path));
}
}
The path returned by the solve method, is actually in backward order. For your example above, it finds the path that you mentionned:
Grid grid = new Grid(5,5,
Arrays.asList(
new Location(0,3),
new Location(2,1)),
Arrays.asList(
new Location(1,3),
new Location(3,1)));
PathNode path = grid.solve(
new Location(0,0),
new Location(4,4));
if (path == null) {
System.out.println("No solution found");
}
while (path != null) {
System.out.println(path.loc);
path = path.link;
}
(4, 4)
(3, 4)
(2, 4)
(1, 4)
(0, 4)
(0, 3)
(0, 2)
(1, 2)
(2, 2)
(2, 1)
(1, 1)
(0, 1)
(0, 0)
Essentially, you need to calculate the minimum spanning tree ( MST, google it ).
Start with the cells that must be visited. These will be the nodes in the graph you apply the MST algorithm to. Find the lengths of the shortest paths between each pair of nodes ( in such a small problem you can easily do that manually ) These will be the links, and link costs you input to the MST.
Input the constructed graph to the MST method in your favorite graph-theory library.
For a more complicated version of this problem, which is solved using the same technique, see How to find a shortest path in a graph that while travelling it, you can "see" all the nodes within a radius

Optimizations for a recursive formula finding a path between two random nodes

I have written a recursive formula that finds a path between two nodes arranged in a grid pattern. My code works with two problems. The first is that sometimes the start node's position is changed from one to another number, but I fixed this by reassigning it after the recursion so it's not that big of a deal. The second issue is that it runs unbearably slow. It takes about 30 seconds to generate a 5x5 and I haven't been able to generate a 7x7 which is my ultimate goal. I am hoping that someone will see if there are any optimizations that can be made.
The Node class, shown below, has a Key property and a Value property. The Key is the position in the grid starting at 0. So, for a 5x5, the top left node will have a Key of 0 and the bottom right node will have a Key of 24. Each node has Up, Down, Left and Right properties that are the other nodes it is connected to. When there are no nodes in that direction, the value is null. For example, in a 5x5, a node with Key = 0 will have an Up of null, a Down of the node with Key = 5, a Left of null, and a Right of the node with Key = 1. As another example, still in a 5x5, a node with Key = 6 will have an Up of the node with Key = 1, a Down of the node with Key = 11, a Left of the node with Key = 5, and a Right of the node with Key = 7. The Position property is the path. The path starts with the node with Position = 1, then goes to the node with Position = 2 etc. until it reaches the end node, which would be position N*N on a NxN board (e.g. a 5x5 board would have an end node with position 25). These nodes are added to a list called nodeList-(a global variable). One of these nodes gets randomly marked as Start-(boolean) and a different node gets randomly assigned as End-(boolean).
The next part is the path. We want to find a random path (starting at 1) between the Start and End nodes that touches every other node without touching the same node twice. This is for a game, so it is important that it is random so the user doesn't play the same board twice. If this is not possible given the Start and End Positions, new Start and End positions are chosen and the algorithm is run again.
class Node
{
public int Key { get; set; }
public int? Position { get; set; } = null;
public Node Up { get; set; } = null;
public Node Down { get; set; } = null;
public Node Left { get; set; } = null;
public Node Right { get; set; } = null;
public bool Start = false;
public bool End = false;
public Node(int key)
{
Key = key;
}
}
public bool GeneratePath()
{
var current = nodeList.Where(w => w.Start).FirstOrDefault();
var start = current;
int position = 1;
bool Recurse(Node caller)
{
if (current.Position == null)
{
current.Position = position;
}
if (current.End)
{
return true;
}
var directions = GetDirections();
for (var i = 0; i < 4; i++)
{
var done = false;
if (directions[i] == 0 && current.Up != null && current.Up.Position == null
&& (!current.Up.End || position == n * n - 1))
{
var temp = current;
current = current.Up;
position++;
done = Recurse(temp);
}
else if (directions[i] == 1 && current.Down != null && current.Down.Position == null
&& (!current.Down.End || position == n * n - 1))
{
var temp = current;
current = current.Down;
position++;
done = Recurse(temp);
}
else if (directions[i] == 2 && current.Left != null && current.Left.Position == null
&& (!current.Left.End || position == n * n - 1))
{
var temp = current;
current = current.Left;
position++;
done = Recurse(temp);
}
else if (directions[i] == 3 && current.Right != null && current.Right.Position == null
&& (!current.Right.End || position == n*n - 1))
{
var temp = current;
current = current.Right;
position++;
done = Recurse(temp);
}
if(done)
{
return true;
}
}
current.Position = null;
position--;
if(caller == null)
{
return false;
}
current = caller;
return false;
}
var success = Recurse(null);
if (success)
{
start.Position = 1;
}
return success;
}
private int[] GetDirections()
{
List<int> toPerm = new List<int>();
for (var i = 0; i < 4; i++)
{
toPerm.Add(i);
}
Random random = new Random();
var perms = HelperMethods.GetPermutations(toPerm, toPerm.Count);
var randomNumber = random.Next(0, perms.Count());
var directions = perms.ElementAt(randomNumber).ToArray();
return directions;
}
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
{
if (length == 1) return list.Select(t => new T[] { t });
return GetPermutations(list, length - 1)
.SelectMany(t => list.Where(o => !t.Contains(o)),
(t1, t2) => t1.Concat(new T[] { t2 }));
}
To reiterate, I am wondering if there are optimizations I can make as it runs too slow for my purposes.
So I found an implementation of an amazing algorithm that can produce 10,000 7x7's in 12 seconds. You can find the implementation here. The author is Nathan Clisby and it is based off of a paper “Secondary structures in long compact polymers”. The idea is to produce a non-random path between the two points, then randomly mutate the path as many times as the user wishes. Supposedly, with enough iterations, this algorithm can produce paths that are nearly as random as the algorithm I posted in the question.
Way to go computer scientists!

Path finding with theta* when the triangle inequality is not fulfilled

I try to use the theta* algorithm (aigamedev.com/open/tutorial/lazy-theta-star) to find the fastest path on a rectangular grid. Distances are euqlidian, but speed between nodes is time dependent and varies between directions. So the triangle inequality, which is a prerequisite for the algorithm, is violated. Still it works excellently in most cases. How could I modify the code to work nicely also in turbulent areas? I suspect I may have to reevaluate some closed nodes and put them back into the open list. If so, under what conditions? An extensive web search hasn't helped.
vertex_t *thetastar(vertex_t *startnode, vertex_t *finishnode, double starttime) {
vertex_t *s, *s1;
double gold, gnew;
int dir; //8 directions to search for node neighbours
//Initialize
vertex[0].row = startnode->row;
vertex[0].col = startnode->col;
vertex[0].g = starttime;
vertex[0].h = h(&vertex[0], finishnode);
vertex[0].open = true;
vertex[0].closed = false;
vertex[0].parent = &vertex[0];
openlist[0] = &vertex[0];
openlist[1] = NULL;
//Find path
while ((s = pop(openlist)) != NULL) {
if (s->row == finishnode->row && s->col == finishnode->col) {
return s;
}
s->closed = true;
for (dir = 0; dir < 8; dir++) {
if ((s1 = nghbrvis(s, dir)) != NULL) {
if (!s1->closed) {
if (!s1->open) {
s1->g = inftime;
s1->parent = NULL;
}
gold = s1->g;
//Path 2
if (lineofsight(s->parent, s1)) {
gnew = (s->parent)->g + c(s->parent, s1);
if (gnew < s1->g) {
s1->parent = s->parent;
s1->g = gnew;
} }
//Path 1
gnew = s->g + c(s, s1);
if (gnew < s1->g) {
s1->parent = s;
s1->g = gnew;
}
if (s1->g < gold) {
s1->h = h(s1, finishnode);
if (s1->open)
remove(s1, openlist);
insert(s1, openlist);
} } } } }
return NULL;
}

Print every leaf path of a tree without recursive

How do I print every leaf path of a tree without using recursion.
It is a tree, NOT a binary tree
struct node {
int data
std::vector<node*> children;
}
Print all the path from root to leaf, i.e. the following is the tree
r:is the root node
d, m, n are r's children
x,y,z are d's children
there is no child for m
o, p are n's children
-------------root
------d m n
---x y z o p
The result should be:
root-d-x
root-d-y
root-d-z
root-m
root-n-o
root-n-p
I tried to use non-recursive way but failed.
public static void printAllPathToLeafNonRecursive(Node root) {
if (root == null) {
return;
}
Queue<Object> q = new LinkedList<Object>();
q.add(root);
q.add(root.data + "");
while(!q.isEmpty()){
Node head = (Node) q.poll();
String headPath = (String) q.poll();
if(head.isLeaf()){
System.out.println(headPath);
continue;
}
if(head.left!=null){
String leftStr = headPath + "->" + head.left.data;
q.add(head.left);
q.add(leftStr);
}
if(head.right!=null){
String rightStr = headPath + "->" + head.right.data;
q.add(head.right);
q.add(rightStr);
}
}
}
Here's a Python solution based purely on pre-order iterative traversal using a stack. Prints both the paths and pathsums.
class Stack(object): # just for reference
def __init__(self):
self.a = []
def push(self, b):
self.a.append(b)
def peek(self):
return self.a[-1]
def pop(self):
return self.a.pop()
def isEmpty(self):
return len(self.a) == 0
def show(self):
return self.a
def paths(troot): # you should create your own Tree and supply the root
current = troot
s = Stack()
s.push(current)
s.push(str(current.key))
s.push(current.key)
while not s.isEmpty():
pathsum = s.pop()
path = s.pop()
current = s.pop()
if not current.left and not current.right:
print 'path: %s, pathsum: %d' % (path, pathsum)
if current.right:
rightstr = path + "->" + str(current.right.key)
rightpathsum = pathsum * 10 + current.right.key
s.push(current.right)
s.push(rightstr)
s.push(rightpathsum)
if current.left:
leftstr = path + "->" + str(current.left.key)
leftpathsum = pathsum * 10 + current.left.key
s.push(current.left)
s.push(leftstr)
s.push(leftpathsum)
For example, for the following tree:
3
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
1 7
/ \ / \
/ \ / \
/ \ / \
/ \ / \
0 2 5 8
/ \ / \ / \ / \
/ \ / \ / \ / \
NUL NUL NUL NUL 4 6 NUL 9
The output would be:
>>> paths()
path: 3->1->0, pathsum: 310
path: 3->1->2, pathsum: 312
path: 3->7->5->4, pathsum: 3754
path: 3->7->5->6, pathsum: 3756
path: 3->7->8->9, pathsum: 3789
The strategy is simple. Go down, right, then up. At each point you know where to go next.
Keep a vector which is your current place in the tree. Start it on the root. And then in pseudocode:
while True:
if not a leaf:
current_place.push_back(0) // move down one
else:
print current path.
while can't move right:
if at root:
exit()
current_place.pop_back() //move up one
current_place[-1] += 1
Those operations will require function calls. But they are function calls with loops, not recursion, so it is not recursive.
In the end,it's just a graph. There are different types of graph traversals. Just use dfs with a stack,and print nodes from which you don't have forward edges.
public static void RoottoPathPrint(BinaryTreeNode root) {
Stack<Object> stack = new Stack<Object>();
if (root == null)
return;
stack.push(root.getData() + "");
stack.push(root);
while (!stack.isEmpty()) {
BinaryTreeNode temp = (BinaryTreeNode) stack.pop();
String path = (String) stack.pop();
if (temp.getRight() != null) {
stack.push(path + temp.getRight().getData());
stack.push(temp.getRight());
}
if (temp.getLeft() != null) {
stack.push(path + temp.getLeft().getData());
stack.push(temp.getLeft());
}
if (temp.getLeft() == null && temp.getRight() == null) {
System.out.println(path);
}
}
}
The idea being to keep track of both the path and the nodes in a single stack as we traverse down the tree. The Object stack takes care of that.
Hope that helped !!
private void rootToLeaf(BSTNode root){
Stack<Map<BSTNode,ArrayList<Integer>>> tmpStack = new Stack<Map<BSTNode,ArrayList<Integer>>>();
Map<BSTNode,ArrayList<Integer>> tmpMap = new HashMap<BSTNode,ArrayList<Integer>>();
//List<Integer> tmp_arraylist = new ArrayList<Integer>();
ArrayList<Integer> tmpList = new ArrayList<Integer>();
tmpList.add(root.data);
tmpMap.put(root, tmpList);
tmpStack.push(tmpMap);
while(!tmpStack.isEmpty()){
Map<BSTNode,ArrayList<Integer>> temp_map = tmpStack.pop();
for(BSTNode node : temp_map.keySet()){
if(node.getLeft()==null && node.getRight()==null){
for(int i: temp_map.get(node)){
System.out.print(i+" ");
}
System.out.println();
}
if(node.getRight()!=null){
ArrayList<Integer> tmp_List = new ArrayList<Integer>();
for(int i: temp_map.get(node)){
tmp_List.add(i);
}
tmp_List.add(node.getRight().getData());
Map<BSTNode,ArrayList<Integer>> tmphashMap = new HashMap<BSTNode,ArrayList<Integer>>();
tmphashMap.put(node.getRight(), tmp_List);
tmpStack.push(tmphashMap);
}
if(node.getLeft()!=null){
ArrayList<Integer> tmp_List = new ArrayList<Integer>();
for(int i: temp_map.get(node)){
tmp_List.add(i);
}
tmp_List.add(node.getLeft().getData());
Map<BSTNode,ArrayList<Integer>> tmphashMap = new HashMap<BSTNode,ArrayList<Integer>>();
tmphashMap.put(node.getLeft(), tmp_List);
tmpStack.push(tmphashMap);
}
}
}
}
For n-ary tree - DFS and BFS based Path, Sum
100
/ / \ \
1 2 3 4
/ / / / / / \
10 11 12 13 14 40 41
/ \
400 401
public void traverseDFS(Node root) {
Stack<Node> s = new Stack<Node>();
Stack<String> sPath = new Stack<>();
Stack<Integer> sSum = new Stack<>();
s.push(root); sPath.push(root.Id + ""); sSum.push(root.Id);
while (!s.isEmpty()) {
// Pop out
Node head = s.pop(); String headPath = sPath.pop(); Integer headSum = sSum.pop();
if(head.children == null || head.children.isEmpty()){ //Leaf
System.out.println(headPath + "(" + headSum+")");
continue;
}
for(Node child : head.children) {
String path = headPath + "->" + child.Id;
Integer sum = headSum + child.Id;
// Push on stack
s.push(child); sPath.push(path); sSum.push(sum);
}
}
}
public static void traverseBFS(Node root) {
Queue<Node> q = new LinkedList<>();
Queue<String> qPath = new LinkedList<>();
Queue<Integer> qSum = new LinkedList<>();
q.add(root); qPath.add(root.Id + ""); qSum.add(root.Id);
while(!q.isEmpty()){
// Poll the q
Node head = q.poll(); String headPath = qPath.poll(); Integer headSum = qSum.poll();
if(head.children == null || head.children.isEmpty()){ //Leaf
System.out.println(headPath + "(" + headSum+")");
continue;
}
for(Node child : head.children) {
String path = headPath + "->" + child.Id;
Integer sum = headSum + child.Id;
// Add to the q
q.add(child); qPath.add(path); qSum.add(sum);
}
}
}
class Node {
int Id;
String Data;
Node Parent;
ArrayList<Node> children;
public Node(int id, String data) {
Id = id;
Data = data;
}
}
Output
-----------Depth FS-------------
100->4->41(145)
100->4->40->401(545)
100->4->40->400(544)
100->3(103)
100->2(102)
100->1->14(115)
100->1->13(114)
100->1->12(113)
100->1->11(112)
100->1->10(111)
-----------BFS-------------
100->2(102)
100->3(103)
100->1->10(111)
100->1->11(112)
100->1->12(113)
100->1->13(114)
100->1->14(115)
100->4->41(145)
100->4->40->400(544)
100->4->40->401(545)
public void allPathsToLeafNodesWithPreOrderDFS() {
Stack<Node> stack = new Stack<> ();
stack.push (root);
List<Deque<Integer>> paths = new ArrayList<> ();
while (!stack.isEmpty ()) {
Node pop = stack.pop ();
System.out.print (" " + pop.data);
if (pop.isLeaf ()) {
Deque<Integer> path = new ArrayDeque<> ();
Node current = pop;
while (current != null) {
path.add (current.data);
current = current.parent;
}
paths.add (path);
}
if (pop.right != null) {
pop.right.parent = pop;
stack.push (pop.right);
}
if (pop.left != null) {
pop.left.parent = pop;
stack.push (pop.left);
}
}
System.out.println ("paths = " + paths);
}
public void allPathsToLeafNodesWithInOrderDFS() {
Stack<Node> stack = new Stack<> ();
List<Deque<Integer>> paths = new ArrayList<> ();
Node current = root;
while (!stack.isEmpty () || current != null) {
if (current != null) {
stack.push (current);
if (current.left != null) current.left.parent = current;
current = current.left;
} else {
Node pop = stack.pop ();
System.out.println (" " + pop.data);
if (pop.isLeaf ()) {
Deque<Integer> path = new ArrayDeque<> ();
Node now = pop;
while (now != null) {
path.add (now.data);
now = now.parent;
}
paths.add (path);
}
current = pop.right;
if (pop.right != null) pop.right.parent = pop;
}
}
System.out.println ("paths = " + paths);
}
public void allPathsToLeafNodesWithBFS (){
List<Deque<Integer>> paths = new ArrayList<> ();
Queue<Node> queue = new LinkedList<> ();
queue.add (root);
while (!queue.isEmpty ()){
Node poll = queue.poll ();
System.out.println ("poll = " + poll);
if (poll.isLeaf ()){
Deque<Integer> path = new ArrayDeque<> ();
Node current = poll;
while (current != null){
path.add (current.data);
current = current.parent;
}
paths.add (path);
}
if(poll.left != null) {
poll.left.parent = poll;
queue.add (poll.left);
}
if(poll.right != null) {
poll.right.parent = poll;
queue.add (poll.right);
}
}
System.out.println ("paths = " + paths);
}

Binary Search Tree Balancing

I had a quesiton here, but it didn't save. I'm having trouble balancing a fully unbalanced tree (nodes 1-15 along the right side).
I'm having trouble because I get stack overflow.
> // balancing
public void balance(node n) {
if(n != null) {
System.out.println(height(n)-levels);
if (height(n.RCN) != height(n.LCN)) {
if (height(n.RCN) > height(n.LCN)) {
if(height(n.RCN) > height(n.LCN)) {
n = rotateL(n);
n = rotateR(n);
} else {
n = rotateL(n);
}
} else {
if(height(n.LCN) > height(n.RCN)) {
n = rotateR(n);
n = rotateL(n);
} else {
n = rotateR(n);
}
}
balance(n.LCN);
balance(n.RCN);
}
}
}
// depth from node to left
public int heightL(node n) {
if (n == null)
return 0;
return height(n.LCN) + 1;
}
// depth from node from the right
public int heightR(node n) {
if (n == null)
return 0;
return height(n.RCN) + 1;
}
// left rotation around node
public node rotateL(node n) {
if (n == null)
return null;
else {
node newRoot = n.RCN;
n.RCN = newRoot.LCN;
newRoot.LCN = n;
return newRoot;
}
}
// right rotation around node
public node rotateR(node n) {
if (n == null)
return null;
else {
node newRoot = n.LCN;
n.LCN = newRoot.RCN;
newRoot.RCN = n;
return newRoot;
}
}
Doing a rotateL followed by a rotateR ends up doing nothing since you are modifying the same node. n is not the original n. It is the newNode from the function. So basically, n is something like this:
newNode = rotateL(n);
n = rotateR(newNode);
So you are basically leaving the tree unchanged.
I am also unsure as to why you repeat the if (height(n.RCN) > height(n.LCN)) check. I think you meant your first check to be more like abs(height(n.RCN) - height(n.LCN)) > 1 and then use the comparison to determine which way to rotate.
Also, could you add the implementation for height(...)?

Resources