Swapping Nodes in pairs - java

I am trying to solve the following leetcode problem :
Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modifying the values in the list's nodes (i.e., only nodes themselves may be changed.)
For example: Input: head = [1,2,3,4]
Output: [2,1,4,3]
I am a newbie to linked lists and have written following code for the above problem:
public void swapPairs() {
if(head == null || head.next == null) {
return;
}
Node prev = head;
Node firstNode = head;
Node secondNode = head.next;
while(secondNode != null) {
Node nxt = secondNode.next;
prev.next = secondNode;
firstNode.next = nxt;
secondNode.next= firstNode;
if(nxt == null) {
break;
}
prev = firstNode;
firstNode = nxt;
secondNode = firstNode.next;
}
}
The output above code returning is [1, 4, 3]. I am unable to understand why 2 is not there in the list at the beginning.

Your code will perform the pairwise swaps correctly, but the head reference is never updated, yet it is clear that after this pairwise swapping the head should now be what was the second node in the original ordering.
So add this line, just before the loop:
head = head.next;
A visualisation may help. Let's take the example of input list 1,2,3,4:
head
↓
┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐
│ data: 1 │ │ data: 2 │ │ data: 3 │ │ data: 4 │
│ next: ──────► │ next: ──────► │ next: ──────► │ next: null│
│ │ │ │ │ │ │ │
└───────────┘ └───────────┘ └───────────┘ └───────────┘
Once the next references have been updated with your code, we get this:
head
↓
┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐
│ data: 1 │ │ data: 2 │ │ data: 3 │ │ data: 4 │
│ next: ┐ │ │ next: ┐ │ │ next: null│ │ next: ┐ │
│ │ │◄──────────┘ │ │ │◄──────────┘ │
└───────│───┘ └───────────┘ └───────────┘ ┌►└───────────┘
└─────────────────────────────────────┘
The nodes have been rewired as expected. If we start at the second node and follow the arrows (the next references), we see the nodes are chained in the desired order. But, because head still references the node with value 1, we will not see the node with value 2 anymore, as it is now ordered before that node.
Before the rewiring process starts we should therefore make the head reference the node with value 2.

Related

Understanding insertion sort for doubly linked list

