Related
I am doing a linked list project for my class at school. Essentially we are supposed to make a linked list from scratch, and have add, delete, and find commands. No matter how hard I've been trying I cannot seem to get the list to display anything other than the head node. here are my classes starting from node
public class main {
public static void main(String args[]) {
for (int i = 0; i < 3; i++) {
LinkedList list = new LinkedList();
Node focus = new Node();
String start;
start = JOptionPane.showInputDialog("Enter 'A' to add an item"
+ "\n" + "Enter 'D' to delete an item\nEnter 'F' to find an item.");
if (start.equals("a") || start.equals("A")) {
focus.data = JOptionPane.showInputDialog("enter an item to ADD");
list.Add(focus);
while (focus != null) {
focus = list.head;
focus = focus.next;
JOptionPane.showMessageDialog(null, "your list is\n" + focus.getData());
}
}
}
}
}
public class Node {
String data;
Node next;
Node prev;
public Node(String data, Node next) {
this.data = data;
this.next = next;
}
Node() {
}
public void setData(String data) {
this.data = data;
}
public String getData() {
return this.data;
}
public void setNext(Node next) {//setnext
this.next = next;
}
public Node getNext() {
return next;
}
}
public class LinkedList extends Node {
Node head;
int listcount = 0;
public LinkedList() {
this.prev = null;
this.next = null;
this.listcount = 0;
}
LinkedList(Node Set) {
}
public void Add(Node n) {
Node current = this.prev;
if (current != null) {
current = this.prev;
this.prev = new Node();
} else {
head = this.prev = new Node();
current = head;
}
listcount++;
}
}
I think my biggest problem is the "your list is" part. I can't seem to get it to display anything other than the head node. I would really appreciate the help, as this has been giving me a huge headache. :)
First of all, why does your LinkedList extends the Node class? It's a linked list not a node. There's nothing coming before and after the linked list. So the linked list has no prev and next. All the elements are added in the list and the elements are inserted after the head node. The head of the node has a prev and a next. In the Add method, if the head of the list is null (i.e, the list is empty), the new element becomes the head of the list. Otherwise, the new node is inserted after the head.
public class LinkedList {
Node head;
int listcount = 0;
public LinkedList() {
this.head = null;
this.listcount = 0;
}
public void Add(Node n) {
Node current = this.head;
if (current == null) {
head = n;
} else {
Node prev = null;
while (current != null) {
prev = current;
current = current.next;
}
prev.next = n;
}
listcount++;
}
public String toString() {
StringBuilder builder = new StringBuilder();
Node current = this.head;
while (current != null) {
builder.append(current.data).append(", ");
current = current.next;
}
return builder.toString();
}
}
I added a toString method which loops over the list and builds a string with the content from each node.
In the main method there are a few problems. The linked list is initialised only once not every time you select a choice. If you initialise the linked list every time you select something, then the linked list will always be reinitialised and the only node that will contain will be the head node after you add the new element.
public class main {
public static void main(String args[]) {
String start;
boolean finished=false;
LinkedList list = new LinkedList();
while(!finished) {
start = JOptionPane.showInputDialog("Enter 'A' to add an item"
+ "\n" + "Enter 'D' to delete an item\nEnter 'F' to find an item.");
if (start.equals("a") || start.equals("A")) {
Node focus = new Node();
focus.data = JOptionPane.showInputDialog("enter an item to ADD");
list.Add(focus);
JOptionPane.showMessageDialog(null, "your list is\n" + list.toString());
}
else {
finished = true;
}
}
}
}
Try to go over the code and understand what is happening and why. Also use pencil and paper to understand the logic.
I wrote a simple method to append a linked list at the end of another linked list.So what the program should ideally do is when I give it two lists
list1 ===>1->2->3
list2 ===>4->5->6
updatedList ==>1->2->3->4->5->6
But when I run the method appendList it goes into an infinite loop printing 1 to 6 indefinitely.What am I doing wrong out here?
public static Node appendList(Node head1, Node head2) {
Node prev = null;
Node current = head1;
while (current != null) {
prev = current;
current = current.next;
}
prev.next = head2;
return head1;
}
Oh and I forgot to add the Node class and how I call the method from my main .I know its bit cumbersome but here it is
public class ReverseLinkedList {
class Node {
int data;
Node next;
Node(int data) {
this.data = data;
}
public void displayData() {
System.out.println(data);
}
}
public static void main(String args[]) {
ReverseLinkedList reversedList = new ReverseLinkedList();
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the length of the linked list!!");
int listSize = scanner.nextInt();
System.out.println("Enter the Numbers you want to insert!!");
int count = 0;
while (scanner.hasNextLine()) {
if (count == listSize)
break;
reversedList.insert(scanner.nextInt());
count++;
}
System.out.println("Inserted List !!");
reversedList.displayList();
/*
* Node reverseNodeStart =
* reversedList.reverseList1(reversedList.first);
* System.out.println("Reversed List !!"); while (reverseNodeStart !=
* null) { reverseNodeStart.displayData(); reverseNodeStart =
* reverseNodeStart.next; }
*/
Node reverseNodeStart = reversedList.appendList(reversedList.first,
reversedList.first);
while (reverseNodeStart != null) {
reverseNodeStart.displayData();
reverseNodeStart = reverseNodeStart.next;
}
}
}
The problem was I was using the same List which was causing the circular reference.It works fine now.You knew the problem even before I posted the code now that's impressive. Thanks!!I solved it by creating a new List2 and passing in List1 and List2.
appendList(Node lis1head, Node list2head)
import java.util.*;
/*
* Remove duplicates from an unsorted linked list
*/
public class LinkedListNode {
public int data;
public LinkedListNode next;
public LinkedListNode(int data) {
this.data = data;
}
}
public class Task {
public static void deleteDups(LinkedListNode head){
Hashtable<Integer, Boolean> table=new Hashtable<Integer, Boolean>();
LinkedListNode previous=null;
//nth node is not null
while(head!=null){
//have duplicate
if(table.containsKey(head.data)){
//skip duplicate
previous.next=head.next;
}else{
//put the element into hashtable
table.put(head.data,true);
//move to the next element
previous=head;
}
//iterate
head=head.next;
}
}
public static void main (String args[]){
LinkedList<Integer> list=new LinkedList<Integer>();
list.addLast(1);
list.addLast(2);
list.addLast(3);
list.addLast(3);
list.addLast(3);
list.addLast(4);
list.addLast(4);
System.out.println(list);
LinkedListNode head=new LinkedListNode(list.getFirst());
Task.deleteDups(head);
System.out.println(list);
}
}
The result: [1, 2, 3, 3, 3, 4, 4]
[1, 2, 3, 3, 3, 4, 4]
It does not eliminate the duplicates.
Why doesn't the method work?
Iterate through the linked list,
adding each element to a hash table. When we discover a duplicate element, we remove the element and continue iterating. We can do this all in one pass since we are using a linked list.
The following solution takes O(n) time, n is the number of element in the linked list.
public static void deleteDups (LinkedListNode n){
Hashtable table = new Hashtable();
LinkedListNode previous = null;
while(n!=null){
if(table.containsKey(n.data)){
previous.next = n.next;
} else {
table.put(n.data, true);
previous = n;
}
n = n.next;
}
}
The solution you have provided does not modify the original list.
To modify the original list and remove duplicates, we can iterate with two pointers. Current: which iterates through LinkedList, and runner which checks all subsequent nodes for duplicates.
The code below runs in O(1) space but O(N square) time.
public void deleteDups(LinkedListNode head){
if(head == null)
return;
LinkedListNode currentNode = head;
while(currentNode!=null){
LinkedListNode runner = currentNode;
while(runner.next!=null){
if(runner.next.data == currentNode.data)
runner.next = runner.next.next;
else
runner = runner.next;
}
currentNode = currentNode.next;
}
}
Reference : Gayle laakmann mcdowell
Here's two ways of doing this in java. the method used above works in O(n) but requires additional space. Where as the second version runs in O(n^2) but requires no additional space.
import java.util.Hashtable;
public class LinkedList {
LinkedListNode head;
public static void main(String args[]){
LinkedList list = new LinkedList();
list.addNode(1);
list.addNode(1);
list.addNode(1);
list.addNode(2);
list.addNode(3);
list.addNode(2);
list.print();
list.deleteDupsNoStorage(list.head);
System.out.println();
list.print();
}
public void print(){
LinkedListNode n = head;
while(n!=null){
System.out.print(n.data +" ");
n = n.next;
}
}
public void deleteDups(LinkedListNode n){
Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
LinkedListNode prev = null;
while(n !=null){
if(table.containsKey(new Integer(n.data))){
prev.next = n.next; //skip the previously stored references next node
}else{
table.put(new Integer(n.data) , true);
prev = n; //stores a reference to n
}
n = n.next;
}
}
public void deleteDupsNoStorage(LinkedListNode n){
LinkedListNode current = n;
while(current!=null){
LinkedListNode runner = current;
while(runner.next!=null){
if(runner.next.data == current.data){
runner.next = runner.next.next;
}else{
runner = runner.next;
}
}
current = current.next;
}
}
public void addNode(int d){
LinkedListNode n = new LinkedListNode(d);
if(this.head==null){
this.head = n;
}else{
n.next = head;
head = n;
}
}
private class LinkedListNode{
LinkedListNode next;
int data;
public LinkedListNode(int d){
this.data = d;
}
}
}
You can use the following java method to remove duplicates:
1) With complexity of O(n^2)
public void removeDuplicate(Node head) {
Node temp = head;
Node duplicate = null; //will point to duplicate node
Node prev = null; //prev node to duplicate node
while (temp != null) { //iterate through all nodes
Node curr = temp;
while (curr != null) { //compare each one by one
/*in case of duplicate skip the node by using prev node*/
if (curr.getData() == temp.getData() && temp != curr) {
duplicate = curr;
prev.setNext(duplicate.getNext());
}
prev = curr;
curr = curr.getNext();
}
temp = temp.getNext();
}
}
Input:1=>2=>3=>5=>5=>1=>3=>
Output:1=>2=>3=>5=>
2)With complexity of O(n) using hash table.
public void removeDuplicateUsingMap(Node head) {
Node temp = head;
Map<Integer, Boolean> hash_map = new HashMap<Integer, Boolean>(); //create a hash map
while (temp != null) {
if (hash_map.get(temp.getData()) == null) { //if key is not set then set is false
hash_map.put(temp.getData(), false);
} else { //if key is already there,then delete the node
deleteNode(temp,head);
}
temp = temp.getNext();
}
}
public void deleteNode(Node n, Node start) {
Node temp = start;
if (n == start) {
start = null;
} else {
while (temp.getNext() != n) {
temp = temp.getNext();
}
temp.setNext(n.getNext());
}
}
Input:1=>2=>3=>5=>5=>1=>3=>
Output:1=>2=>3=>5=>
Ans is in C . first sorted link list sort() in nlog time and then deleted duplicate del_dip() .
node * partition(node *start)
{
node *l1=start;
node *temp1=NULL;
node *temp2=NULL;
if(start->next==NULL)
return start;
node * l2=f_b_split(start);
if(l1->next!=NULL)
temp1=partition(l1);
if(l2->next!=NULL)
temp2=partition(l2);
if(temp1==NULL || temp2==NULL)
{
if(temp1==NULL && temp2==NULL)
temp1=s_m(l1,l2);
else if(temp1==NULL)
temp1=s_m(l1,temp2);
else if(temp2==NULL)
temp1=s_m(temp1,l2);
}
else
temp1=s_m(temp1,temp2);
return temp1;
}
node * sort(node * start)
{
node * temp=partition(start);
return temp;
}
void del_dup(node * start)
{
node * temp;
start=sort(start);
while(start!=NULL)
{
if(start->next!=NULL && start->data==start->next->data )
{
temp=start->next;
start->next=start->next->next;
free(temp);
continue;
}
start=start->next;
}
}
void main()
{
del_dup(list1);
print(list1);
}
Try this it is working for delete the duplicate elements from your linkedList
package com.loknath.lab;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
public class Task {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
list.addLast(1);
list.addLast(2);
list.addLast(3);
list.addLast(3);
list.addLast(3);
list.addLast(4);
list.addLast(4);
deleteDups(list);
System.out.println(list);
}
public static void deleteDups(LinkedList<Integer> list) {
Set s = new HashSet<Integer>();
s.addAll(list);
list.clear();
list.addAll(s);
}
}
I think you can just use one iterator current to finish this problem
public void compress(){
ListNode current = front;
HashSet<Integer> set = new HashSet<Integer>();
set.add(current.data);
while(current.next != null){
if(set.contains(current.next.data)){
current.next = current.next.next; }
else{
set.add(current.next.data);
current = current.next;
}
}
}
Here is a very easy version.
LinkedList<Integer> a = new LinkedList<Integer>(){{
add(1);
add(1);
}}
Set<Integer> set = new HashSet<Integer>(a);
a = new LinkedList<Integer>(set);
Very concise. Isn't it?
The first problem is that
LinkedListNode head=new LinkedListNode(list.getFirst());
does not actually initialize head with the contents of list. list.getFirst() simply returns the Integer 1, and head contains 1 as its only element. You would have to initialize head by looping through list in order to get all of the elements.
In addition, although
Task.deleteDups(head)
modifies head, this leaves list completely unchanged—there is no reason why the changes to head should propagate to list. Therefore, to check your method, you would have to loop down head and print out each element, rather than printing out list again.
Try This.Its working.
// Removing Duplicates in Linked List
import java.io.*;
import java.util.*;
import java.text.*;
class LinkedListNode{
int data;
LinkedListNode next=null;
public LinkedListNode(int d){
data=d;
}
void appendToTail(int d){
LinkedListNode newnode = new LinkedListNode(d);
LinkedListNode n=this;
while(n.next!=null){
n=n.next;
}
n.next=newnode;
}
void print(){
LinkedListNode n=this;
System.out.print("Linked List: ");
while(n.next!=null){
System.out.print(n.data+" -> ");
n=n.next;
}
System.out.println(n.data);
}
}
class LinkedList2_0
{
public static void deletenode2(LinkedListNode head,int d){
LinkedListNode n=head;
// If It's head node
if(n.data==d){
head=n.next;
}
//If its other
while(n.next!=null){
if(n.next.data==d){
n.next=n.next.next;
}
n=n.next;
}
}
public static void removeDuplicateWithBuffer(LinkedListNode head){
LinkedListNode n=head;
LinkedListNode prev=null;
Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
while(n!=null){
if(table.containsKey(n.data)){
prev.next=n.next;
}
else{
table.put(n.data,true);
prev=n;
}
n=n.next;
}
}
public static void removeDuplicateWithoutBuffer(LinkedListNode head){
LinkedListNode currentNode=head;
while(currentNode!=null){
LinkedListNode runner=currentNode;
while(runner.next!=null){
if(runner.next.data==currentNode.data){
runner.next=runner.next.next;
}
else
runner=runner.next;
}
currentNode=currentNode.next;
}
}
public static void main(String[] args) throws java.lang.Exception {
LinkedListNode head=new LinkedListNode(1);
head.appendToTail(1);
head.appendToTail(3);
head.appendToTail(2);
head.appendToTail(3);
head.appendToTail(4);
head.appendToTail(5);
head.print();
System.out.print("After Delete: ");
deletenode2(head,4);
head.print();
//System.out.print("After Removing Duplicates(with buffer): ");
//removeDuplicateWithBuffer(head);
//head.print();
System.out.print("After Removing Duplicates(Without buffer): ");
removeDuplicateWithoutBuffer(head);
head.print();
}
}
here are a couple other solutions (slightly different from Cracking coding inerview, easier to read IMO).
public void deleteDupes(Node head) {
Node current = head;
while (current != null) {
Node next = current.next;
while (next != null) {
if (current.data == next.data) {
current.next = next.next;
break;
}
next = next.next;
}
current = current.next;
}
}
public void deleteDupes(Node head) {
Node current = head;
while (current != null) {
Node next = current.next;
while (next != null) {
if (current.data == next.data) {
current.next = next.next;
current = current.next;
next = current.next;
} else {
next = next.next;
}
}
current = current.next;
}
}
It's simple way without HashSet or creation Node.
public String removeDuplicates(String str) {
LinkedList<Character> chars = new LinkedList<Character>();
for(Character c: str.toCharArray()){
chars.add(c);
}
for (int i = 0; i < chars.size(); i++){
for (int j = i+1; j < chars.size(); j++){
if(chars.get(j) == chars.get(i)){
chars.remove(j);
j--;
}
}
}
return new String(chars.toString());
}
And to verify it:
#Test
public void verifyThatNoDuplicatesInLinkedList(){
CodeDataStructures dataStructures = new CodeDataStructures();
assertEquals("abcdefghjk", dataStructures.removeDuplicates("abcdefgabcdeaaaaaaaaafabcdeabcdefgabcdbbbbbbefabcdefghjkabcdefghjkghjkhjkabcdefghabcdefghjkjfghjkabcdefghjkghjkhjkabcdefghabcdefghjkj")
.replace(",", "")
.replace("]", "")
.replace("[", "")
.replace(" ", ""));
}
LinkedList<Node> list = new LinkedList<Node>();
for(int i=0; i<list.size(); i++){
for(int j=0; j<list.size(); j++){
if(list.get(i).data == list.get(j).data && i!=j){
if(i<j){
list.remove(j);
if(list.get(j)!= null){
list.get(j-1).next = list.get(j);
}else{
list.get(j-1).next = null;
}
}
else{
if(i>j){
list.remove(i);
if(list.get(i) != null){
list.get(j).next = list.get(i);
}else{
list.get(j).next = null;
}
}
}
}
}
}
/**
*
* Remove duplicates from an unsorted linked list.
*/
public class RemoveDuplicates {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<String>();
list.add("Apple");
list.add("Grape");
list.add("Apple");
HashSet<String> set = removeDuplicatesFromList(list);
System.out.println("Removed duplicates" + set);
}
public static HashSet<String> removeDuplicatesFromList(LinkedList<String> list){
HashSet<String> set = new LinkedHashSet<String>();
set.addAll(list);
return set;
}
}
Below code implements this without needing any temporary buffer. It starts with comparing first and second nodes, if not a match, it adds char at first node to second node then proceeds comparing all chars in second node to char at third node and so on. After comperison is complete, before leaving the node it clears everything that is added and restores its old value which resides at node.val.char(0)
F > FO > FOL > (match found, node.next = node.next.next) > (again match, discard it) > FOLW > ....
public void onlyUnique(){
Node node = first;
while(node.next != null){
for(int i = 0 ; i < node.val.length(); i++){
if(node.val.charAt(i) == node.next.val.charAt(0)){
node.next = node.next.next;
}else{
if(node.next.next != null){ //no need to copy everything to the last element
node.next.val = node.next.val + node.val;
}
node.val = node.val.charAt(0)+ "";
}
}
node = node.next;
}
}
All the solutions given above looks optimised but most of them defines custom Node as a part of solution. Here is a simple and practical solution using Java's LinkedList and HashSet which does not confine to use the preexisting libraries and methods.
Time Complexity : O(n)
Space Complexity: O(n)
#SuppressWarnings({ "unchecked", "rawtypes" })
private static LinkedList<?> removeDupsUsingHashSet(LinkedList<?> list) {
HashSet set = new HashSet<>();
for (int i = 0; i < list.size();) {
if (set.contains(list.get(i))) {
list.remove(i);
continue;
} else {
set.add(list.get(i));
i++;
}
}
return list;
}
This also preserves the list order.
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>();
linkedList.add(1);
linkedList.add(2);
linkedList.add(2);
linkedList.add(3);
linkedList.add(4);
linkedList.add(5);
linkedList.add(6);
deleteElement(linkedList);
System.out.println(linkedList);
}
private static void deleteElement(LinkedList<Integer> linkedList) {
Set s = new HashSet<Integer>();
s.addAll(linkedList);
linkedList.clear();
linkedList.addAll(s);
}
This is my Java version
// Remove duplicate from a sorted linked list
public void removeDuplicates() {
Node current = head;
Node next = null;
/* Traverse list till the last node */
while (current != null) {
next = current;
/*
* Compare current node with the next node and keep on deleting them until it
* matches the current node data
*/
while (next != null && current.getValue() == next.getValue()) {
next = next.getNext();
}
/*
* Set current node next to the next different element denoted by temp
*/
current.setNext(next);
current = current.getNext();
}
}
1.Fully Dynamic Approach
2.Remove Duplicates from LinkedList
3.LinkedList Dynamic Object based creation
Thank you
import java.util.Scanner;
class Node{
int data;
Node next;
public Node(int data)
{
this.data=data;
this.next=null;
}
}
class Solution
{
public static Node insert(Node head,int data)
{
Node p=new Node(data);
if(head==null)
{
head=p;
}
else if(head.next==null)
{
head.next=p;
}
else
{
Node start=head;
while(start.next!=null)
{
start=start.next;
}
start.next=p;
return head;
//System.out.println();
}
return head;
}
public static void display(Node head)
{
Node start=head;
while(start!=null)
{
System.out.print(start.data+" ");
start=start.next;
}
}
public static Node remove_duplicates(Node head)
{
if(head==null||head.next==null)
{
return head;
}
Node prev=head;
Node p=head.next;
while(p!=null)
{
if(p.data==prev.data)
{
prev.next=p.next;
p=p.next;
}
else{
prev=p;
p=p.next;
}
}
return head;
}
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
Node head=null;
int T=sc.nextInt();
while(T-->0)
{
int ele=sc.nextInt();
head=insert(head,ele);
}
head=remove_duplicates(head);
display(head);
}
}
input:
5
1 1 2 3 3
output:
1 2 3
So the app reads from an external file a bunch of strings, each on a separate line.
For example:
and
cake
here
It is not arranged in any particular order. I need to read these letters and put them into linked list and finally sort them.
I need help on doing that:
Here is the current code:
import java.util.*;
import java.io.*;
public class LinkedList
{
static File dataInpt;
static Scanner inFile;
public static void main(String[] args) throws IOException
{
dataInpt=new File("C:\\lldata.txt");
inFile=new Scanner(dataInpt);
Node first = insertInOrder();
printList(first);
}
public static Node getNode(Object element)
{
Node temp=new Node();
temp.value=element;
temp.next=null;
return temp;
}
public static void printList(Node head)
{
Node ptr; //not pointing anywhere
for(ptr=head;ptr!=null;ptr=ptr.next)
System.out.println(ptr.value);
System.out.println();
}
public static Node insertInOrder()
{
Node first=getNode(inFile.next());
Node current=first,previous=null;
Node last=first;
int count=0;
while (inFile.hasNext())
{
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) < 0)
{
current.next=last;
last=current;
}
previous=current;
current=getNode(inFile.next());
}
return last;
}
}
But that gives an infinite loop with "Cat".
Here is the data file:
Lol
Cake
Gel
Hi
Gee
Age
Rage
Tim
Where
And
Kite
Jam
Nickel
Cat
Ran
Jug
Here
Okay, self-study. Split the reading and inserting. Though old and new code both have 14 lines of code,
it makes it more intelligable.
public static Node insertInOrder() {
Node first = null;
while (inFile.hasNext()) {
String value = inFile.next().toString();
first = insert(first, value);
}
return first;
}
/**
* Insert in a sub-list, yielding a changed sub-list.
* #param node the sub-list.
* #param value
* #return the new sub-list (the head node might have been changed).
*/
private static Node insert(Node node, String value) {
if (node == null) { // End of list
return getNode(value);
}
int comparison = node.value.compareTo(value);
if (comparison >= 0) { // Or > 0 for stable sort.
Node newNode = getNode(value); // Insert in front.
newNode.next = node;
return newNode;
}
node.next = insert(node.next, value); // Insert in the rest.
return node;
}
This uses recursion (nested "rerunning"), calling insert inside insert. This works like a loop, or work delegation to a clone, or like a mathematical inductive proof.
Iterative alternative
also simplified a bit.
private static void Node insert(Node list, String value) {
Node node = list;
Node previous = null;
for (;;) {
if (node == null || node.value.compareTo(value) >= 0) {
Node newNode = getNode(value);
newNode.next = node;
if (previous == null)
list = newNode;
else
previous.next = newNode;
break;
}
// Insert in the rest:
previous = node;
node = node.next;
}
return list;
}
public static Node insertInOrder()
{
Node first=getNode(inFile.next());
Node current=first,previous=null;
Node last=first;
int count=0;
while (inFile.hasNext())
{
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) < 0)
{
current.next=last;
last=current;
}
previous=current;
current=getNode(inFile.next());
}
return last;
}
First of all, you never do anything with the last line read from the file, so that's not ever inserted. You have to read the line and create the new Node before relinking next pointers.
Then, if last and previous refer to the same Node and the data of current is larger than that of previous,
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
You set last.next = last, breaking the list. From the code (in particular the absence of a sort(Node) function), it seems as though you want to sort the list as it is created. But you only ever compare each new Node with one other, so that doesn't maintain order.
For each new node, you have to find the node after which it has to be inserted, scanning from the front of the list, and modify current.next and the predecessor's next.
In relatively simple code like that in your question, a good exercise to understanding it is to work through a few interations of your loop, inspecting the values of all your local variable to see the effect of your code. You can even do it by hand if the code is simple. If it is too difficult to do by hand, your code is probably too complicated. If you can't follow it, how can you know if you are doing what you intend. For example, I could be wrong, but this appears the be the state at the top of each iteration of the loop. It starts falling apart on the third time through, and by the fourth you have a severe problem as your list becomes disjointed.
1)last = first = Lol, current = previous = null
Lol->null
2)last = first = previous = Lol, current = Cake
Lol->Lol
3)first = Lol, last = Cake, previous = Cake, current = Gel
Cake->Lol->Lol
4)first = Lol, last = Cake, previous = Cake, current = Hi
Cake->Gel, Lol->Lol
Quite honestly, if I were running the course, I would consider the correct answer to be:
List<String> list = new LinkedList<String>();
// read in lines and: list.add(word);
Collections.sort(list);
Ok, I don't remember exactly school theory about insertion sort, but here is somehow a mix of what I think it is and your code:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class LinkedList {
public static class Node {
public String value;
public Node next;
}
static File dataInpt;
static Scanner inFile;
public static void main(String[] args) throws IOException {
inFile = new Scanner("Lol\r\n" + "Cake\r\n" + "Gel\r\n" + "Hi\r\n" + "Gee\r\n" + "Age\r\n" + "Rage\r\n" + "Tim\r\n" + "Where\r\n"
+ "And\r\n" + "Kite\r\n" + "Jam\r\n" + "Nickel\r\n" + "Cat\r\n" + "Ran\r\n" + "Jug\r\n" + "Here");
Node first = insertInOrder();
printList(first);
}
public static Node getNode(String element) {
Node temp = new Node();
temp.value = element;
temp.next = null;
return temp;
}
public static void printList(Node head) {
Node ptr; // not pointing anywhere
for (ptr = head; ptr != null; ptr = ptr.next) {
System.out.println(ptr.value);
}
System.out.println();
}
public static Node insertInOrder() {
Node current = getNode(inFile.next());
Node first = current, last = current;
while (inFile.hasNext()) {
if (first != null && current.value.compareTo(first.value) < 0) {
current.next = first;
first = current;
} else if (last != null && current.value.compareTo(last.value) > 0) {
last.next = current;
last = current;
} else {
Node temp = first;
while (current.value.compareTo(temp.value) < 0) {
temp = temp.next;
}
current.next = temp.next;
temp.next = current;
}
current = getNode(inFile.next());
}
return first;
}
}
And it works like a charm. Of course this far from optimal, both in terms of performance and code reuse.
Okay, I have read through all the other related questions and cannot find one that helps with java. I get the general idea from deciphering what i can in other languages; but i am yet to figure it out.
Problem: I would like to level sort (which i have working using recursion) and print it out in the general shape of a tree.
So say i have this:
1
/ \
2 3
/ / \
4 5 6
My code prints out the level order like this:
1 2 3 4 5 6
I want to print it out like this:
1
2 3
4 5 6
Now before you give me a moral speech about doing my work... I have already finished my AP Comp Sci project and got curious about this when my teacher mentioned the Breadth First Search thing.
I don't know if it will help, but here is my code so far:
/**
* Calls the levelOrder helper method and prints out in levelOrder.
*/
public void levelOrder()
{
q = new QueueList();
treeHeight = height();
levelOrder(myRoot, q, myLevel);
}
/**
* Helper method that uses recursion to print out the tree in
* levelOrder
*/
private void levelOrder(TreeNode root, QueueList q, int curLev)
{
System.out.print(curLev);
if(root == null)
{
return;
}
if(q.isEmpty())
{
System.out.println(root.getValue());
}
else
{
System.out.print((String)q.dequeue()+", ");
}
if(root.getLeft() != null)
{
q.enqueue(root.getLeft().getValue());
System.out.println();
}
if(root.getRight() != null)
{
q.enqueue(root.getRight().getValue());
System.out.println();
curLev++;
}
levelOrder(root.getLeft(),q, curLev);
levelOrder(root.getRight(),q, curLev);
}
From what i can figure out, i will need to use the total height of the tree, and use a level counter... Only problem is my level counter keeps counting when my levelOrder uses recursion to go back through the tree.
Sorry if this is to much, but some tips would be nice. :)
Here is the code, this question was asked to me in one of the interviews...
public void printTree(TreeNode tmpRoot) {
Queue<TreeNode> currentLevel = new LinkedList<TreeNode>();
Queue<TreeNode> nextLevel = new LinkedList<TreeNode>();
currentLevel.add(tmpRoot);
while (!currentLevel.isEmpty()) {
Iterator<TreeNode> iter = currentLevel.iterator();
while (iter.hasNext()) {
TreeNode currentNode = iter.next();
if (currentNode.left != null) {
nextLevel.add(currentNode.left);
}
if (currentNode.right != null) {
nextLevel.add(currentNode.right);
}
System.out.print(currentNode.value + " ");
}
System.out.println();
currentLevel = nextLevel;
nextLevel = new LinkedList<TreeNode>();
}
}
This is the easiest solution
public void byLevel(Node root){
Queue<Node> level = new LinkedList<>();
level.add(root);
while(!level.isEmpty()){
Node node = level.poll();
System.out.print(node.item + " ");
if(node.leftChild!= null)
level.add(node.leftChild);
if(node.rightChild!= null)
level.add(node.rightChild);
}
}
https://github.com/camluca/Samples/blob/master/Tree.java
in my github you can find other helpful functions in the class Tree like:
Displaying the tree
****......................................................****
42
25 65
12 37 43 87
9 13 30 -- -- -- -- 99
****......................................................****
Inorder traversal
9 12 13 25 30 37 42 43 65 87 99
Preorder traversal
42 25 12 9 13 37 30 65 43 87 99
Postorder traversal
9 13 12 30 37 25 43 99 87 65 42
By Level
42 25 65 12 37 43 87 9 13 30 99
Here is how I would do it:
levelOrder(List<TreeNode> n) {
List<TreeNode> next = new List<TreeNode>();
foreach(TreeNode t : n) {
print(t);
next.Add(t.left);
next.Add(t.right);
}
println();
levelOrder(next);
}
(Was originally going to be real code - got bored partway through, so it's psueodocodey)
Just thought of sharing Anon's suggestion in real java code and fixing a couple of KEY issues (like there is not an end condition for the recursion so it never stops adding to the stack, and not checking for null in the received array gets you a null pointer exception).
Also there is no exception as Eric Hauser suggests, because it is not modifying the collection its looping through, it's modifying a new one.
Here it goes:
public void levelOrder(List<TreeNode> n) {
List<TreeNode> next = new ArrayList<TreeNode>();
for (TreeNode t : n) {
if (t != null) {
System.out.print(t.getValue());
next.add(t.getLeftChild());
next.add(t.getRightChild());
}
}
System.out.println();
if(next.size() > 0)levelOrder(next);
}
Below method returns ArrayList of ArrayList containing all nodes level by level:-
public ArrayList<ArrayList<Integer>> levelOrder(TreeNode root) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
if(root == null) return result;
Queue q1 = new LinkedList();
Queue q2 = new LinkedList();
ArrayList<Integer> list = new ArrayList<Integer>();
q1.add(root);
while(!q1.isEmpty() || !q2.isEmpty()){
while(!q1.isEmpty()){
TreeNode temp = (TreeNode)q1.poll();
list.add(temp.val);
if(temp.left != null) q2.add(temp.left);
if(temp.right != null) q2.add(temp.right);
}
if(list.size() > 0)result.add(new ArrayList<Integer>(list));
list.clear();
while(!q2.isEmpty()){
TreeNode temp = (TreeNode)q2.poll();
list.add(temp.val);
if(temp.left != null) q1.add(temp.left);
if(temp.right != null) q1.add(temp.right);
}
if(list.size() > 0)result.add(new ArrayList<Integer>(list));
list.clear();
}
return result;
}
The answer is close....the only issue I could see with it is that if a tree doesn't have a node in a particular position, you would set that pointer to null. What happens when you try to put a null pointer into the list?
Here is something I did for a recent assignment. It works flawlessly. You can use it starting from any root.
//Prints the tree in level order
public void printTree(){
printTree(root);
}
public void printTree(TreeNode tmpRoot){
//If the first node isn't null....continue on
if(tmpRoot != null){
Queue<TreeNode> currentLevel = new LinkedList<TreeNode>(); //Queue that holds the nodes on the current level
Queue<TreeNode> nextLevel = new LinkedList<TreeNode>(); //Queue the stores the nodes for the next level
int treeHeight = height(tmpRoot); //Stores the height of the current tree
int levelTotal = 0; //keeps track of the total levels printed so we don't pass the height and print a billion "null"s
//put the root on the currnt level's queue
currentLevel.add(tmpRoot);
//while there is still another level to print and we haven't gone past the tree's height
while(!currentLevel.isEmpty()&& (levelTotal< treeHeight)){
//Print the next node on the level, add its childen to the next level's queue, and dequeue the node...do this until the current level has been printed
while(!currentLevel.isEmpty()){
//Print the current value
System.out.print(currentLevel.peek().getValue()+" ");
//If there is a left pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
tmpRoot = currentLevel.peek().getLeft();
if(tmpRoot != null)
nextLevel.add(tmpRoot);
else
nextLevel.add(new TreeNode(null));
//If there is a right pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
tmpRoot = currentLevel.remove().getRight();
if(tmpRoot != null)
nextLevel.add(tmpRoot);
else
nextLevel.add(new TreeNode(null));
}//end while(!currentLevel.isEmpty())
//populate the currentLevel queue with items from the next level
while(!nextLevel.isEmpty()){
currentLevel.add(nextLevel.remove());
}
//Print a blank line to show height
System.out.println("");
//flag that we are working on the next level
levelTotal++;
}//end while(!currentLevel.isEmpty())
}//end if(tmpRoot != null)
}//end method printTree
public int height(){
return height(getRoot());
}
public int height(TreeNode tmpRoot){
if (tmpRoot == null)
return 0;
int leftHeight = height(tmpRoot.getLeft());
int rightHeight = height(tmpRoot.getRight());
if(leftHeight >= rightHeight)
return leftHeight + 1;
else
return rightHeight + 1;
}
I really like the simplicity of Anon's code; its elegant. But, sometimes elegant code doesn't always translate into code that is intuitively easy to grasp. So, here's my attempt to show a similar approach that requires Log(n) more space, but should read more naturally to those who are most familiar with depth first search (going down the length of a tree)
The following snippet of code sets nodes belonging to a particular level in a list, and arranges that list in a list that holds all the levels of the tree. Hence the List<List<BinaryNode<T>>> that you will see below. The rest should be fairly self explanatory.
public static final <T extends Comparable<T>> void printTreeInLevelOrder(
BinaryTree<T> tree) {
BinaryNode<T> root = tree.getRoot();
List<List<BinaryNode<T>>> levels = new ArrayList<List<BinaryNode<T>>>();
addNodesToLevels(root, levels, 0);
for(List<BinaryNode<T>> level: levels){
for(BinaryNode<T> node: level){
System.out.print(node+ " ");
}
System.out.println();
}
}
private static final <T extends Comparable<T>> void addNodesToLevels(
BinaryNode<T> node, List<List<BinaryNode<T>>> levels, int level) {
if(null == node){
return;
}
List<BinaryNode<T>> levelNodes;
if(levels.size() == level){
levelNodes = new ArrayList<BinaryNode<T>>();
levels.add(level, levelNodes);
}
else{
levelNodes = levels.get(level);
}
levelNodes.add(node);
addNodesToLevels(node.getLeftChild(), levels, level+1);
addNodesToLevels(node.getRightChild(), levels, level+1);
}
Following implementation uses 2 queues. Using ListBlokcingQueue here but any queue would work.
import java.util.concurrent.*;
public class Test5 {
public class Tree {
private String value;
private Tree left;
private Tree right;
public Tree(String value) {
this.value = value;
}
public void setLeft(Tree t) {
this.left = t;
}
public void setRight(Tree t) {
this.right = t;
}
public Tree getLeft() {
return this.left;
}
public Tree getRight() {
return this.right;
}
public String getValue() {
return this.value;
}
}
Tree tree = null;
public void setTree(Tree t) {
this.tree = t;
}
public void printTree() {
LinkedBlockingQueue<Tree> q = new LinkedBlockingQueue<Tree>();
q.add(this.tree);
while (true) {
LinkedBlockingQueue<Tree> subQueue = new LinkedBlockingQueue<Tree>();
while (!q.isEmpty()) {
Tree aTree = q.remove();
System.out.print(aTree.getValue() + ", ");
if (aTree.getLeft() != null) {
subQueue.add(aTree.getLeft());
}
if (aTree.getRight() != null) {
subQueue.add(aTree.getRight());
}
}
System.out.println("");
if (subQueue.isEmpty()) {
return;
} else {
q = subQueue;
}
}
}
public void testPrint() {
Tree a = new Tree("A");
a.setLeft(new Tree("B"));
a.setRight(new Tree("C"));
a.getLeft().setLeft(new Tree("D"));
a.getLeft().setRight(new Tree("E"));
a.getRight().setLeft(new Tree("F"));
a.getRight().setRight(new Tree("G"));
setTree(a);
printTree();
}
public static void main(String args[]) {
Test5 test5 = new Test5();
test5.testPrint();
}
}
public class PrintATreeLevelByLevel {
public static class Node{
int data;
public Node left;
public Node right;
public Node(int data){
this.data = data;
this.left = null;
this.right = null;
}
}
public void printATreeLevelByLevel(Node n){
Queue<Node> queue = new LinkedList<Node>();
queue.add(n);
int node = 1; //because at root
int child = 0; //initialize it with 0
while(queue.size() != 0){
Node n1 = queue.remove();
node--;
System.err.print(n1.data +" ");
if(n1.left !=null){
queue.add(n1.left);
child ++;
}
if(n1.right != null){
queue.add(n1.right);
child ++;
}
if( node == 0){
System.err.println();
node = child ;
child = 0;
}
}
}
public static void main(String[]args){
PrintATreeLevelByLevel obj = new PrintATreeLevelByLevel();
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
Node node7 = new Node(7);
Node node8 = new Node(8);
node4.left = node2;
node4.right = node6;
node2.left = node1;
// node2.right = node3;
node6.left = node5;
node6.right = node7;
node1.left = node8;
obj.printATreeLevelByLevel(node4);
}
}
Try this, using 2 Queues to keep track of the levels.
public static void printByLevel(Node root){
LinkedList<Node> curLevel = new LinkedList<Node>();
LinkedList<Node> nextLevel = curLevel;
StringBuilder sb = new StringBuilder();
curLevel.add(root);
sb.append(root.data + "\n");
while(nextLevel.size() > 0){
nextLevel = new LinkedList<Node>();
for (int i = 0; i < curLevel.size(); i++){
Node cur = curLevel.get(i);
if (cur.left != null) {
nextLevel.add(cur.left);
sb.append(cur.left.data + " ");
}
if (cur.right != null) {
nextLevel.add(cur.right);
sb.append(cur.right.data + " ");
}
}
if (nextLevel.size() > 0) {
sb.append("\n");
curLevel = nextLevel;
}
}
System.out.println(sb.toString());
}
A - Solution
I've written direct solution here. If you want the detailed answer, demo code and explanation, you can skip and check the rest headings of the answer;
public static <T> void printLevelOrder(TreeNode<T> root) {
System.out.println("Tree;");
System.out.println("*****");
// null check
if(root == null) {
System.out.printf(" Empty\n");
return;
}
MyQueue<TreeNode<T>> queue = new MyQueue<>();
queue.enqueue(root);
while(!queue.isEmpty()) {
handleLevel(queue);
}
}
// process each level
private static <T> void handleLevel(MyQueue<TreeNode<T>> queue) {
int size = queue.size();
for(int i = 0; i < size; i++) {
TreeNode<T> temp = queue.dequeue();
System.out.printf("%s ", temp.data);
queue.enqueue(temp.left);
queue.enqueue(temp.right);
}
System.out.printf("\n");
}
B - Explanation
In order to print a tree in level-order, you should process each level using a simple queue implementation. In my demo, I've written a very minimalist simple queue class called as MyQueue.
Public method printLevelOrder will take the TreeNode<T> object instance root as a parameter which stands for the root of the tree. The private method handleLevel takes the MyQueue instance as a parameter.
On each level, handleLevel method dequeues the queue as much as the size of the queue. The level restriction is controlled as this process is executed only with the size of the queue which exactly equals to the elements of that level then puts a new line character to the output.
C - TreeNode class
public class TreeNode<T> {
T data;
TreeNode<T> left;
TreeNode<T> right;
public TreeNode(T data) {
this.data = data;;
}
}
D - MyQueue class : A simple Queue Implementation
public class MyQueue<T> {
private static class Node<T> {
T data;
Node next;
public Node(T data) {
this(data, null);
}
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
}
private Node head;
private Node tail;
private int size;
public MyQueue() {
head = null;
tail = null;
}
public int size() {
return size;
}
public void enqueue(T data) {
if(data == null)
return;
if(head == null)
head = tail = new Node(data);
else {
tail.next = new Node(data);
tail = tail.next;
}
size++;
}
public T dequeue() {
if(tail != null) {
T temp = (T) head.data;
head = head.next;
size--;
return temp;
}
return null;
}
public boolean isEmpty() {
return size == 0;
}
public void printQueue() {
System.out.println("Queue: ");
if(head == null)
return;
else {
Node<T> temp = head;
while(temp != null) {
System.out.printf("%s ", temp.data);
temp = temp.next;
}
}
System.out.printf("%n");
}
}
E - DEMO : Printing Tree in Level-Order
public class LevelOrderPrintDemo {
public static void main(String[] args) {
// root level
TreeNode<Integer> root = new TreeNode<>(1);
// level 1
root.left = new TreeNode<>(2);
root.right = new TreeNode<>(3);
// level 2
root.left.left = new TreeNode<>(4);
root.right.left = new TreeNode<>(5);
root.right.right = new TreeNode<>(6);
/*
* 1 root
* / \
* 2 3 level-1
* / / \
* 4 5 6 level-2
*/
printLevelOrder(root);
}
public static <T> void printLevelOrder(TreeNode<T> root) {
System.out.println("Tree;");
System.out.println("*****");
// null check
if(root == null) {
System.out.printf(" Empty\n");
return;
}
MyQueue<TreeNode<T>> queue = new MyQueue<>();
queue.enqueue(root);
while(!queue.isEmpty()) {
handleLevel(queue);
}
}
// process each level
private static <T> void handleLevel(MyQueue<TreeNode<T>> queue) {
int size = queue.size();
for(int i = 0; i < size; i++) {
TreeNode<T> temp = queue.dequeue();
System.out.printf("%s ", temp.data);
queue.enqueue(temp.left);
queue.enqueue(temp.right);
}
System.out.printf("\n");
}
}
F - Sample Input
1 // root
/ \
2 3 // level-1
/ / \
4 5 6 // level-2
G - Sample Output
Tree;
*****
1
2 3
4 5 6
public void printAllLevels(BNode node, int h){
int i;
for(i=1;i<=h;i++){
printLevel(node,i);
System.out.println();
}
}
public void printLevel(BNode node, int level){
if (node==null)
return;
if (level==1)
System.out.print(node.value + " ");
else if (level>1){
printLevel(node.left, level-1);
printLevel(node.right, level-1);
}
}
public int height(BNode node) {
if (node == null) {
return 0;
} else {
return 1 + Math.max(height(node.left),
height(node.right));
}
}
First of all, I do not like to take credit for this solution. It's a modification of somebody's function and I tailored it to provide the solution.
I am using 3 functions here.
First I calculate the height of the tree.
I then have a function to print a particular level of the tree.
Using the height of the tree and the function to print the level of a tree, I traverse the tree and iterate and print all levels of the tree using my third function.
I hope this helps.
EDIT: The time complexity on this solution for printing all node in level order traversal will not be O(n). The reason being, each time you go down a level, you will visit the same nodes again and again.
If you are looking for a O(n) solution, i think using Queues would be a better option.
I think we can achieve this by using one queue itself. This is a java implementation using one queue only. Based on BFS...
public void BFSPrint()
{
Queue<Node> q = new LinkedList<Node>();
q.offer(root);
BFSPrint(q);
}
private void BFSPrint(Queue<Node> q)
{
if(q.isEmpty())
return;
int qLen = q.size(),i=0;
/*limiting it to q size when it is passed,
this will make it print in next lines. if we use iterator instead,
we will again have same output as question, because iterator
will end only q empties*/
while(i<qLen)
{
Node current = q.remove();
System.out.print(current.data+" ");
if(current.left!=null)
q.offer(current.left);
if(current.right!=null)
q.offer(current.right);
i++;
}
System.out.println();
BFSPrint(q);
}
the top solutions only print the children of each node together. This is wrong according to the description.
What we need is all the nodes of the same level together in the same line.
1) Apply BFS
2) Store heights of nodes to a map that will hold level - list of nodes.
3) Iterate over the map and print out the results.
See Java code below:
public void printByLevel(Node root){
Queue<Node> q = new LinkedBlockingQueue<Node>();
root.visited = true;
root.height=1;
q.add(root);
//Node height - list of nodes with same level
Map<Integer, List<Node>> buckets = new HashMap<Integer, List<Node>>();
addToBuckets(buckets, root);
while (!q.isEmpty()){
Node r = q.poll();
if (r.adjacent!=null)
for (Node n : r.adjacent){
if (!n.visited){
n.height = r.height+1; //adjust new height
addToBuckets(buckets, n);
n.visited = true;
q.add(n);
}
}
}
//iterate over buckets and print each list
printMap(buckets);
}
//helper method that adds to Buckets list
private void addToBuckets(Map<Integer, List<Node>> buckets, Node n){
List<Node> currlist = buckets.get(n.height);
if (currlist==null)
{
List<Node> list = new ArrayList<Node>();
list.add(n);
buckets.put(n.height, list);
}
else{
currlist.add(n);
}
}
//prints the Map
private void printMap(Map<Integer, List<Node>> buckets){
for (Entry<Integer, List<Node>> e : buckets.entrySet()){
for (Node n : e.getValue()){
System.out.print(n.value + " ");
}
System.out.println();
}
Simplest way to do this without using any level information implicitly assumed to be in each Node. Just append a 'null' node after each level. check for this null node to know when to print a new line:
public class BST{
private Node<T> head;
BST(){}
public void setHead(Node<T> val){head = val;}
public static void printBinaryTreebyLevels(Node<T> head){
if(head == null) return;
Queue<Node<T>> q = new LinkedList<>();//assuming you have type inference (JDK 7)
q.add(head);
q.add(null);
while(q.size() > 0){
Node n = q.poll();
if(n == null){
System.out.println();
q.add(null);
n = q.poll();
}
System.out.print(n.value+" ");
if(n.left != null) q.add(n.left);
if(n.right != null) q.add(n.right);
}
}
public static void main(String[] args){
BST b = new BST();
c = buildListedList().getHead();//assume we have access to this for the sake of the example
b.setHead(c);
printBinaryTreeByLevels();
return;
}
}
class Node<T extends Number>{
public Node left, right;
public T value;
Node(T val){value = val;}
}
This works for me. Pass an array list with rootnode when calling printLevel.
void printLevel(ArrayList<Node> n){
ArrayList<Node> next = new ArrayList<Node>();
for (Node t: n) {
System.out.print(t.value+" ");
if (t.left!= null)
next.add(t.left);
if (t.right!=null)
next.add(t.right);
}
System.out.println();
if (next.size()!=0)
printLevel(next);
}
Print Binary Tree in level order with a single Queue:
public void printBFSWithQueue() {
java.util.LinkedList<Node> ll = new LinkedList<>();
ll.addLast(root);
ll.addLast(null);
Node in = null;
StringBuilder sb = new StringBuilder();
while(!ll.isEmpty()) {
if(ll.peekFirst() == null) {
if(ll.size() == 1) {
break;
}
ll.removeFirst();
System.out.println(sb);
sb = new StringBuilder();
ll.addLast(null);
continue;
}
in = ll.pollFirst();
sb.append(in.v).append(" ");
if(in.left != null) {
ll.addLast(in.left);
}
if(in.right != null) {
ll.addLast(in.right);
}
}
}
void printTreePerLevel(Node root)
{
Queue<Node> q= new LinkedList<Node>();
q.add(root);
int currentlevel=1;
int nextlevel=0;
List<Integer> values= new ArrayList<Integer>();
while(!q.isEmpty())
{
Node node = q.remove();
currentlevel--;
values.add(node.value);
if(node.left != null)
{
q.add(node.left);
nextlevel++;
}
if(node.right != null)
{
q.add(node.right);
nextlevel++;
}
if(currentlevel==0)
{
for(Integer i:values)
{
System.out.print(i + ",");
}
System.out.println();
values.clear();
currentlevel=nextlevel;
nextlevel=0;
}
}
}
Python implementation
# Function to print level order traversal of tree
def printLevelOrder(root):
h = height(root)
for i in range(1, h+1):
printGivenLevel(root, i)
# Print nodes at a given level
def printGivenLevel(root , level):
if root is None:
return
if level == 1:
print "%d" %(root.data),
elif level > 1 :
printGivenLevel(root.left , level-1)
printGivenLevel(root.right , level-1)
""" Compute the height of a tree--the number of nodes
along the longest path from the root node down to
the farthest leaf node
"""
def height(node):
if node is None:
return 0
else :
# Compute the height of each subtree
lheight = height(node.left)
rheight = height(node.right)
#Use the larger one
if lheight > rheight :
return lheight+1
else:
return rheight+1
Queue<Node> queue = new LinkedList<>();
queue.add(root);
Node leftMost = null;
while (!queue.isEmpty()) {
Node node = queue.poll();
if (leftMost == node) {
System.out.println();
leftMost = null;
}
System.out.print(node.getData() + " ");
Node left = node.getLeft();
if (left != null) {
queue.add(left);
if (leftMost == null) {
leftMost = left;
}
}
Node right = node.getRight();
if (right != null) {
queue.add(right);
if (leftMost == null) {
leftMost = right;
}
}
}
To solve this type of question which require in-level or same-level traversal approach, one immediately can use Breath First Search or in short BFS. To implement the BFS one can use Queue. In Queue each item comes in order of insertion, so for example if a node has two children, we can insert its children into queue one after another, thus make them in order inserted. When in return polling from queue, we traverse over children as it like we go in same-level of tree. Hense I am going to use a simple implementation of an in-order traversal approach.
I build up my Tree and pass the root which points to the root.
inorderTraversal takes root and do a while-loop that peeks one node first, and fetches children and insert them back into queue. Note that nodes one by one get inserted into queue, as you see, once you fetch the children nodes, you append it to the StringBuilder to construct the final output.
In levelOrderTraversal method though, I want to print the tree in level order. So I need to do the above approach, but instead I don't poll from queue and insert its children back to queue. Because I intent to insert "next-line-character" in a loop, and if I insert the children to queue, this loop would continue inserting a new line for each node, instead I need to check do it only for a level. That's why I used a for-loop to check how many items I have in my queue.
I simply don't poll anything from queue, because I only want to know if there are any level exists.
This separation of method helps me to still keep using BFS data and when required I can print them in-order or level-order , based-on requirements of the application.
public class LevelOrderTraversal {
public static void main(String[] args) throws InterruptedException {
BinaryTreeNode node1 = new BinaryTreeNode(100);
BinaryTreeNode node2 = new BinaryTreeNode(50);
BinaryTreeNode node3 = new BinaryTreeNode(200);
node1.left = node2;
node1.right = node3;
BinaryTreeNode node4 = new BinaryTreeNode(25);
BinaryTreeNode node5 = new BinaryTreeNode(75);
node2.left = node4;
node2.right = node5;
BinaryTreeNode node6 = new BinaryTreeNode(350);
node3.right = node6;
String levelOrderTraversal = levelOrderTraversal(node1);
System.out.println(levelOrderTraversal);
String inorderTraversal = inorderTraversal(node1);
System.out.println(inorderTraversal);
}
private static String inorderTraversal(BinaryTreeNode root) {
Queue<BinaryTreeNode> queue = new LinkedList<>();
StringBuilder sb = new StringBuilder();
queue.offer(root);
BinaryTreeNode node;
while ((node = queue.poll()) != null) {
sb.append(node.data).append(",");
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return sb.toString();
}
public static String levelOrderTraversal(BinaryTreeNode root) {
Queue<BinaryTreeNode> queue = new LinkedList<>();
queue.offer(root);
StringBuilder stringBuilder = new StringBuilder();
while (!queue.isEmpty()) {
handleLevelPrinting(stringBuilder, queue);
}
return stringBuilder.toString();
}
private static void handleLevelPrinting(StringBuilder sb, Queue<BinaryTreeNode> queue) {
for (int i = 0; i < queue.size(); i++) {
BinaryTreeNode node = queue.poll();
if (node != null) {
sb.append(node.data).append("\t");
queue.offer(node.left);
queue.offer(node.right);
}
}
sb.append("\n");
}
private static class BinaryTreeNode {
int data;
BinaryTreeNode right;
BinaryTreeNode left;
public BinaryTreeNode(int data) {
this.data = data;
}
}
}
Wow. So many answers. For what it is worth, my solution goes like this:
We know the normal way to level order traversal: for each node, first the node is visited and then it’s child nodes are put in a FIFO queue. What we need to do is keep track of each level, so that all the nodes at that level are printed in one line, without a new line.
So I naturally thought of it as miaintaining a queue of queues. The main queue contains internal queues for each level. Each internal queue contains all the nodes in one level in FIFO order. When we dequeue an internal queue, we iterate through it, adding all its children to a new queue, and adding this queue to the main queue.
public static void printByLevel(Node root) {
Queue<Node> firstQ = new LinkedList<>();
firstQ.add(root);
Queue<Queue<Node>> mainQ = new LinkedList<>();
mainQ.add(firstQ);
while (!mainQ.isEmpty()) {
Queue<Node> levelQ = mainQ.remove();
Queue<Node> nextLevelQ = new LinkedList<>();
for (Node x : levelQ) {
System.out.print(x.key + " ");
if (x.left != null) nextLevelQ.add(x.left);
if (x.right != null) nextLevelQ.add(x.right);
}
if (!nextLevelQ.isEmpty()) mainQ.add(nextLevelQ);
System.out.println();
}
}
public void printAtLevel(int i){
printAtLevel(root,i);
}
private void printAtLevel(BTNode<T> n,int i){
if(n != null){
sop(n.data);
} else {
printAtLevel(n.left,i-1);
printAtLevel(n.right,i-1);
}
}
private void printAtLevel(BTNode<T> n,int i){
if(n != null){
sop(n.data);
printAtLevel(n.left,i-1);
printAtLevel(n.right,i-1);
}
}