We got an assignment where we need to code:
I think you should do it this manner (code is in C#, but shouldn't be very hard to convert it to Java):
//list should be sorted
public void myFunc(List<int> list){
Queue<List<int>> queue = new Queue<List<int>>();
queue.Enqueue(list);
while(queue.Any()){
List<int> l = queue.Dequeue();
int rindex = findRoot(l);
//print r or store it somewhere
Console.WriteLine(l.ElementAt(rindex));
List<int> leftlist = l.GetRange(0, rindex);
List<int> rightlist = l.GetRange(rindex + 1, l.Count-rindex-1);
//leftlist = list l from index 0 to r-1; rightlist = list l from index r+1 to end.
if (leftlist.Any())
{
queue.Enqueue(leftlist);
}
if (rightlist.Any())
{
queue.Enqueue(rightlist);
}
}
}
******EDIT: *********************************************
For finding the root every time you have a list of size n, do the following:
public int findRoot(List<int> list)
{
int n = list.Count;
double h = Math.Ceiling(Math.Log(n + 1, 2)) - 1;
double totNodesInCompleteBinaryTreeOfHeighthMinusOne = Math.Pow(2, h) - 1;
double nodesOnLastLevel = n - totNodesInCompleteBinaryTreeOfHeighthMinusOne;
double nodesOnLastLevelInRightSubtree = 0;
if (nodesOnLastLevel > Math.Pow(2, h - 1))
{
nodesOnLastLevelInRightSubtree = nodesOnLastLevel - Math.Pow(2, h - 1);
}
int rindex = (int)(n - nodesOnLastLevelInRightSubtree - 1 - ((totNodesInCompleteBinaryTreeOfHeighthMinusOne - 1) / 2));
return rindex;
}
The complete BST part took a bit of time to sort out what that actually is. Your requirement also calls for order level insert. I can't say this does "inserts", but it builds the BST in order level.
The input List must be sorted first.
The building in order level is accomplished by taking the root and adding it to the BST, then splitting what is left into left and right lists, adding them into a list of lists, then processing the list of lists. Each round of splitting and adding to a list of lists is a level of insertion.
The complete part is more difficult, as was noticed. The way to handle that is to compute the root for the list differently than a normal balanced tree. In a normal balanced tree the root index is at length/2. For the BST to be complete the root index has to be offset so that nodes that would normally appear on the right side of the root instead appear on the left side of the root. As long as the computation works for any length list then each split sublist is built properly.
From what I can tell computing the offset done by incrementing the offset for each additional element in length until you get to 1/2 of the width of a level. So, a BST with height of 4 has 8 elements in the lowest level. Lists of size 8, 9, 10, … 15 create BST with height of 4. For those lists the root index into the list is then 4, 5, 6, 7, 7, 7, 7, 7.
Seems to work.
public class Node<T extends Comparable<T>> {
protected Node<T> left;
protected Node<T> right;
protected T data;
}
public class BTree<T extends Comparable<T>> {
private Node<T> root = new Node<>();
public void addData(T data) {
Node<T> parent = root;
while (parent.data != null ) {
if ( data.compareTo( parent.data ) > 0 ) {
if ( parent.right == null )
parent.right = new Node<>();
parent = parent.right;
} else {
if ( parent.left == null )
parent.left = new Node<>();
parent = parent.left;
}
}
parent.data = data;
}
}
private void run() {
for ( int i = 2; i < 65; ++i ) {
List<Integer> intList = IntStream.range(1, i).boxed().collect(Collectors.toList());
BTree<Integer> bTree = new BTree<>();
List<List<Integer>> splitLists = new ArrayList<>();
splitLists.add(intList);
while (splitLists.size() > 0 ) {
List<List<Integer>> tSplitLists = new ArrayList<>();
for ( List<Integer> tIntList: splitLists) {
int length = tIntList.size();
// compute starting point
int mid = calcMid(length); // length/2 ; //+ calcOffset(length);
bTree.addData(tIntList.get(mid));
if ( mid - 0 > 0)
tSplitLists.add(tIntList.subList(0, mid));
if ( length - (mid+1) > 0)
tSplitLists.add(tIntList.subList(mid+1, length));
}
splitLists = tSplitLists;
}
bTree.printNode();
}
}
private int calcMid(int length) {
if ( length <= 4 )
return length / 2;
int levelSize = 1;
int total = 1;
while ( total < length ) {
levelSize *= 2;
total += levelSize;
}
int excess = length - (total - levelSize);
int minMid = (total - levelSize + 1) / 2;
if ( excess <= levelSize / 2 ) {
return minMid + (excess - 1);
} else {
int midExcess = levelSize/2;
return minMid + (midExcess - 1);
}
}
See How to print binary tree diagram? for code on printing a binary tree.
PS> I'm sure you can make it a bit better by clearing and copying Lists instead of making new ones each time.
EDIT: Did you go and get the printNode
code referenced above?
1
2
/
1
2
/ \
1 3
3
/ \
/ \
2 4
/
1
And so on …