So I understand how insertion sort works but trying to apply the concept to doubly linked lists fizzles out my brain. Can someone please explain how the algorithm works in this context? I cannot wrap my head around how the node pointers change after each node-by-node comparison, given a pre-existing linked list. I am currently working in Java and referring to this code-example: https://www.geeksforgeeks.org/insertion-sort-doubly-linked-list/
Below are two functions, sortedInsert and insertionSort, where the former is helper function.
What is the else clause doing in sortedInsert? Also why does the author "removing all links so as to create current" in the insertionSort function?
// function to insert a new node in sorted way in
// a sorted doubly linked list
static Node sortedInsert(Node head_ref, Node newNode)
{
Node current;
// if list is empty
if (head_ref == null)
head_ref = newNode;
// if the node is to be inserted at the beginning
// of the doubly linked list
else if ((head_ref).data >= newNode.data)
{
newNode.next = head_ref;
newNode.next.prev = newNode;
head_ref = newNode;
}
else
{
current = head_ref;
// locate the node after which the new node
// is to be inserted
while (current.next != null &&
current.next.data < newNode.data)
current = current.next;
//Make the appropriate links /
newNode.next = current.next;
// if the new node is not inserted
// at the end of the list
if (current.next != null)
newNode.next.prev = newNode;
current.next = newNode;
newNode.prev = current;
}
return head_ref;
}
// function to sort a doubly linked list using insertion sort
static Node insertionSort(Node head_ref)
{
// Initialize 'sorted' - a sorted doubly linked list
Node sorted = null;
// Traverse the given doubly linked list and
// insert every node to 'sorted'
Node current = head_ref;
while (current != null)
{
// Store next for next iteration
Node next = current.next;
// removing all the links so as to create 'current'
// as a new node for insertion
current.prev = current.next = null;
// insert current in 'sorted' doubly linked list
sorted=sortedInsert(sorted, current);
// Update current
current = next;
}
// Update head_ref to point to sorted doubly linked list
head_ref = sorted;
return head_ref;
}
What is the else clause doing in sortedInsert?
The first two blocks (before the else) deal with two boundary cases:
What to do when the list is empty
What to do if the new node must be inserted before the first node of the list.
So the else block is dealing with all other cases, i.e. where the new node will not be the new head of the list, but the current head node will remain what it was.
It first finds a node (current) for which the next one holds a value that should come after the new node's value (or alternatively, it has no next node following it). By consequence (and because of the previous boundary case), we then know that the current node's value should come before the new node's value. So if we find such a current, we know that the new node must be inserted between current and current.next.
In short, the while loop finds the spot where to insert newNode. This is a typical phase in any insertion-sort algorithm.
The section that is commented "make the appropriate links" will then make up to 4 rewiring assignments.
Here is an example. Let's say the linked list has 3 values 10, 20 and 30 at the moment sortedInsert is called with a new node that has value 25:
head_ref
↓
┌───────────┐ ┌───────────┐ ┌───────────┐
│data: 10 │ │data: 20 │ │data: 30 │
│next: ────────> │next: ────────> │next: null │
│prev: null │ │prev: ─┐ │ │prev: ─┐ │
└───────────┘ └───────│───┘ └───────│───┘
^ │ ^ │
└─────────────┘ └─────────────┘
┌───────────┐
│data: 25 │
│next: null │
│prev: null │
└───────────┘
↑
newNode
Because head_ref is not null and head_ref.data < newNode.data, we get in the else block where current is defined. The while loop will iterate once, and make the current reference stop at this point:
head_ref current
↓ ↓
┌───────────┐ ┌───────────┐ ┌───────────┐
│data: 10 │ │data: 20 │ │data: 30 │
│next: ────────> │next: ────────> │next: null │
│prev: null │ │prev: ─┐ │ │prev: ─┐ │
└───────────┘ └───────│───┘ └───────│───┘
^ │ ^ │
└─────────────┘ └─────────────┘
Now current.next.data >= newNode.data and so we have found the insertion point for newNode.
The first rewiring is done with newNode.next = current.next, which results in this:
head_ref current
↓ ↓
┌───────────┐ ┌───────────┐ ┌───────────┐
│data: 10 │ │data: 20 │ │data: 30 │
│next: ────────> │next: ────────> │next: null │
│prev: null │ │prev: ─┐ │ │prev: ─┐ │
└───────────┘ └───────│───┘ └───────│───┘
^ │ ^ │ ^
└─────────────┘ └─────────────┘ │
│
┌───────────┐ │
│data: 25 │ │
│next: ────────────┘
│prev: null │
└───────────┘
↑
newNode
The next rewiring only happens when current is not the tail node: newNode.next.prev = newNode, which is our case:
head_ref current
↓ ↓
┌───────────┐ ┌───────────┐ ┌───────────┐
│data: 10 │ │data: 20 │ │data: 30 │
│next: ────────> │next: ────────> │next: null │
│prev: null │ │prev: ─┐ │ │prev: ─┐ │
└───────────┘ └───────│───┘ └───────│───┘
^ │ │ ^
└─────────────┘ │ │
│ │
┌───────────┐ │ │
│data: 25 │ <──┘ │
│next: ────────────┘
│prev: null │
└───────────┘
↑
newNode
At this stage, the new node is correctly linked with the node that should follow it (the one with value 30). Now remain two more assignments to establish the link between the node that should precede the new node (the one with value 20). First assignment is current.next = newNode, which results in:
head_ref current
↓ ↓
┌───────────┐ ┌───────────┐ ┌───────────┐
│data: 10 │ │data: 20 │ │data: 30 │
│next: ────────> │next: ────────┐ │next: null │
│prev: null │ │prev: ─┐ │ │ │prev: ─┐ │
└───────────┘ └───────│───┘ │ └───────│───┘
^ │ │ │ ^
└─────────────┘ │ │ │
v │ │
┌───────────┐ │ │
│data: 25 │ <─┘ │
│next: ───────────┘
│prev: null │
└───────────┘
↑
newNode
And finally the rewiring is completed with newNode.prev = current:
head_ref current
↓ ↓
┌───────────┐ ┌───────────┐ ┌───────────┐
│data: 10 │ │data: 20 │ │data: 30 │
│next: ────────> │next: ────────┐ │next: null │
│prev: null │ │prev: ─┐ │ │ │prev: ─┐ │
└───────────┘ └───────│───┘ │ └───────│───┘
^ │ ^ │ │ ^
└─────────────┘ │ │ │ │
│ v │ │
│ ┌───────────┐ │ │
│ │data: 25 │ <─┘ │
│ │next: ───────────┘
│ │prev: ─┐ │
│ └───────│───┘
└─────────┘
↑
newNode
This is no different then:
head_ref current newNode
↓ ↓ ↓
┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐
│data: 10 │ │data: 20 │ │data: 25 │ │data: 30 │
│next: ────────> │next: ────────> │next: ────────> │next: null │
│prev: null │ │prev: ─┐ │ │prev: ─┐ │ │prev: ─┐ │
└───────────┘ └───────│───┘ └───────│───┘ └───────│───┘
^ │ ^ │ ^ │
└─────────────┘ └─────────────┘ └─────────────┘
The caller gets back the head reference head_ref, which actually didn't change. It would only change if the new node became the first node in the list, which is what the first two if blocks deal with.
Also why does the author "removing all links so as to create current" in the insertionSort function?
This is just a clean way to extract the node from the input list: it is no longer a part of it, and is ready to become part of the new list (sorted). Technically this is not necessary for the case described above, since there both the prev and next members of newNode get new references assigned anyway, but it remains important for the first two boundary cases, as there we do not assign null values where they are actually needed.
Alternatively, you could assign those null references in sortedInsert.
Hope this clarifies it.

