What data structure best mixes strengths of dictionary and list - algorithm

A question I asked recently left me wondering about the following:
What is the data structure to store a collection (key, value) pairs such that:
its elements are ordered
d[key] -> val has complexity O(dict)
d(index) -> (key, val) has complexity O(list)
provides reverse lookup d{val} -> (index, key) with complexity O(dict)
uses the least possible storage
When I type O(type) I mean the same complexity for the operation as data structure type.
For instance, if the ordered collection is:
c = {key_1:val_1, key_2:val_2, key_3:val_3}
I'd like to obtain
c[key_1] # returns val_1, as in a dictionary
c(1) # returns val_2, as in a list
c{val_3} # returns (2, key_3) as in a sort of "indexed dictionary"

You're asking for O(1) look-ups by key and index as well as O(1) value look-ups. You can do this by maintaining a hash data-structure for the key/values, a second hash structure for the reverse lookup and, a list data structure for the ordered list->key mappings. You'll still have O(n) insertations and deletions, though, and your space complexity will be 3 times what it normally would be.
If you're willing to compromise on speed, you can save on space, there are plenty of set data structures based on trees (TreeSet in Java for example), whose operations have complexity log(n).
It's always a trade off

You've not mentioned insertion cost, which is also an important concern. You could do this with a dictionary lexically ordered, and handle lookups using a binary search (which is log(n)). You'd need to maintain two such structures however, one going key->val and one going val->key, so the insertion cost is going to be double, and the need to insert elements in the middle puts that at O(n) (i.e., the same as for a list).

I had the same problem. So I took the source code of java.util.TreeMap and wrote IndexedTreeMap. It implements my own IndexedNavigableMap:
public interface IndexedNavigableMap<K, V> extends NavigableMap<K, V> {
K exactKey(int index);
Entry<K, V> exactEntry(int index);
int keyIndex(K k);
}
The implementation is based on updating node weights in the red-black tree when it is changed. Weight is the number of child nodes beneath a given node, plus one - self. For example when a tree is rotated to the left:
private void rotateLeft(Entry<K, V> p) {
if (p != null) {
Entry<K, V> r = p.right;
int delta = getWeight(r.left) - getWeight(p.right);
p.right = r.left;
p.updateWeight(delta);
if (r.left != null) {
r.left.parent = p;
}
r.parent = p.parent;
if (p.parent == null) {
root = r;
} else if (p.parent.left == p) {
delta = getWeight(r) - getWeight(p.parent.left);
p.parent.left = r;
p.parent.updateWeight(delta);
} else {
delta = getWeight(r) - getWeight(p.parent.right);
p.parent.right = r;
p.parent.updateWeight(delta);
}
delta = getWeight(p) - getWeight(r.left);
r.left = p;
r.updateWeight(delta);
p.parent = r;
}
}
updateWeight simply updates weights up to the root:
void updateWeight(int delta) {
weight += delta;
Entry<K, V> p = parent;
while (p != null) {
p.weight += delta;
p = p.parent;
}
}
And when we need to find the element by index here is the implementation that uses weights:
public K exactKey(int index) {
if (index < 0 || index > size() - 1) {
throw new ArrayIndexOutOfBoundsException();
}
return getExactKey(root, index);
}
private K getExactKey(Entry<K, V> e, int index) {
if (e.left == null && index == 0) {
return e.key;
}
if (e.left == null && e.right == null) {
return e.key;
}
if (e.left != null && e.left.weight > index) {
return getExactKey(e.left, index);
}
if (e.left != null && e.left.weight == index) {
return e.key;
}
return getExactKey(e.right, index - (e.left == null ? 0 : e.left.weight) - 1);
}
Also comes in very handy finding the index of a key:
public int keyIndex(K key) {
if (key == null) {
throw new NullPointerException();
}
Entry<K, V> e = getEntry(key);
if (e == null) {
throw new NullPointerException();
}
if (e == root) {
return getWeight(e) - getWeight(e.right) - 1;//index to return
}
int index = 0;
int cmp;
if (e.left != null) {
index += getWeight(e.left);
}
Entry<K, V> p = e.parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
while (p != null) {
cmp = cpr.compare(key, p.key);
if (cmp > 0) {
index += getWeight(p.left) + 1;
}
p = p.parent;
}
} else {
Comparable<? super K> k = (Comparable<? super K>) key;
while (p != null) {
if (k.compareTo(p.key) > 0) {
index += getWeight(p.left) + 1;
}
p = p.parent;
}
}
return index;
}
You can find the result of this work at http://code.google.com/p/indexed-tree-map/

