Adjust Range Search of BinaryTree to get the Outer Elements - c#

I have a RedBlack [Balanced, sorted] Binary Tree and I am searching it to find all the values within the range [lower, upper].
public IEnumerable<TData> Range(
BinaryTree<TData> root,
IComparer<TData> comparer,
TData lower,
TData upper)
{
var stack = new Stack<State>(16);
BinaryTree<TData> here = root;
do
{
if (here == null)
{
if (stack.Count == 0)
break;
State popped = stack.Pop();
yield return popped.Data;
here = popped.Next;
continue;
}
if (comparer.Compare(here.Data, lower) < 0)
{
here = here.Right;
}
else if (comparer.Compare(here.Data, upper) > 0)
{
here = here.Left;
}
else
{
stack.Push(new State {Next = here.Right, Data = here.Data});
here = here.Left;
}
} while (true);
}
So with this code, if I were to have a tree built with the values
[0, 1, 4, 5, 6, 9],
and search for all elements within the range
[3, 8]
I would get the following results:
[4, 5, 6].
My question is how can I do about adjusting this algorithm in order to get the outer elements of the search? like this:
[1, 4, 5, 6, 9]
i.e. the value 3 lies between 1 and 4 in the tree, so I want to return 1, similarly the value 8 lies between 6 and 9 and I would want the value 9 to be includes in the result.
One catch is I don't want to restart the search from root
Currently implemented using NGenerics
[Edit]
Willing to accept a general algorithmic answer.

I'm not sure with what you are trying to populate the Red Black Tree. But if you are using array or stream of data (whose number of elements will not change) then you may go this by using Segment Tree
class SegmentTree
{
class Node
{
int max, min, s, e;
Node left, right;
#Override
public String toString()
{
String str = "Min: "+this.min+" Max: "+this.max+" "+this.s+"-"+this.e;
return str;
}
}
private Node root;
public SegmentTree() {}
public SegmentTree(int[] array)
{
add(array);
}
public void add(int[] array)
{
root = add(0, array.length-1, array);
}
private Node add(int s, int e, int[] array)
{
Node n = new Node();
n.s = s;
n.e = e;
if(n.s==n.e)
{
n.min = n.max = array[n.s];
return n;
}
int mid = s+(e-s)/2;
n.left = add(s, mid, array);
n.right = add(mid+1, e, array);
n.max = Math.max(n.left.max, n.right.max);
n.min = Math.min(n.left.min, n.right.min);
return n;
}
// Get the max value between the limits l and r (both inclusive)
public int getMax(int l, int r)
{
return getMax(root, l, r);
}
private int getMax(Node n, int l, int r)
{
if(l<=n.s && r>=n.e)
return n.max;
if(l>n.e || r<n.s)
return Integer.MIN_VALUE;
return Math.max(getMax(n.left, l, r), getMax(n.right, l, r));
}
public int getMin(int l, int r)
{
return getMin(root, l, r);
}
private int getMin(Node n, int l, int r)
{
if(l<=n.s && r>=n.e)
return n.min;
if(l>n.e || r<n.s)
return Integer.MAX_VALUE;
return Math.min(getMin(n.left, l, r), getMin(n.right, l, r));
}
}
NOTE
If there is increase or decrease in the data then you have to reconstruct the tree. If there is frequent insertion/ deletion/ updation then this is not at all a good choice.
This is very useful when you have set of data and on which you need to frequently check the values for the particular range.
I have given the example of storing both minimum and maximum value. You may store sum of values or any thing else in your Node
Apologize for writing code in JAVA :)

Related

C# Radix Sort implementation in LinkedList