When using Java Arrays.fill(array,int[] subArray), why subArray share the same memory block?

int[][] dp = new int[5][2];
Arrays.fill(dp,new int[]{2,3});
dp[1][0] = 10;
I thought that only dp[1][0] is changed to 10, but all dp[x][0] are 10(x is from 0 to 4).
I have found a comment related to my problem, "This line makes every row refer to the same memory block, i.e. changing arr[1][5] will also change arr[100][5]."
So why these array objects share the same memory? Are they all in the JVM heap or constant pool?
Related link: https://stackoverflow.com/a/19199560/13724489
You would think that Array.fill(dp, new int[2]{2,3}) is equivalent to:
dp[0] = new int[2]{2,3};
dp[1] = new int[2]{2,3};
dp[2] = new int[2]{2,3};
dp[3] = new int[2]{2,3};
dp[4] = new int[2]{2,3};
But no, it's more like:
int[] val = new int[2]{2,3};
dp[0] = val;
dp[1] = val;
dp[2] = val;
dp[3] = val;
dp[4] = val;
You are only ever creating one array in the line Array.fill(dp, new int[2]{2,3}). All subarrays in dp refer to that single array that you created. dp[0] and dp[1] and dp[whatever] all refer to the same array.
This is because when you call a method, all the arguments get evaluated, before the method is run, so new int[2]{2,3} is evaluated before fill is called. fill doesn't "run" the expression new int[2]{2,3} in a loop and assign it to the array. fill doesn't even know what expression you used! Rather, fill only knows the value that the expression new int[2]{2,3} evaluated to - a reference to one newly created int array object. fill then assigns that same object to each index of dp.
When you run int[][] dp = new int[5][2];, you get an outer array of length 5, and 5 inner arrays of length 2. All 5 inner arrays are filled with 0 values.
dp →→→┌───┐ ┌───┬───┐
│ •→│→→→│ 0 │ 0 │
├───┤ └───┴───┘ ┌───┬───┐
│ •→│→→→→→→→→→→→→→│ 0 │ 0 │
├───┤ ┌───┬───┐ └───┴───┘
│ •→│→→→│ 0 │ 0 │
├───┤ └───┴───┘ ┌───┬───┐
│ •→│→→→→→→→→→→→→→│ 0 │ 0 │
├───┤ ┌───┬───┐ └───┴───┘
│ •→│→→→│ 0 │ 0 │
└───┘ └───┴───┘
When you then run Arrays.fill(dp,new int[2]{2,3});, you create a new array of length 2 with values 2 and 3, then fill all 5 positions of the outer array with a reference to that new array. The 5 previous inner arrays are discarded:
dp →→→┌───┐ ┌───┬───┐
│ •→│→→→→→↓ │ 0 │ 0 │
├───┤ ↓ └───┴───┘ ┌───┬───┐
│ •→│→→→↓ ↓ │ 0 │ 0 │
├───┤ ┌───┬───┐ ┌───┬───┐ └───┴───┘
│ •→│→→→│ 2 │ 3 │ │ 0 │ 0 │
├───┤ └───┴───┘ └───┴───┘ ┌───┬───┐
│ •→│→→→↑ ↑ │ 0 │ 0 │
├───┤ ↑ ┌───┬───┐ └───┴───┘
│ •→│→→→→→↑ │ 0 │ 0 │
└───┘ └───┴───┘
Which of course means that dp[1][0] and dp[4][0] both refer to the same array position, i.e. the position holding the 2 value.
It’s true what they say:
int[][] dp = new int[5][2];
Arrays.fill(dp, new int[] { 2, 3 });
dp[1][0] = 10;
System.out.println(Arrays.deepToString(dp));
Output:
[[10, 3], [10, 3], [10, 3], [10, 3], [10, 3]]
In the code you are only instantiating one int[] (one one-dimentional array of ints). You are doing new int[] { 2, 3 }) only once. So you have only one inner array. The fill method fills a reference to this same array into every slot of the outer array. This is what happens.
Two other points
As Holger said in the comment, when we are constructing the inner array/s afterward, also constructing them in the declaration is a waste. Leave out the inner dimension to construct only the outer array first:
int[][] dp = new int[5][]; // No number in the second set of square brackets
As an aside you’ve got an error in this line of your code:
Arrays.fill(dp,new int[2]{2,3});
You are not allowed to give both an array dimension (length) and contents. In my Eclipse I get Cannot define dimension expressions when an array initializer is provided. So leave out the 2 in the square brackets as I am doing above.
If you wanted five separate inner arrays, you may use the setAll method:
Arrays.setAll(dp, index -> new int[] { 2, 3 });
Now the output will be:
[[2, 3], [10, 3], [2, 3], [2, 3], [2, 3]]
What happens now is that setAll calls new int[] { 2, 3 } for every index of the outer array, so five inner arrays are created.

