The following programme returns whether a tree is balanced or not. A tree is said to be balanced if a path from the root to any leaf has the same length.
using System;
namespace BalancedTree
{
public class MainClass
{
static bool isBalanced(int[][] sons)
{
return isBalanced(sons, 0);
}
static bool isBalanced(int[][] sons, int startNode)
{
int[] children = sons[startNode];
int minHeight = int.MaxValue;
int maxHeight = int.MinValue;
bool allChildBalanced = true;
if(children.Length == 0)
return true;
else
{
foreach (int node in children)
{
int h = height(sons, node);
if(h > maxHeight)
maxHeight = h;
if(h < minHeight)
minHeight = h;
}
}
foreach (int node in children)
{
allChildBalanced = allChildBalanced && isBalanced(sons, node);
if(!allChildBalanced)
return false;
}
return Math.Abs(maxHeight - minHeight) < 2 && allChildBalanced;
}
static int height(int[][] sons, int startNode)
{
int maxHeight = 0;
foreach (int child in sons[startNode])
{
int thisHeight = height(sons, child);
if(thisHeight > maxHeight)
maxHeight = thisHeight;
}
return 1 + maxHeight;
}
public static void Main (string[] args)
{
int[][] sons = new int[6][];
sons[0] = new int[] { 1, 2, 4 };
sons[1] = new int[] { };
sons[2] = new int[] { 3, 5};
sons[3] = new int[] { };
sons[4] = new int[] { };
sons[5] = new int[] { };
Console.WriteLine (isBalanced(sons));
}
}
}
My problem is that my code is very inefficient, due to recursive calls to function
static int height(int[][] sons, int startNode)
making the time complexity exponential.
I know this can be optimised in case of a binary tree, but I'm looking for a way to optimise my programme in case of a general tree as described above.
One idea would be for instance to call function 'height' from the current node instead of startNode.
My only constraint is time complexity which must be linear, but I can use additional memory.
Sorry, but I have never done C#. So, there will be no example code.
However, it shouldn't be too hard for you to do it.
Defining isBalanced() recursively will never give best performance. The reason is simple: A tree can still be unbalanced, if all sub-trees are balanced. So, you can't just traverse the tree once.
However, your height() function already does the right thing. It visits every node in the tree only once to find the height (i.e. maximum length from the root to a leaf).
All you have to do is write a minDistance() function that finds the minimum length from the root to a leaf. You can do this using almost the same code.
With these functions a tree is balanced if and only if height(...)==minDistance(...).
Finally, you can merge both function into one that returns a (min,max) pair. This will not change time complexity but could bring down execution time a bit, if returning pairs is not too expensive in C#
Related
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.
Length = input Long(can be 2550, 2880, 2568, etc)
List<long> = {618, 350, 308, 300, 250, 232, 200, 128}
The program takes a long value, for that particular long value we have to find the possible combination from the above list which when added give me a input result(same value can be used twice). There can be a difference of +/- 30.
Largest numbers have to be used most.
Ex:Length = 868
For this combinations can be
Combination 1 = 618 + 250
Combination 2 = 308 + 232 + 200 +128
Correct Combination would be Combination 1
But there should also be different combinations.
public static void Main(string[] args)
{
//subtotal list
List<int> totals = new List<int>(new int[] { 618, 350, 308, 300, 250, 232, 200, 128 });
// get matches
List<int[]> results = KnapSack.MatchTotal(2682, totals);
// print results
foreach (var result in results)
{
Console.WriteLine(string.Join(",", result));
}
Console.WriteLine("Done.");
}
internal static List<int[]> MatchTotal(int theTotal, List<int> subTotals)
{
List<int[]> results = new List<int[]>();
while (subTotals.Contains(theTotal))
{
results.Add(new int[1] { theTotal });
subTotals.Remove(theTotal);
}
if (subTotals.Count == 0)
return results;
subTotals.Sort();
double mostNegativeNumber = subTotals[0];
if (mostNegativeNumber > 0)
mostNegativeNumber = 0;
if (mostNegativeNumber == 0)
subTotals.RemoveAll(d => d > theTotal);
for (int choose = 0; choose <= subTotals.Count; choose++)
{
IEnumerable<IEnumerable<int>> combos = Combination.Combinations(subTotals.AsEnumerable(), choose);
results.AddRange(from combo in combos where combo.Sum() == theTotal select combo.ToArray());
}
return results;
}
public static class Combination
{
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int choose)
{
return choose == 0 ?
new[] { new T[0] } :
elements.SelectMany((element, i) =>
elements.Skip(i + 1).Combinations(choose - 1).Select(combo => (new[] { element }).Concat(combo)));
}
}
I Have used the above code, can it be more simplified, Again here also i get unique values. A value can be used any number of times. But the largest number has to be given the most priority.
I have a validation to check whether the total of the sum is greater than the input value. The logic fails even there..
The algorithm you have shown assumes that the list is sorted in ascending order. If not, then you shall first have to sort the list in O(nlogn) time and then execute the algorithm.
Also, it assumes that you are only considering combinations of pairs and you exit on the first match.
If you want to find all combinations, then instead of "break", just output the combination and increment startIndex or decrement endIndex.
Moreover, you should check for ranges (targetSum - 30 to targetSum + 30) rather than just the exact value because the problem says that a margin of error is allowed.
This is the best solution according to me because its complexity is O(nlogn + n) including the sorting.
V4 - Recursive Method, using Stack structure instead of stack frames on thread
It works (tested in VS), but there could be some bugs remaining.
static int Threshold = 30;
private static Stack<long> RecursiveMethod(long target)
{
Stack<long> Combination = new Stack<long>(establishedValues.Count); //Can grow bigger, as big as (target / min(establishedValues)) values
Stack<int> Index = new Stack<int>(establishedValues.Count); //Can grow bigger
int lowerBound = 0;
int dimensionIndex = lowerBound;
long fail = -1 * Threshold;
while (true)
{
long thisVal = establishedValues[dimensionIndex];
dimensionIndex++;
long afterApplied = target - thisVal;
if (afterApplied < fail)
lowerBound = dimensionIndex;
else
{
target = afterApplied;
Combination.Push(thisVal);
if (target <= Threshold)
return Combination;
Index.Push(dimensionIndex);
dimensionIndex = lowerBound;
}
if (dimensionIndex >= establishedValues.Count)
{
if (Index.Count == 0)
return null; //No possible combinations
dimensionIndex = Index.Pop();
lowerBound = dimensionIndex;
target += Combination.Pop();
}
}
}
Maybe V3 - Suggestion for Ordered solution trying every combination
Although this isn't chosen as the answer for the related question, I believe this is a good approach - https://stackoverflow.com/a/17258033/887092(, otherwise you could try the chosen answer (although the output for that is only 2 items in set being summed, rather than up to n items)) - it will enumerate every option including multiples of the same value. V2 works but would be slightly less efficient than an ordered solution, as the same failing-attempt will likely be attempted multiple times.
V2 - Random Selection - Will be able to reuse the same number twice
I'm a fan of using random for "intelligence", allowing the computer to brute force the solution. It's also easy to distribute - as there is no state dependence between two threads trying at the same time for example.
static int Threshold = 30;
public static List<long> RandomMethod(long Target)
{
List<long> Combinations = new List<long>();
Random rnd = new Random();
//Assuming establishedValues is sorted
int LowerBound = 0;
long runningSum = Target;
while (true)
{
int newLowerBound = FindLowerBound(LowerBound, runningSum);
if (newLowerBound == -1)
{
//No more beneficial values to work with, reset
runningSum = Target;
Combinations.Clear();
LowerBound = 0;
continue;
}
LowerBound = newLowerBound;
int rIndex = rnd.Next(LowerBound, establishedValues.Count);
long val = establishedValues[rIndex];
runningSum -= val;
Combinations.Add(val);
if (Math.Abs(runningSum) <= 30)
return Combinations;
}
}
static int FindLowerBound(int currentLowerBound, long runningSum)
{
//Adjust lower bound, so we're not randomly trying a number that's too high
for (int i = currentLowerBound; i < establishedValues.Count; i++)
{
//Factor in the threshold, because an end aggregate which exceeds by 20 is better than underperforming by 21.
if ((establishedValues[i] - Threshold) < runningSum)
{
return i;
}
}
return -1;
}
V1 - Ordered selection - Will not be able to reuse the same number twice
Add this very handy extension function (uses a binary algorithm to find all combinations):
//Make sure you put this in a static class inside System namespace
public static IEnumerable<List<T>> EachCombination<T>(this List<T> allValues)
{
var collection = new List<List<T>>();
for (int counter = 0; counter < (1 << allValues.Count); ++counter)
{
List<T> combination = new List<T>();
for (int i = 0; i < allValues.Count; ++i)
{
if ((counter & (1 << i)) == 0)
combination.Add(allValues[i]);
}
if (combination.Count == 0)
continue;
yield return combination;
}
}
Use the function
static List<long> establishedValues = new List<long>() {618, 350, 308, 300, 250, 232, 200, 128, 180, 118, 155};
//Return is a list of the values which sum to equal the target. Null if not found.
List<long> FindFirstCombination(long target)
{
foreach (var combination in establishedValues.EachCombination())
{
//if (combination.Sum() == target)
if (Math.Abs(combination.Sum() - target) <= 30) //Plus or minus tolerance for difference
return combination;
}
return null; //Or you could throw an exception
}
Test the solution
var target = 858;
var result = FindFirstCombination(target);
bool success = (result != null && result.Sum() == target);
//TODO: for loop with random selection of numbers from the establishedValues, Sum and test through FindFirstCombination
I have implemented skip list for integers. When testing method insert, I insert natural numbers from 1 to 1000000 in a for loop with counter j. I am using stopwatch also.
Appendix: in the real program, values are doubles, because I use sentinels with values
double.PositiveInfinity in double.NegativeInfinity. (but that shouldn't be the problem)
Pseudocode:
MyList = new SkipList();
stopwatch.start();
t1 = stopwatch.Elapsed.TotalMilliseconds;
for(int j = 0; j<1000000; j++){
steps = MyList.insert(j);
if(j%500==0){
t2= stopwatch.Elapsed.TotalMilliseconds -t1;
write j,t2 in a file1;
write j,steps in a file2;
t1 = t2;
}
}
When I make a graph time/number of nodes, it is linear, but graph steps/nodes is logarithmic as expected. (steps is number of loop-cycles (~operations) in the method insert).
Method insert creates extra nodes and set some poiters. Nodes are implemented in the following way:
class Node
{
public Node right;//his right neighbour - maybe "null"
public Node down;//his bottom neighbour -maybe null
public int? value;//value
public int depth;//level where node is present: 0, 1, 2 ...
public Node(int i,Node rightt,Node downn,int depthh) {
//constructor for node with two neighbours.
value = i;
right = rightt;
down = downn;
depth = depthh;
}
//there are some other contructors (for null Node etc.)
}
class SkipList
{
public Node end;//upper right node
public Node start;//upper left node
public int depth;//depth of SkipList
//there are left (-inf) and right sentinels (inf) in the SkipList.
}
Skip list is made of nodes.
Insert is defined in the class SkipList and works in the following way:
public int Insert(int value2, int depth2)
{
//returns number of steps
//depth2 is calculated like (int)(-Math.Log(0<=random double<1 ,2))
//and works as expected - probability P(depth = k) = Math.Pow(0.5,k)
//lsit of nodes, which will get a new right neighbour
List<Node> list = new List<Node>();
Node nod = start;
int steps = 0;
while (true) {
if (nod.right.value >= value2)
{
//must be added to our list
lsit.Add(nod);
if (nod.down != null)
nod = nod.down;
else
break;
}
else {
nod = nod.right;
}
steps++;
}
//depth (of skipList) is maybe < depth2, so we must create
//k = 2*(depth2-depth) new edge nodes and fix right pointers of left sentinels
List<Node> newnodes = new List<Node>();
for (int jj = 0; jj < depth2 - depth;jj++ )
{
steps++;
//new sentinels
Node end2 = new Node(double.PositiveInfinity, end,depth+jj+1);
Node start2 = new Vozlisce(double.NegativeInfinity, end2,
start,depth+jj+1);
start = start2;
end = end2;
newnodes.Add(start2);
}
//fix right pointers of nodes in the List list (from the beginning)
Node x = new Node(value,list[list.Count-1].right,0);
list[list.Count-1].right=x;
int j =1;
while(j<=Math.Min(depth2,depth)){
steps++;
//create new nodes with value value
x = new Node(value,lsit[list.Count -(j+1)].right,x,j);
list[list.Count-(j+1)].right = x;
j++;
}
//if there are some new edge sentinels, we must fix their right neighbours
// add the last depth2-depth nodes
for(int tj=0;tj<depth2-depth;tj++){
steps++;
x = new Node(value,newnodes[tj].right,x,depth+tj+1);
newnodes[tj].right = x;
}
depth = Math.Max(depth, depth2);
return steps;
}
I've implemented also a version of skip list where nodes are blocks and have n = node.depth
right neighbours, stored in array, but the graph time/num. of nodes is still linear (and steps/num. of nodes is logarithmic).
^ is "xor";
10 : 1010
6 : 0110
---------
^ : 1100 = 12
If you loop from 0 to 11, then yes - it'll appear pretty linear - you won't notice any degradation over that size. You probably want Math.Pow rather than ^, but it would be simpler to hard-code 1000000.
I was trying out an iterative method to find the height/depth of a binary search tree.
Basically, I tried using Breadth First Search to calculate the depth, by using a Queue to store the tree nodes and using just an integer to hold the current depth of the tree. Each node in the tree is queued, and it is checked for child nodes. If child nodes are present, then the depth variable is incremented. Here is the code:
public void calcDepthIterative() {
Queue<TreeNode> nodeQ = new LinkedList<TreeNode>();
TreeNode node = root;
int level = 0;
boolean flag = false;
nodeQ.add(node);
while(!nodeQ.isEmpty()) {
node = nodeQ.remove();
flag = false;
if(node.leftChild != null) {
nodeQ.add(node.leftChild);
flag = true;
}
if(node.rightChild != null) {
nodeQ.add(node.rightChild);
flag = true;
}
if(flag) level++;
}
System.out.println(level);
}
However, the code doesn't work for all cases. For example, for the following tree:
10
/ \
4 18
\ / \
5 17 19
It shows the depth as 3, instead of 2.
I did an alternate version of it using an additional Queue to store the current depths, using the idea in this page. I wanted to avoid using an additional queue so I tried to optimize it. Here is the code which works, albeit using an additional Queue.
public void calcDepthIterativeQueue() {
Queue<TreeNode> nodeQ = new LinkedList<TreeNode>();
Queue<Integer> lenQ = new LinkedList<Integer>();
TreeNode node = root;
nodeQ.add(node);
lenQ.add(0);
int maxLen = 0;
while(!nodeQ.isEmpty()) {
TreeNode curr = nodeQ.remove();
int currLen = lenQ.remove();
if(curr.leftChild != null) {
nodeQ.add(curr.leftChild);
lenQ.add(currLen + 1);
}
if(curr.rightChild != null) {
nodeQ.add(curr.rightChild);
lenQ.add(currLen + 1);
}
maxLen = currLen > maxLen ? currLen : maxLen;
}
System.out.println(maxLen);
}
QUESTION:
Is there a way to fix the first method such that it returns the right depth?
EDIT
SEE ACCEPTED ANSWER BELOW
Java code for rici's answer:
public void calcDepthIterative() {
Queue<TreeNode> nodeQ = new LinkedList<TreeNode>();
int depth = 0;
nodeQ.add(root);
while(!nodeQ.isEmpty()) {
int nodeCount = nodeQ.size();
if(nodeCount == 0)
break;
depth++;
while(nodeCount > 0) {
TreeNode topNode = nodeQ.remove();
if(topNode.leftChild != null)
nodeQ.add(topNode.leftChild);
if(topNode.rightChild != null)
nodeQ.add(topNode.rightChild);
nodeCount--;
}
}
System.out.println(depth);
}
Here's one way of doing it:
Create a Queue, and push the root onto it.
Let Depth = 0
Loop:
Let NodeCount = size(Queue)
If NodeCount is 0:
return Depth.
Increment Depth.
While NodeCount > 0:
Remove the node at the front of the queue.
Push its children, if any, on the back of the queue
Decrement NodeCount.
How it works
Every time NodeCount is set, the scan is just about to start a new row. NodeCount is set to the number of Nodes in that row. When all of those Nodes have been removed (i.e., NodeCount is decremented to zero), then the row has been completed and all the children of nodes on that row have been added to the queue, so the queue once again has a complete row, and NodeCount is again set to the number of Nodes in that row.
public int height(Node root){
int ht =0;
if(root==null) return ht;
Queue<Node> q = new ArrayDeque<Node>();
q.addLast(root);
while(true){
int nodeCount = q.size();
if(nodeCount==0) return ht;
ht++;
while(nodeCount>0){
Node node = q.pop();
if(node.left!=null) q.addLast(node.left);
if(node.right!=null) q.addLast(node.right);
nodeCount--;
}
}
How about recurtion,
int Depth(Node node)
{
int depthR=0,depthL=0;
if(Right!=null)depthR=Depth(Right);
if(Left!=null)depthL=Depth(Left);
return Max(depthR,depthL)+1;
}
If tou want a zero based depth, just subtract the resulting depth by 1.
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);
}
}