i have a task to make a radix sort algorithm for a linkedlist class, i have an object "Info", which has int Year and double Price, i need to sort linked list by Year using radix sorting.
class Info
{
public int Year { get; set; }
public double Price { get; set; }
public Info() { }
public Info(int y, double p)
{
Year = y;
Price = p;
}
}
class Node
{
public Info Data { get; set; }
public Node Next { get; set; }
public Node(Info data, Node adress)
{
Data = data;
Next = adress;
}
}
class LinkedList
{
private Node First;
private Node Last;
private Node Current;
public LinkedList()
{
First = null;
Last = null;
Current = null;
}
}
And i have taken radix sort algorithm for integer from this site. Problem is, i don't know how to modify it to work with my linked class.
static void Sort(int[] arr)
{
int temp = 0;
int i, j;
int[] tmp = new int[arr.Length];
for (int shift = 31; shift > -1; --shift)
{
j = 0;
for (i = 0; i < arr.Length; ++i)
{
bool move = (arr[i] << shift) >= 0;
if (shift == 0 ? !move : move)
arr[i - j] = arr[i];
else
tmp[j++] = arr[i];
}
Array.Copy(tmp, 0, arr, arr.Length - j, j);
}
}
How to make it work with my linked class ?
Based on that code, arr and tmp would need to be linked lists. One issue with this approach is that moving a node requires keeping track of the previous nodes in order to move a node. A dummy head node could be used to provide a node previous to the first data node, or special case handing when moving a node to the start of a list. An alternative would be using two pointers (references) to nodes of temp lists, one where bit == 0, one where bit == 1, and then concatenating the two temp lists into a single list. Note this approach takes 32 passes. If the radix sort were based on a byte instead of a bit, it could be reduced to 4 passes, but would need 256 pointers to nodes for 256 lists.

Get the path between two items in array

I am trying to write a function to get the path between two items in array
this array represent the connectivities between the items
like a tree with no cycles for example:
A=[1, 3, 0, 3, 2]
A[0]=1 // node 0 is connected to node 1
A[1]=3 // node 1 is connected to node 3
A[2]=0 //node 2 is connected to node 0
and so on,
So now this array generates a graph like this <4---2---0----1---3>
And this function should get the path between two given indecies in the array
if given 4 & 1 the output should be list of [2,0]
So I want to help how to start building the algorithm for this function?
I tried this code
private List<int> getDirectlyConnectedNodes(int ind, int[] A)
{
List<int> directNeighbours = new List<int>();
for (int i = 0; i < A.Length; i++)
{
if ((A[i] == ind || A[ind] == i) && ind != i)
{
directNeighbours.Add(i);
}
}
return directNeighbours;
}
private List<int> getPath(int ind1, int ind2, int[] A, List<int> path)
{
List<int> directNeighbours= getDirectlyConnectedNodes(ind1, A);
foreach (int i in directNeighbours)
{
path.Add(i);
if (A[i] == ind2 || A[ind2] == i)
{
return path;
}
else
{
getPath(i, ind2, A, path);
}
}
return path;
}
You can find paths to root from both nodes, drop common part and join paths.
public static List<int> GetPath(int a,int b,int[] array) {
Stack<int> stacka=GetPathToRoot(a,array);
Stack<int> stackb=GetPathToRoot(b,array);
int lastCommonNode=-1;
while(stacka.Count>0&&stackb.Count>0&&stacka.Peek()==stackb.Peek()) {
lastCommonNode=stacka.Pop();
stackb.Pop();
}
List<int> list=new List<int>();
while(stacka.Count>1) {
list.Add(stacka.Pop());
}
list.Reverse();
if(stacka.Count>0&&stackb.Count>0) {
list.Add(lastCommonNode);
}
while(stackb.Count>1) {
list.Add(stackb.Pop());
}
return list;
}
private static Stack<int> GetPathToRoot(int a,int[] array) {
Stack<int> stack=new Stack<int>();
for(;;) {
stack.Push(a);
if(array[a]==a) {
break;
}
a=array[a];
}
return stack;
}
Can't you just start with the first index and keep going until you hit the second index? There doesn't seem to be any branching in your data structure, just a fixed path from one node to the next.
private IEnumerable<int> getPath(int ind1, int ind2, int[] A)
{
for (int ind = ind1; A[ind] != ind && A[ind] != ind2; ind = A[ind])
{
yield return A[ind];
}
}
You might need to tweak it to cover the false positive you get if there is no path between the specified nodes, but when there is a path it should find it.

Printing a binary tree in order