Why Hashmap.values().parallelStream() does not run in parallel while wrap them in ArrayList could work?

The hashmap has two key and value pairs, they are not processed in parallel by different threads.
import java.util.stream.Stream;
import java.util.Map;
import java.util.HashMap;
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.values().parallelStream()
.peek(x -> System.out.println("processing "+x+" in "+Thread.currentThread()))
.forEach(System.out::println);
}
}
Output:
processing 1 in Thread[main,5,main]
1
processing 2 in Thread[main,5,main]
2
URL: https://ideone.com/Hkxkoz
The ValueSpliterator should have tried to split the arrays of HashMap into slot of size 1, which means two elements should be processed in different threads.
Source: https://www.codota.com/code/java/methods/java8.util.HMSpliterators$ValueSpliterator/%3Cinit%3E
After wrapped them in ArrayList, it works as expected.
new ArrayList(map.values()).parallelStream()
.peek(x -> System.out.println("processing "+x+" in "+Thread.currentThread()))
.forEach(System.out::println);
output:
processing 1 in Thread[ForkJoinPool.commonPool-worker-3,5,main]
1
processing 2 in Thread[main,5,main]
2
As explained in this answer, the issue is connected with the fact that the HashMap has a capacity potentially larger than its size and the actual values are distributed over the backing array based on their hash codes.
The splitting logic is basically the same for all array based spliterators, whether you stream over an array, an ArrayList, or a HashMap. To get balanced splits on a best-effort basis, each split will half the (index) range, but in case of HashMap, the number of actual elements within the range differs from the range size.
In principle, every range based spliterator can split down to single elements, however, the client code, i.e. the Stream API implementation, might not split so far. The decision for even attempting to split is driven by the expected number of elements and number of CPU cores.
Taking the following program
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
for(int depth: new int[] { 1, 2, Integer.MAX_VALUE }) {
System.out.println("With max depth: "+depth);
Tree<Spliterator<Map.Entry<String, Integer>>> spTree
= split(map.entrySet().spliterator(), depth);
Tree<String> valueTree = spTree.map(sp -> "estimated: "+sp.estimateSize()+" "
+StreamSupport.stream(sp, false).collect(Collectors.toList()));
System.out.println(valueTree);
}
}
private static <T> Tree<Spliterator<T>> split(Spliterator<T> sp, int depth) {
Spliterator<T> prefix = depth-- > 0? sp.trySplit(): null;
return prefix == null?
new Tree<>(sp): new Tree<>(null, split(prefix, depth), split(sp, depth));
}
public static class Tree<T> {
final T value;
List<Tree<T>> children;
public Tree(T value) {
this.value = value;
children = Collections.emptyList();
}
public Tree(T value, Tree<T>... ch) {
this.value = value;
children = Arrays.asList(ch);
}
public <U> Tree<U> map(Function<? super T, ? extends U> f) {
Tree<U> t = new Tree<>(value == null? null: f.apply(value));
if(!children.isEmpty()) {
t.children = new ArrayList<>(children.size());
for(Tree<T> ch: children) t.children.add(ch.map(f));
}
return t;
}
public #Override String toString() {
if(children.isEmpty()) return value == null? "": value.toString();
final StringBuilder sb = new StringBuilder(100);
toString(sb, 0, 0);
return sb.toString();
}
public void toString(StringBuilder sb, int preS, int preEnd) {
final int myHandle = sb.length() - 2;
sb.append(value == null? "": value).append('\n');
final int num = children.size() - 1;
if (num >= 0) {
if (num != 0) {
for (int ix = 0; ix < num; ix++) {
int nPreS = sb.length();
sb.append(sb, preS, preEnd);
sb.append("\u2502 ");
int nPreE = sb.length();
children.get(ix).toString(sb, nPreS, nPreE);
}
}
int nPreS = sb.length();
sb.append(sb, preS, preEnd);
final int lastItemHandle = sb.length();
sb.append(" ");
int nPreE = sb.length();
children.get(num).toString(sb, nPreS, nPreE);
sb.setCharAt(lastItemHandle, '\u2514');
}
if (myHandle > 0) {
sb.setCharAt(myHandle, '\u251c');
sb.setCharAt(myHandle + 1, '\u2500');
}
}
}
you will get:
With max depth: 1
├─estimated: 1 [a=1, b=2]
└─estimated: 1 []
With max depth: 2
├─
│ ├─estimated: 0 [a=1, b=2]
│ └─estimated: 0 []
└─
├─estimated: 0 []
└─estimated: 0 []
With max depth: 2147483647
├─
│ ├─
│ │ ├─
│ │ │ ├─estimated: 0 []
│ │ │ └─estimated: 0 [a=1]
│ │ └─
│ │ ├─estimated: 0 [b=2]
│ │ └─estimated: 0 []
│ └─
│ ├─
│ │ ├─estimated: 0 []
│ │ └─estimated: 0 []
│ └─
│ ├─estimated: 0 []
│ └─estimated: 0 []
└─
├─
│ ├─
│ │ ├─estimated: 0 []
│ │ └─estimated: 0 []
│ └─
│ ├─estimated: 0 []
│ └─estimated: 0 []
└─
├─
│ ├─estimated: 0 []
│ └─estimated: 0 []
└─
├─estimated: 0 []
└─estimated: 0 []
On ideone
So, as said, the spliterator can split down to individual elements if we split deep enough, however, the estimated size of two elements does not suggest that it’s worth doing that. On each split, it will halve the estimate and while you might say that it’s wrong for the elements you’re interested in, it’s actually correct for most spliterators here, as when going down to the maximum level, most spliterators are representing an empty range and splitting them turns out to be a waste of resources.
As said in the other answer, the decision is about balancing the work of splitting (or preparation in general) and the expected work to parallelize, which the Stream implementation can’t know in advance. If you know in advance that the per-element workload will be very high, to justify more preparation work, you can use, e.g. new ArrayList<>(map.[keySet|entrySet|values]()) .parallelStream() to enforce balanced splits. Usually, the problem will be much smaller for larger maps anyway.
Thank you for Holger's answer, I will add more details here.
The root cause comes from the sizeEstimate inaccuracy for HashMap.values().
By default, HashMap has the capacity of 16, with 2 elements, which backed by an array. The estimate size of the Spliterator is 2.
Every time, each split will halve the array by half. In this case, the 16 length of array is split into two, 8 in each half, and each half has estimate size of 1. As the elements are placed according to hashcode, unfortunately, two elements lie in the same half.
Then the forkjoin framework thinks 1 is below the sizeThreshold, it will stop splitting and begin to process the task.
At the same time, arrayList does not have this problem, as the estimatedSize is always accurate.