Related

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!

Correct implementation of Min-Max in a tree

I implemented the min-max algorithm on a tree. The algorithm I created is working as intented, returning the path in the tree that corresponds to the min and max values. But my problem is that it doesn't feel right. My question is , is that a correct implementation of the min-max algorithm?
I couldn't find a pure implementation of the algorithm in a tree structure that consists of nodes. On the examples I manages to find ,people implemented the algorithm to solve problems related to games (tic-tac-toe). To be honest I felt stupid I couldn't make the connection.
I used 2 functions ,
1->evaluations_function which traverses the tree and adds value to nodes that don't have (a.k.a. all nodes that are not leaves).
2->print_optimal which traverses the tree and returns the path .
public void evaluation_function(Node root, int maxHeight, int rootHeight) {
if (root.childrenList.Count != 0) {
foreach (Node node in root.childrenList) {
evaluation_function(node, maxHeight, rootHeight);
}
}
if (root.height != rootHeight) {
if ((root.height % 2) == 0) {
if (root.value < root.parent.value || root.parent.value == 123456) {
root.parent.value = root.value;
}
} else if ((root.height % 2) != 0) {
if (root.value > root.parent.value || root.parent.value == 123456) {
root.parent.value = root.value;
}
}
}
}
And here is print_optimal
public void print_optimal(Node root) {
int maxValue = 0;
int minValue = 9999;
if (root.childrenList.Count != 0) {
if (root.height % 2 == 0) {
foreach (Node child in root.childrenList) {
if (child.value > maxValue) { maxValue = child.value; }
}
foreach (Node child in root.childrenList) {
if (child.value == maxValue) {
Console.WriteLine("Selected node " + child.name
+ " with value = " + child.value + " as MAX player");
print_optimal(child);
}
}
} else {
foreach (Node child in root.childrenList) {
if (child.value < minValue) { minValue = child.value; }
}
foreach (Node child in root.childrenList) {
if (child.value == minValue) {
Console.WriteLine("Selected node " + child.name
+ " with value = " + child.value + " as MIN player");
print_optimal(child);
}
}
}
}
}
I don't want to swarm the question with code , as my question is theoretical. But if you want to see the data struct or want to test the algorithm you can find it here : https://github.com/AcidDreamer/AI_Exercises/tree/master/1.2.1/Exercise1_2_1/Exercise1_2_1
IMPROVEMENT
evaluation_function changed to
public void evaluation_function(Node root, int rootHeight) {
if (root.childrenList.Count != 0) {
foreach (Node node in root.childrenList) {
evaluation_function(node, rootHeight);
}
}
if (root.height != rootHeight || root.childrenList.Count != 0) {
int maxValue = 0, minValue = 999;
if ((root.height % 2) == 0) {
foreach (Node child in root.childrenList) {
if (maxValue < child.value) {
maxValue = child.value;
root.value = maxValue;
root.bestChild = child;
}
}
} else if ((root.height % 2) != 0) {
foreach (Node child in root.childrenList) {
if (minValue > child.value) {
minValue = child.value;
root.value = minValue;
root.bestChild = child;
}
}
}
}
}
giving values to the current nodes.
print_optimal had a huge improvement using a bestChild field and is changed to
public void print_optimal(Node root) {
if (root.bestChild != null) {
Console.Write(root.name + "->");
print_optimal(root.bestChild);
} else {
Console.WriteLine(root.name);
}
}
I find it a little unnatural that the evaluation_function, which receives a Node as input, actually updates the value for the parent node.
I feel that a better approach would be for that function to update the current node instead.
It should do nothing if the current node is a leaf.
Otherwise, it should iterate through all the children (as it currently does in the first loop), and after each recursive call for a child, it should also check whether the current node value should be updated (i.e. a better value was just encountered, for the current child).
In addition, it is possible to add an additional field to each node, e.g. bestChild, or bestMove, to avoid re-iterating through children when calling print-optimal.
Overall your code is good (which you knew, since it works), but I have some remarks about improvements:
evaluation_function: you do not use maxHeight at all. Use it or remove the parameter. It's weird (kind of bad practice) that the function changes the parents of the current node. It should rather look at the children's values (if not leaf), and update the current node's value depending on that. Besides, you could add a field to keep track of the best child (or even of the selected path to a leaf) to avoid the matching process in print_optimal.
print_optimal(): You currently have a problem if 2 children have the same values: you'll print both of them and explore both trees. Checking if (child.value < minValue) { minValue = child.value; } is useless since you assume you've already used evaluation_function(), and it is not enough to "replace" evaluation_function if you had forgotten to do so.