I have a problem to convert a sorted array to a binary tree. I think that I have done it. Now I just want to print all items after conversion to double check it.
My question is that my printing part doesn't print all items. Something is wrong in the method 'inOrderTraversalHelper'.
class Program
{
// Given an array where elements are sorted in ascending order,
// convert it to a height balanced BST
static int[] arr = new int[8] {1,2,3,4,5,6,7,8};
static TreeNode node { get; set; }
static void Main(string[] args)
{
node = SortedArrayToBST(arr, 0, arr.Length-1);
inOrderTraversal();
}
static void inOrderTraversal()
{
inOrderTraversalHelper(node);
}
static void inOrderTraversalHelper(TreeNode r)
{
if (r != null)
{
**// UPDATED**
inOrderTraversalHelper(r.leftNode);
Console.Write("{0} ", r.data);
inOrderTraversalHelper(r.rightNode);
}
}
static TreeNode SortedArrayToBST(int[] a,int start,int end)
{
if (start > end) return null;
int mid = (start + end) / 2;
TreeNode node = new TreeNode(a[mid]);
node.leftNode= SortedArrayToBST(a, start, mid-1);
node.rightNode = SortedArrayToBST(a, mid + 1, end);
return node;
}
}
public class TreeNode
{
public int data;
public TreeNode leftNode;
public TreeNode rightNode;
public TreeNode(int data)
{
this.data = data;
}
}
It's because you are storing the value of the index mid not the value at the index of mid:
int mid = (start + end) / 2;
TreeNode node = new TreeNode(mid);
You are calculating the value of mid and then passing it in as the data. Instead mid should be the index of the value you want. For, example if you had a data set where the data was ordered but non sequential you'd get even stranger results:
{-1,22,33,44,55,66,77,100}
So your code should probably look up the value at index mid instead:
var mid = (int)((start + end) / 2.0);
var node = new TreeNode(arr[mid]);
In SortedArrayToBST, you work with the index mid, rather than with the element a[mid], change:
TreeNode node = new TreeNode(mid);
to:
TreeNode node = new TreeNode(a[mid]);
In the call to the SortedArrayToBST function, you need to pass array size - 1, since the end condition in inclusive, change:
node = SortedArrayToBST(arr, 0, arr.Length);
to:
node = SortedArrayToBST(arr, 0, arr.Length-1);
Also, your inOrderTraversalHelper function isn't actually in-order, but rather post-order.

C# fastest union of 2 sets of sorted values