Can someone explain why/how Nodes from LinkedLists change without changing them directly in Java?

Sorry, the title of this question may not be entirely clear. I'm just having trouble understanding this sample question from my upcoming exam:
The following Node points to the following list of chars:
head -> [a] -> [b] -> [c] -> [d]
where the list nodes are instances of the following class
public class Node {
public char value;
public Node next;
}
What will be printed after the following code executes?
Node ptr1, ptr2, p;
ptr1 = head;
ptr2 = head.next;
ptr1.next = ptr2.next.next;
ptr2.next.next = ptr1;
p = head;
head = head.next;
while(p!=null){
System.out.print(p.value + " ");
p=p.next;
}
Apparently the answer is a d. Can someone explain this to me?
These were my steps toward solving the problem:
ptr1 = head; //ptr1 -> [a]->[b]->[c]->[d]
ptr2 = head.next; //ptr2 -> [b]->[c]->[d]
prt1.next = ptr2.next.next; //prt1 -> [a]->[d]
prt2.next.next=prt1; //prt2 -> [b]->[c]->[a]->[d]
p=head; //p-> [a]->[b]->[c]->[d]
head=head.next; // head-> [b]->[c]->[d]
So I was thinking that the answer was just iterating over the original Node (a, b, c, d), which obviously isn't the case, I just don't understand at what point "head" became anything than it's original state. Do the Node variables change the original Node somehow? This doesn't make sense to me from everything I know about Java so far. Sorry if this is a stupid question I am just failing to understand and I haven't been able to find anything online regarding this. Thanks.
You should draw it on paper, so you can see what's going on.
The sequence is as follows:
head → [a] → [b] → [c] → [d]
ptr1 = head;
ptr1
↓
head → [a] → [b] → [c] → [d]
ptr2 = head.next;
ptr1 ptr2
↓ ↓
head → [a] → [b] → [c] → [d]
ptr1.next = ptr2.next.next;
ptr1 ptr2
↓ ↓
↓ [b] → [c]
↓ ↓
head → [a] → → → → [d]
ptr2.next.next = ptr1;
ptr1 ptr2
↓ ↓
↓ [b] → [c]
↓ ↓
head → → → → → → → [a] → [d]
p = head;
ptr1 ptr2
↓ ↓
↓ [b] → [c]
↓ ↓
head → → → → → → → [a] → [d]
↑
p
head = head.next;
ptr1 ptr2 head
↓ ↓ ↓
↓ [b] → [c] ↓
↓ ↓ ↓
→ → → → → [a] → [d]
↑
p
You're correct up to this point.
prt2.next.next=prt1; //prt2 -> [b]->[c]->[a]->[d]
Then, on this next step, head hasn't changed. You're right about that. Now, head is pointing to [a] and always has been, so it's still pointing to [a], even though [a] has moved somewhere else.
p=head; //p-> [a]->[d]
Then we assign head to head.next, but that doesn't even matter because we never use head again. So we're iterating over [a] then [d], hence the output.