How can I find a middle element in a linked list?

How can I find a middle element in a linked list by traversing the entire list only once?
The length of the list is not given, and I am allowed to only use two pointers. How can this be done?
I don't see how you could do it without traversing the entire list unless you know the length.
I'm guessing the answer wants one pointer to be traversing one element at a time, while the second pointer moves 2 elements at a time.
This way when the second pointer reaches the end, the first pointer will be at the middle.
The below code will help you get the middle element.
You need to use two pointers "fast" and "slow". At every step the fast pointer will increment by two and slower will increment by one. When the list will end the slow pointer will be at the middle.
Let us consider the Node looks like this
class Node
{
int data;
Node next;
}
And LinkedList has a getter method to provide the head of the linked list
public Node getHead()
{
return this.head;
}
The below method will get the middle element of the list (Without knowing the size of the list)
public int getMiddleElement(LinkedList l)
{
return getMiddleElement(l.getHead());
}
private int getMiddleElement(Node n)
{
Node slow = n;
Node fast = n;
while(fast!=null && fast.next!=null)
{
fast = fast.next.next;
slow = slow.next;
}
return slow.data;
}
Example:
If the list is 1-2-3-4-5 the middle element is 3
If the list is 1-2-3-4 the middle element is 3
In C, using pointers, for completeness. Note that this is based on the "Tortoise and Hare" algorithm used for checking if a linked list contains a cycle.
Our node is defined as the following:
typedef struct node {
int val;
struct node *next;
} node_t;
Then our algorithm is thus:
node_t *
list_middle (node_t *root)
{
node_t *tort = root;
node_t *hare = root;
while (hare != NULL && hare->next != NULL) {
tort = tort->next;
hare = hare->next->next;
}
return (tort);
}
For a list with an even number of nodes this returns the node proceding the actual centre (e.g. in a list of 10 nodes, this will return node 6).
There are two possible answers one for odd and one for even, both having the same algorithm
For odd: One pointer moves one step and second pointer moves two element as a time and when the second elements reach the last element, the element at which the first pointer is, the mid element. Very easy for odd.
Try: 1 2 3 4 5
For even: Same, One pointer moves one step and second pointer moves two element as a time and when the second elements cannot jump to next element, the element at which the first pointer is, the mid element.
Try: 1 2 3 4
LinkedList.Node current = head;
int length = 0;
LinkedList.Node middle = head;
while(current.next() != null){
length++;
if(length%2 ==0){
middle = middle.next();
}
current = current.next();
}
if(length%2 == 1){
middle = middle.next();
}
System.out.println("length of LinkedList: " + length);
System.out.println("middle element of LinkedList : " + middle);
Using a size variable you can maintain the size of the Linked list.
public class LinkedList {
private Node headnode;
private int size;
public void add(int i) {
Node node = new Node(i);
node.nextNode = headnode;
headnode = node;
size++;
}
public void findMiddleNode(LinkedList linkedList, int middle) {
Node headnode = linkedList.getHeadnode();
int count = -1;
while (headnode != null) {
count++;
if(count == middle) {
System.out.println(headnode.data);
}else {
headnode = headnode.nextNode;
}
}
}
private class Node {
private Node nextNode;
private int data;
public Node(int data) {
this.data = data;
this.nextNode = null;
}
}
public Node getHeadnode() {
return headnode;
}
public int getSize() {
return size;
}
}
Then from a client method find the middle of the size of the list:
public class MainLinkedList {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(5);
linkedList.add(3);
linkedList.add(9);
linkedList.add(4);
linkedList.add(7);
linkedList.add(99);
linkedList.add(34);
linkedList.add(798);
linkedList.add(45);
linkedList.add(99);
linkedList.add(46);
linkedList.add(22);
linkedList.add(22);
System.out.println(linkedList.getSize());
int middle = linkedList.getSize()/2;
linkedList.findMiddleNode(linkedList, middle);
}
}
I don’t know if this is better than the two node way, but here also you don’t have to traverse through the entire loop.
Using C# to find a middle element of the linked list:
static void Main(string[] args)
{
LinkedList<int> linked = new LinkedList<int>();
linked.AddLast(1);
linked.AddLast(3);
linked.AddLast(5);
linked.AddLast(6);
linked.AddFirst(12);
Console.WriteLine("Middle Element - " + ListMiddle<int>(linked));
Console.ReadLine();
}
public static T ListMiddle<T>(IEnumerable<T> input)
{
if (input == null)
return default(T);
var slow = input.GetEnumerator();
var fast = input.GetEnumerator();
while (slow.MoveNext())
{
if (fast.MoveNext())
{
if (!fast.MoveNext())
return slow.Current;
}
else
{
return slow.Current;
}
}
return slow.Current;
}
The below Java methods finds the middle of a linked list. It uses two pointers:
Slow pointers which moves by one in each iteration.
A fast pointer which moves twice in each iteration.
The slow pointer will point to the middle when fast reaches the end of the list
public SinglyLinkedListNode getMiddle(SinglyLinkedListNode list) {
if (list == null)
return null;
SinglyLinkedListNode fastPtr = list.next;
SinglyLinkedListNode slowPtr = list;
while (fastPtr != null) {
fastPtr = fastPtr.next;
if (fastPtr != null) {
slowPtr = slowPtr.next;
fastPtr = fastPtr.next;
}
}
return slowPtr;
}
For a doubly-linked list with given pointers to the head and tail node:
We can use both head and tail traversal:
p = head;
q = tail;
while(p != q && p->next != q)
{
p = p->next;
q = q->prev;
}
return p;
Introducing a pointer to the middle node may be an option, but functions like insertNode and deleteNode have to modify this pointer.
Python code for a middle element using the two-pointer method:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def printList(self):
temp = self.head
while(temp):
print(temp.data, end=" ")
temp = temp.next
def insertAtBeg(self, new_data):
new_node = Node(new_data)
if self.head is None:
self.head = new_node
return
new_node.next = self.head
self.head = new_node
def findMiddle(self):
fast_ptr = self.head
slow_ptr = self.head
if(self.head is not None):
while(fast_ptr is not None and fast_ptr.next is not None):
fast_ptr = fast_ptr.next.next
slow_ptr = slow_ptr.next
print('The middle element is ' + str (slow_ptr.data))
if __name__ == '__main__':
mylist = LinkedList()
mylist.insertAtBeg(10)
mylist.insertAtBeg(20)
mylist.insertAtBeg(30)
mylist.findMiddle()
Output:
The middle element is
import java.util.*;
public class MainLinkedList {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(10);
linkedList.add(32);
linkedList.add(90);
linkedList.add(43);
linkedList.add(70);
linkedList.add(20);
linkedList.add(45);
int middle = linkedList.size()/2;
System.out.println(linkedList.get(middle));
}
}
I am adding my solution which will work for both odd and even number of elements scenarios like:
1-2-3-4-5 middle element 3
1-2-3-4 middle element 2,3
It is inspired by the same fast pointer and slow pointer principle as mentioned in some of the other answers in the post.
public class linkedlist {
Node head;
static class Node {
int data;
Node next;
Node(int d) { data = d; next=null; }
}
public static void main(String args[]) {
linkedlist ll = new linkedlist();
Node one = new Node(1);
Node second = new Node(2);
Node third = new Node(3);
Node fourth = new Node(4);
Node five = new Node(5);
Node sixth = new Node(6);
Node seventh = new Node(7);
Node eight = new Node(8);
ll.head = one;
one.next = second;
second.next = third;
third.next = fourth;
fourth.next = five;
five.next = sixth;
sixth.next = seventh;
seventh.next = eight;
ll.printList();
ll.middleElement();
}
public void printList() {
Node n = head;
while(n != null) {
System.out.print(n.data + " ---> ");
n = n.next;
}
}
public void middleElement() {
Node headPointer = head;
Node headFasterPointer = head;
int counter = 0;
if(head != null) {
while(headFasterPointer.next != null) {
if(headFasterPointer.next.next != null) {
headFasterPointer = headFasterPointer.next.next;
headPointer = headPointer.next;
}
else
{
headFasterPointer = headFasterPointer.next;
}
counter++;
}
System.out.println();
System.out.println("The value of counter is " + counter);
if(counter %2 == 0) {
System.out.println("The middle element is " + headPointer.data + "," + headPointer.next.data);
}
else
{
System.out.println("The middle element is " + headPointer.data);
}
}
}
}
Class Node:
# Function to initialise the node object
def __init__(self, data):
self.data = data
self.next = None
Class LinkedList:
def __init__(self):
self.head = None
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
# Function to get the middle of
# the linked list
def printMiddle(self):
slow_ptr = self.head
fast_ptr = self.head
if self.head is not None:
while (fast_ptr is not None and fast_ptr.next is not None):
fast_ptr = fast_ptr.next.next
slow_ptr = slow_ptr.next
print("The middle element is: ", slow_ptr.data)
Driver code
list1 = LinkedList()
list1.push(5)
list1.push(4)
list1.push(2)
list1.push(3)
list1.push(1)
list1.printMiddle()
It's stupid to use two pointers, "fast" and "slow", because the operator next is used 1.5n times. There is no optimization.
Using a pointer to save the middle element can help you:
list* find_mid_1(list* ptr)
{
list *p_s1 = ptr, *p_s2 = ptr;
while (p_s2=p_s2->get_next())
{
p_s2 = p_s2->get_next();
if (!p_s2)
break;
p_s1 = p_s1->get_next();
}
return p_s1;
}