What is the fastest way to union 2 sets of sorted values? Speed (big-O) is important here; not clarity - assume this is being done millions of times.
Assume you do not know the type or range of the values, but have an efficent IComparer<T> and/or IEqualityComparer<T>.
Given the following set of numbers:
var la = new int[] { 1, 2, 4, 5, 9 };
var ra = new int[] { 3, 4, 5, 6, 6, 7, 8 };
I am expecting 1, 2, 3, 4, 5, 6, 7, 8, 9. The following stub may be used to test the code:
static void Main(string[] args)
{
var la = new int[] { 1, 2, 4, 5, 9 };
var ra = new int[] { 3, 4, 5, 6, 6, 7, 8 };
foreach (var item in UnionSorted(la, ra, Int32Comparer.Default))
{
Console.Write("{0}, ", item);
}
Console.ReadLine();
}
class Int32Comparer : IComparer<Int32>
{
public static readonly Int32Comparer Default = new Int32Comparer();
public int Compare(int x, int y)
{
if (x < y)
return -1;
else if (x > y)
return 1;
else
return 0;
}
}
static IEnumerable<T> UnionSorted<T>(IEnumerable<T> sortedLeft, IEnumerable<T> sortedRight, IComparer<T> comparer)
{
}
The following method returns the correct results:
static IEnumerable<T> UnionSorted<T>(IEnumerable<T> sortedLeft, IEnumerable<T> sortedRight, IComparer<T> comparer)
{
var first = true;
var continueLeft = true;
var continueRight = true;
T left = default(T);
T right = default(T);
using (var el = sortedLeft.GetEnumerator())
using (var er = sortedRight.GetEnumerator())
{
// Loop until both enumeration are done.
while (continueLeft | continueRight)
{
// Only if both enumerations have values.
if (continueLeft & continueRight)
{
// Seed the enumeration.
if (first)
{
continueLeft = el.MoveNext();
if (continueLeft)
{
left = el.Current;
}
else
{
// left is empty, just dump the right enumerable
while (er.MoveNext())
yield return er.Current;
yield break;
}
continueRight = er.MoveNext();
if (continueRight)
{
right = er.Current;
}
else
{
// right is empty, just dump the left enumerable
if (continueLeft)
{
// there was a value when it was read earlier, let's return it before continuing
do
{
yield return el.Current;
}
while (el.MoveNext());
} // if continueLeft is false, then both enumerable are empty here.
yield break;
}
first = false;
}
// Compare them and decide which to return.
var comp = comparer.Compare(left, right);
if (comp < 0)
{
yield return left;
// We only advance left until they match.
continueLeft = el.MoveNext();
if (continueLeft)
left = el.Current;
}
else if (comp > 0)
{
yield return right;
continueRight = er.MoveNext();
if (continueRight)
right = er.Current;
}
else
{
// The both match, so advance both.
yield return left;
continueLeft = el.MoveNext();
if (continueLeft)
left = el.Current;
continueRight = er.MoveNext();
if (continueRight)
right = er.Current;
}
}
// One of the lists is done, don't advance it.
else if (continueLeft)
{
yield return left;
continueLeft = el.MoveNext();
if (continueLeft)
left = el.Current;
}
else if (continueRight)
{
yield return right;
continueRight = er.MoveNext();
if (continueRight)
right = er.Current;
}
}
}
}
The space is ~O(6) and time ~O(max(n,m)) (where m is the second set).
This will make your UnionSorted function a little less versatile, but you can make a small improvement by making an assumption about types. If you do the comparison inside the loop itself (rather than calling the Int32Comparer) then that'll save on some function call overhead.
So your UnionSorted declaration becomes this...
static IEnumerable<int> UnionSorted(IEnumerable<int> sortedLeft, IEnumerable<int> sortedRight)
And then you do this inside the loop, getting rid of the call to comparer.Compare()...
//var comp = comparer.Compare(left, right); // too slow
int comp = 0;
if (left < right)
comp = -1;
else if (left > right)
comp = 1;
In my testing this was about 15% faster.
I'm going to give LINQ the benefit of the doubt and say this is probably as fast as you are going to get without writing excessive code:
var result = la.Union(ra);
EDITED:
Thanks, I missed the sorted part.
You could do:
var result = la.Union(ra).OrderBy(i => i);
I would solve the problem this way. (I am making an assumption which lightens the difficulty of this problem significantly, only to illustrate the idea.)
Assumption: All numbers contained in sets are non-negative.
Create a word of at least n bits, where n is the largest value you expect. (If the largest value you expect is 12, then you must create a word of 16 bits.).
Iterate through both sets. For each value, val, or the val-th bit with 1.
Once done, count the amount of bits set to 1. Create an array of that size.
Go through each bit one by one, adding n to the new array if the n-th bit is set.

How to create a binary tree