Level Order Traversal of BST in Java

I'm trying to do a level order traversal on the following BST.
BST bst = new BST();
int [] arr = {12, 15, 7, 3, 81, 9, 36, 23, 33, 41, 4};
for (int i = 0; i <arr.length; i++) {
bst.add(arr[i]);
}
This is my code.
public static void levelOrderTraversal(Node root){
if(root == null) return;
Queue<Node> queue = new ArrayDeque<Node>();
queue.add(root);
while(!queue.isEmpty()){
Node current = queue.peek();
System.out.print(current.getData() + " ");
if (current.left != null)
queue.add(current.left);
if (current.right != null){
queue.add(current.right);
}
queue.poll();
}
}
The output that I get is
12 7 15 3 9 81 4 36 23 41 33
This clearly is not the correct BFS. Where am I going wrong.
Your traversal function is correct. You may want to check this online tool
https://www.cs.usfca.edu/~galles/visualization/BST.html
It provides visualization of the insert, delete and find process as well. This is the resulting tree:
I don't see why, given the list of elements you provide the tree will look like:
12
|- 7 (L)
|- 3 (L)
|- 4 (R)
|- 9 (R)
|- 15 (R)
|- 81 (R)
|- 36 (L)
|- 23 (L)
|- 33 (R)
|- 41 (R)
Or a better visual:
12
/ \
7 15
/ \ \
3 9 81
\ /
4 36
/ \
23 41
\
33
Note this is not a balanced binary search tree. A BST will simply create first a node 12 (first element you provide). And 12 will remain the root. All elements less than are sorted left (and start growing their own roots etc.)

Categories