Why doesn't this work recursively?

Below is a program in Scala.
def range(low : Int, high : Int) : List[Int] = {
var result : List[Int] = Nil
result = rangerec(root, result, low, high)
result
}
private def rangerec(r : Node, l : List[Int], low : Int, high :Int) : List[Int] = {
var resultList : List[Int] = List()
if(r.left != null) {
rangerec(r.left, resultList, low, high)
} else if(r.right != null) {
rangerec(r.right, resultList, low, high)
} else {
if(r.key >= low && r.key <= high) {
resultList = resultList ::: List(r.key)
resultList
}
}
resultList
}
I made range method in my binary search tree, implementing in-order traversal algorithm. So it has to work recursively, but it doesn't print anything, List(). How to fix my algorithm? or edit my code?
I don't know scala, but you need to use list l passed as a parameter into recursive function and use output from rangerec function.
private def rangerec(r : Node, l : List[Int], low : Int, high :Int) : List[Int] = {
var resultList : List[Int] = l
if(r.left != null) {
resultList = rangerec(r.left, l, low, high)
} else if(r.right != null) {
resultList = rangerec(r.right, l, low, high)
} else {
if(r.key >= low && r.key <= high) {
resultList = l ::: List(r.key)
}
}
resultList
}
Define your resultList outside the function as I see you appending result to this variable. By the way, in order traversal follows this rule. Visit Left, Visit Root and finally Visit Right. However from the code (although I don't know scala), I can decipher that you are visiting left, right and finally root.
A equivalent recursive in-order printing javacode would have looked like this
public void printOrdered(Node node){
if(node.left != null){
printOrdered(node.left); //VISIT LEFT
}
System.out.println(node.data); //VISIT ROOT AND PRINT
if(node.right!=null){
printOrdered(node.right); //VISIT RIGHT
}
}
So, the scala may look like this (syntax may be wrong)
private def rangerec(r : Node) : Void = {
if(r.left != null) {
rangerec(r.left)
}
resultList = resultList :: List(r.key)
if(r.right != null) {
rangerec(r.right)
}
}
Here resultList is a variable of type List which should be passed from outside.

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