I did'nt mean binary search tree.
for example,
if I insert values 1,2,3,4,5 in to a binary search tree the inorder traversal will give
1,2,3,4,5 as output.
but if I insert the same values in to a binary tree, the inorder traversal should give
4,2,5,1,3 as output.
Binary tree can be created using dynamic arrays in which for each element in index n,
2n+1 and 2n+2 represents its left and right childs respectively.
so representation and level order traversal is very easy here.
but I think, in-order,post-order,pre-order is difficult.
my question is how can we create a binary tree like a binary search tree.
ie.
have a tree class which contains data, left and right pointers instead of arrays.
so that we can recursively do traversal.
If I understand you correctly, you want to create a binary tree from an array
int[] values = new int[] {1, 2, 3, 4, 5};
BinaryTree tree = new BinaryTree(values);
this should prepopulate the binary tree with the values 1 - 5 as follows:
1
/ \
2 3
/ \
4 5
this can be done using the following class:
class BinaryTree
{
int value;
BinaryTree left;
BinaryTree right;
public BinaryTree(int[] values) : this(values, 0) {}
BinaryTree(int[] values, int index)
{
Load(this, values, index);
}
void Load(BinaryTree tree, int[] values, int index)
{
this.value = values[index];
if (index * 2 + 1 < values.Length)
{
this.left = new BinaryTree(values, index * 2 + 1);
}
if (index * 2 + 2 < values.Length)
{
this.right = new BinaryTree(values, index * 2 + 2);
}
}
}
Since I have not received any answers to the question which I asked, I will post my own implementaion of the binary tree using arrays.
now I know that array implementaion is easier than i thought ,but still i dont know how to implement the same using linked lists.
the code is in c#
class BinaryTree
{
private static int MAX_ELEM = 100; //initial size of the array
int lastElementIndex;
int?[] dataArray;
public BinaryTree()
{
dataArray = new int?[MAX_ELEM];
lastElementIndex = -1;
}
//function to insert data in to the tree
//insert as a complete binary tree
public void insertData(int data)
{
int?[] temp;
if (lastElementIndex + 1 < MAX_ELEM)
{
dataArray[++lastElementIndex] = data;
}
else
{ //double the size of the array on reaching the limit
temp = new int?[MAX_ELEM * 2];
for (int i = 0; i < MAX_ELEM; i++)
{
temp[i] = dataArray[i];
}
MAX_ELEM *= 2;
dataArray = temp;
dataArray[++lastElementIndex] = data;
}
}
//internal function used to get the left child of an element in the array
int getLeftChild(int index) {
if(lastElementIndex >= (2*index+1))
return (2*index + 1);
return -1;
}
//internal function used to get the right child of an element in the array
int getRightChild(int index) {
if(lastElementIndex >= (2*index+2))
return (2*index + 2);
return -1;
}
//function to check if the tree is empty
public bool isTreeEmpty() {
if (lastElementIndex == -1)
return true;
return false;
}
//recursive function for inorder traversal
public void traverseInOrder(int index) {
if (index == -1)
return;
traverseInOrder(getLeftChild(index));
Console.Write("{0} ", dataArray[index]);
traverseInOrder(getRightChild(index));
}
//recursive function for preorder traversal
public void traversePreOrder(int index) {
if (index == -1)
return;
Console.Write("{0} ", dataArray[index]);
traversePreOrder(getLeftChild(index));
traversePreOrder(getRightChild(index));
}
//recursive function for postorder traversal
public void traversePostOrder(int index) {
if (index == -1)
return;
traversePostOrder(getLeftChild(index));
traversePostOrder(getRightChild(index));
Console.Write("{0} ", dataArray[index]);
}
//function to traverse the tree in level order
public void traverseLevelOrder()
{
Console.WriteLine("\nPrinting Elements Of The Tree In Ascending Level Order\n");
if (lastElementIndex == -1)
{
Console.WriteLine("Empty Tree!...press any key to return");
Console.ReadKey();
return;
}
for (int i = 0; i <= lastElementIndex; i++)
{
Console.Write("{0} ", dataArray[i]);
}
Console.WriteLine("\n");
}
}
The tree class declaration part is, certainly, not the difficulty here. You basically stated exactly how to declare it, in the question:
class BinaryTree
{
private:
int data;
BinaryTree *left, *right;
};
This supports various forms of traversal, like so:
void Inorder(const BinaryTree *root)
{
if(root == 0)
return;
Inorder(root->left);
printf("now at %d\n", root->data);
Inorder(root->right);
}
You should be able to deduce pre- and post-order traversals from that. In a real implementation, the tree would probably be templated to store random data, the traversal routines would be more general (with a user-data input, or perhaps user-supplied per-node callback, or whatever), of course.
If you're after source for a comprehensive BinaryTree implementation you can learn from have a look at The C5 Generic Collection Library.
class BstNode
{
public int data;
public BstNode(int data)
{
this.data = data;
}
public BstNode left;
public BstNode right;
}
class Program
{
public static BstNode Insert(BstNode root, int data)
{
if (root == null) root = new BstNode(data);
else if (data <= root.data) root.left = Insert(root.left, data);
else if (data > root.data) root.right = Insert(root.right, data);
return root;
}
public static void Main(string[] args)
{
// create/insert into BST
BstNode Root = null;
Root = Insert(Root, 15);
Root = Insert(Root, 10);
Root = Insert(Root, 20);
Root = Insert(Root, 8);
Root = Insert(Root, 12);
Root = Insert(Root, 17);
Root = Insert(Root, 25);
}
}

Categories

Resources