How can I remove all the evens in a linked list in java? Other similar questions did not help me. I have a possible solution, but it seems too complicated. I'm not sure it even works.
public class Node {
public int value;
public Node next;
public Node (int val) {
value = val;
}
public Node removeNode (Node root) {
if (root == null || (root.next == null && isOdd(root.value))) {
return null;
}
Node deep = root;
while (deep.next != null) {
deep = deep.next;
}
if (isOdd(deep.value)) {
for (Node x = root; x != null; x = x.next) {
if (isOdd(x.next.value)) {
x.next = x.next.next;
}
}
} else {
for (Node x = root; x.next != null; x = x.next) {
if (isOdd(x.next.value)) {
x.next = x.next.next;
}
}
}
if (isOdd(root.value)) {
root = root.next;
}
return root;
}
public boolean isOdd (int val) {
return (val % 2 == 1);
}
How can I improve this solution?
First of all: The remove method should be in your LinkedList class, not in the Node class itself!
After that it's quite easy to just remove the the even ones:
public class LinkedList {
private Node root;
public void removeEvens() {
if (root == null) return;
// removing all even nodes after the root
Node prev = root;
while (prev.next != null) {
if (isEven(prev.next))
prev.next = prev.next.next; // next is even: delete it
else
prev = prev.next; // next is not even: proceed
}
// delete root if it's even
if (isEven(root))
root = root.next;
}
private boolean isEven(Node node) {
return node.value % 2 == 0;
}
}
You can add an element before root node. In that case you don't have to write code for check root node.
public class Node {
public int value;
public Node next;
public Node(){}
public Node (int val) {
value = val;
}
public static Node removeEvens (Node root) {
Node head = new Node();
head.next = root;
for (Node node = head; node.next!=null; node=node.next)
if (isEven(node.next))
node.next = node.next.next;
return head.next;
}
public static boolean isEven(Node node) {
return node.value % 2 == 0;
}
}
Related
I created my own Linked List using nodes, and I have few methods to do.
Methods in main:
//List<Person> females = peopleFromWarsaw.getWithFilter(p -> p.getName().endsWith("a"));
// Dont know how to implements this methods.
// ObjectContainer.removeIf(p -> p.getAge() > 50);
// peopleFromWarsaw.storeToFile("youngPeopleFromWarsaw.txt",
// p -> p.getAge() < 30, p -> p.getName() + ";" + p.getAge() + ";" + p.getCity());
At the begging i made a linked list and tried to print elements from list but doesnt work.
At first it looks like it doesn't have a method toString but class Person has toString. I guess the program takes the node but I want to print object.
Maybe u can see what is the problem with code, basically nodes and methods in Object Container are fine.
Secondly i have a problem with implementing methods in main (getWithFilter,removeIf and storeToFile)
No matter how I write method in ObjectContainer, always intelij tells me that cannot use lambda and underline p.getName (p -> p.getName().endsWith("a"));
In class Person i have getters and setters with fields name,age.
Maybe someone could explain how properly write this methods ?
public class ObjectContainer<T> {
private Node head;
private Node tail;
private final Predicate<T> predicate;
public ObjectContainer(Predicate<T> predicate) {
this.predicate = predicate;
}
static class Node {
private Object object;
private Node next;
Node(Object object) {
this.object = object;
}
}
public void add(T object) {
if (!predicate.test(object)) {
throw new IllegalArgumentException("Element can not be added");
}
Node newNode = new Node(object);
if (head == null) {
head = newNode;
tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
}
public int size() {
int count = 0;
Node current = head;
while (current != null) {
count++;
current = current.next;
}
return count;
}
public void push(T new_data) {
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
public void insertAfter(Node prev_node, T new_data) {
if (prev_node == null) {
System.out.println("The given previous node cannot be null");
return;
}
Node new_node = new Node(new_data);
new_node.next = prev_node.next;
prev_node.next = new_node;
}
public void append(T new_data) {
Node new_node = new Node(new_data);
if (head == null) {
head = new Node(new_data);
return;
}
new_node.next = null;
Node last = head;
while (last.next != null)
last = last.next;
last.next = new_node;
return;
}
public void printList() {
Node tnode = head;
while (tnode != null) {
tnode = tnode.next;
System.out.println(tnode);
}
}
}
Probably you don't want to print the node, but the object contained within. Also, you want to print the first object, too. That is
public void printList() {
Node tnode = head;
while (tnode != null) {
System.out.println(tnode.object);
tnode = tnode.next;
}
}
I have been debugging this for hours and I cannot see any reason why my search method cannot find anything. and my toString only ever returns the first node, then again, nothing. can someone help me?
While debugging, I can confirm that the order of the list is correct, I can switch around the addLast and addFirst and will always return what should be the first element, but otherwise, I do not know. the first is always sored in head.info and during debugging I see that but then the prev and next are still null.
thanks in advance!
public class DoubleLinkedList {
private DoubleNode head;
public DoubleLinkedList() {
head = null;
}
public class DoubleNode {
int info;
DoubleNode prev;
DoubleNode next;
public DoubleNode(int key) {
info = key;
prev = next = null;
}
}
public DoubleNode search(int key) {
DoubleNode current = this.head;
while (current != null && current.info != key) {
current = current.next;
}
return current;
}
public void addFirst(int key) {
this.head = new DoubleNode(key);
}
public void addLast(int key) {
DoubleNode node = new DoubleNode(key);
DoubleNode current;
if (head == null) {
this.head = node;
} else {
current = this.head;
while (current.next != null) {
current = current.next;
current.next = node;
node.prev = current;
}
}
}
public int delete(int key) {
DoubleNode current, sent;
current = search( key );
if (current != null) {
sent = delete( current );
return sent.info;
} else {
return -1;
}
}
private DoubleNode delete(DoubleNode node) {
if (node.prev != null) {
(node.prev).next = node.next;
} else {
this.head = node.next;
}
if (node.next != null) {
(node.next).prev = node.prev;
}
return node;
}
public String toString() {
String string = "";
while (head != null) {
string += head.info + " ";
head = head.next;
}
return string;
}
public static void main(String[] args) {
DoubleLinkedList test = new DoubleLinkedList();
test.addLast( 3 );
test.addLast( 5 );
test.addFirst( 7 );
System.out.println(test);
System.out.println( "Search: " + test.search( 1 ) );
}
}
The results come out as:
7,
Search: null
Your addFirst method isn't currently setting the new head's next property. It needs to be something more like this:
public void addFirst(int key) {
DoubleNode node = new DoubleNode(key);
node.next = this.head;
this.head = node;
}
Take a look at this example:
public class Test {
public static void main(String[] args) {
List list = new List();
list.addNode("1");
list.addNode("2");
list.addNode("3");
System.out.println(list);// not implemented
}
}
class List {
Node head;
Node tail;
class Node {
Node next;
Node previous;
String info;
public Node(String info) {
this.info = info;
}
}
void addNode(String info) {
Node node = new Node(info);
if (head == null) {
head = tail = node;
} else if(tail == head){
Node next = new Node(info);
tail.next = next;
head = next;
head.previous = tail;
} else{
Node next = new Node(info);
Node current = head;
head.next =next;
head = next;
head.previous = current;
}
}
}
At the moment I'm trying to create an AVLTree to store data and and then print the data via in-order traversal. However I'm currently stuck trying to fix a StackOverflowError that seems to be occuring when I call my height() method.
I'm pretty sure the StackOverflowError is resulting from a bad recursion call on my height() method but I don't know why that bad recursion call is happening.
public class AVLTree<K,V> implements AVLTreeI<K,V> {
class Node<K,V> {
K key;
V value;
Node<K,V> leftChild;
Node<K,V> rightChild;
Node<K,V> parent;
public Node(K key, V value) {
this.key = key;
this.value = value;
leftChild = rightChild = parent = null;
}
}
private Node<K,V> root;
private int currentSize;
public AVLTree() {
root = null;
currentSize = 0;
}
public void add(K key, V value) {
Node<K,V> node = new Node<K,V>(key, value);
if (root == null) {
root = node;
currentSize++;
}
add(root, node);
}
private void add(Node<K,V> parent, Node<K,V> newNode) {
if (((Comparable<K>)newNode.key).compareTo(parent.key) > 0) {
if (parent.rightChild == null) {
parent.rightChild = newNode;
newNode.parent = parent;
currentSize++;
}
else
add(parent.rightChild, newNode);
}
else {
if (parent.leftChild == null) {
parent.leftChild = newNode;
newNode.parent = parent;
currentSize++;
}
else
add(parent.leftChild, newNode);
}
checkBalance(newNode);
}
public int height() {
if (root == null)
return 0;
return height(root) - 1;
}
private int height(Node<K,V> node) {
if (node == null)
return 0;
int leftHeight = height(node.leftChild) + 1;
int rightHeight = height(node.rightChild) + 1;
if (leftHeight > rightHeight)
return leftHeight;
return rightHeight;
}
public void checkBalance(Node<K,V> node) {
if ((height(node.leftChild) - height(node.rightChild) > 1) ||
(height(node.leftChild) - height(node.rightChild) < -1)) {
rotate(node);
}
if (node.parent == null)
return;
checkBalance(node.parent);
}
public void rotate (Node<K,V> node) {
if (height(node.leftChild) - height(node.rightChild) > 1) {
if (height(node.leftChild.leftChild) >
height(node.leftChild.rightChild)) {
node = rightRotate(node);
}
else
node = leftRightRotate(node);
}
else {
if (height(node.rightChild.rightChild) >
height(node.rightChild.leftChild)) {
node = leftRotate(node);
}
else
node = rightLeftRotate(node);
}
if (node.parent == null)
root = node;
}
public Node<K,V> leftRotate(Node<K,V> node) {
Node<K,V> tmp = node.rightChild;
node.rightChild = tmp.leftChild;
tmp.leftChild = node;
node.rightChild = tmp.parent;
tmp.parent = node.parent;
tmp.leftChild.parent = tmp;
return tmp;
}
public Node<K,V> rightRotate(Node<K,V> node) {
Node<K,V> tmp = node.leftChild;
node.leftChild = tmp.rightChild;
tmp.rightChild = node;
node.leftChild = tmp.parent;
tmp.parent = node.parent;
tmp.rightChild.parent = tmp;
return tmp;
}
public Node<K,V> rightLeftRotate(Node<K,V> node) {
node.rightChild = rightRotate(node.rightChild);
return leftRotate(node);
}
public Node<K,V> leftRightRotate(Node<K,V> node) {
node.leftChild = leftRotate(node.leftChild);
return rightRotate(node);
}
Your problem is not the height() method (it seems reasonable), but the add() method:
public void add(K key, V value) {
Node<K,V> node = new Node<K,V>(key, value);
if (root == null) {
root = node;
currentSize++;
}
add(root, node);
}
You create a new Node and if the tree is empty you set the node as root node.
But then you go on and add the same node also as a subnode of the root node - which means that the node gets added as left subnode of itself. And it is this that leads to the infinite recursion.
Instead, your add method should add a node either as root node or as a subnode of the root node:
public void add(K key, V value) {
Node<K,V> node = new Node<K,V>(key, value);
if (root == null) {
root = node;
currentSize++;
} else {
add(root, node);
}
}
I've got a class Node
class Node{
int val;
Node parent;
Node left;
Node right;
public Node (int val){
this.val = val;
}
}
And I have a few methods:
public class Tree{
public Node root = null;
void insertNodeSorted(Node x, Node tree) {
if (x.val < tree.val) {
if (tree.left == null) {
tree.left = x;
}
else
insertNodeSorted(x, tree.left);
}
else {
if (tree.right == null) {
tree.right = x;
}
else
insertNodeSorted(x, tree.right);
}
} // end insertNodeSorted
void deleteNodeSorted(Node x) {
if (root == null)
return;
else
root = deleteNodeSorted(x, root);
}
Node deleteNodeSorted(Node x, Node tree) {
if (x.val < tree.val)
tree.left = deleteNodeSorted(x, tree.left);
else if (x.val > tree.val)
tree.right = deleteNodeSorted(x, tree.right);
else
tree = replaceNodeSorted(tree);
return tree;
} // end deleteNodeSorted
// Additional Method
Node replaceNodeSorted(Node tree) {
if (tree.right == null)
tree = tree.left;
else if (tree.left == null)
tree = tree.right;
else
tree.right = findReplacement(tree.right, tree);
return tree;
} // end replaceNodeSorted
Node findReplacement(Node tree, Node replace) {
if (tree.left != null)
tree.left = findReplacement(tree.left, replace);
else {
replace.val = tree.val;
tree = tree.right;
}
return tree;
} // end findReplacement
And I'd like to compile the Tree, but I don't know what I exactly I need to write in the main method.
public static void main(String[] args){
Tree t = new Tree();
t.insertNodeSorted();
What do I have to write in the brackets in order to print the Tree? (I know I still have to add System.out.println(val); in the methods..)
You defined a variable holding the root node, so it is not necessary to pass the parameter tree for the method insertNodeSorted. You can use always the root node.
Add a method taking only one parameter.
public void insertNodeSorted(Node x) {
if (root == null) {
root = x;
return;
}
insertNodeSorted(x, root);
}
Define the other method with two parameters as private
private void insertNodeSorted(Node x, Node tree) {
...
}
Now you can insert elements as follow:
Tree t = new Tree();
t.insertNodeSorted(new Node(1));
t.insertNodeSorted(new Node(134));
t.insertNodeSorted(new Node(13));
t.insertNodeSorted(new Node(4));
...
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
So in simpletons, I am creating my own AVLTree data structure. Now when i add a new node into my tree, it seems to add fine.
EDIT: It doesnt seem to take into account my duplicates (nor add them to the original node's list by key).
But when i print the rootNode to see if it exists it doesn't exist. I can't figure out what the problem is with my add method.
Here is my AVLTree class:
package cw.util;
import java.util.ArrayList;
import java.util.Comparator;
public class AVLTree<K, V>
{
public class Node {
private K key;
private ArrayList<V> valuesList;
private Node left, right;
private int height;
public Node(K key, ArrayList<V> valuesList) {
this.key = key;
this.valuesList = valuesList;
this.height = 0;
}
public Node(V value) {
}
public void addToNode(V value) {
valuesList.add(value);
}
public K getKey() {
return key;
}
public ArrayList<V> getValues() {
return valuesList;
}
public Node getLeftChild() {
return left;
}
public Node getRightChild() {
return right;
}
public int getHeight() {
return height;
}
public Node getChildNodeFromSide(String side) {
switch(side) {
default: return null;
case "left": return left;
case "right": return right;
}
}
}
private Node rootNode;
private Comparator<K> comparator;
//Unused
public AVLTree() {
}
public AVLTree(Comparator<K> comparator) {
this.comparator = comparator;
this.rootNode = null;
}
public V insert(K key, V value) {
Node n = insert(key, value, rootNode);
if(n != null) {
for(V v : n.getValues())
System.out.println(v.toString());
System.out.println();
return value;
} else {
return null;
}
}
public Node insert(K key, V value, Node node) {
ArrayList<V> values = new ArrayList<V>();
values.add(value);
if(node == null)
node = new Node(key, values);
else if(comparator.compare(key, node.key) < 0) {
node.left = insert(key, value, node.left);
if(height(node.left) - height(node.right) == 2) {
if(comparator.compare(key, node.left.key) < 0)
node = rotateWithLeftChild(node);
else
node = doubleRotateWithLeft(node);
}
} else if(comparator.compare(key, node.key) > 0) {
node.right = insert(key, value, node.right);
if(height(node.right) - height(node.left) == 2) {
if(comparator.compare(key, node.right.key) > 0)
node = rotateWithRightChild(node);
else
node = doubleRotateWithRight(node);
}
} else node.getValues().add(value);
node.height = Math.max(height(node.left), height(node.right)) + 1;
return node;
}
public Node search(K key) {
return search(key, rootNode);
}
public Node search(K key, Node node) {
boolean isFound = false;
while((node != null) && !isFound) {
K nodeKey = node.getKey();
if(comparator.compare(key, nodeKey) < 0)
node = node.getLeftChild();
else if(comparator.compare(key, nodeKey) > 0)
node = node.getRightChild();
else {
isFound = true;
}
node = search(key, node);
}
if(isFound) return node;
else return null;
}
//Custom Methods
public boolean isEmpty() {
return rootNode == null;
}
private int height(Node n) {
return n == null ? -1 : n.getHeight();
}
private Node rotateWithLeftChild(Node node2) {
Node node1 = node2.left;
node2.left = node1.right;
node1.right = node2;
node2.height = Math.max(height(node2.left), height(node2.right)) + 1;
node1.height = Math.max(height(node1.left), node2.getHeight()) + 1;
return node1;
}
private Node rotateWithRightChild(Node node1) {
Node node2 = node1.right;
node1.right = node2.left;
node2.left = node1;
node1.height = Math.max(height(node1.left), height(node1.right)) + 1;
node2.height = Math.max(height(node2.left), node1.getHeight()) + 1;
return node2;
}
private Node doubleRotateWithLeft(Node node) {
node.left = rotateWithRightChild(node.left);
return rotateWithLeftChild(node);
}
private Node doubleRotateWithRight(Node node) {
node.right = rotateWithLeftChild(node.right);
return rotateWithRightChild(node);
}
}
Here is how I test the class:
package cw.avl;
import cw.util.AVLTree;
public class AVLTest
{
public static void main(String[] args) {
AVLTree<String, Integer> tree = new AVLTree<String, Integer>(String.CASE_INSENSITIVE_ORDER);
for (int i=1; i <= 10;i++) {
String s = "S" + i;
int x = i;
tree.insert(s, x);
tree.insert(s, x);
}
}
}
Well, you don't seem to ever assign to rootNode, so it starts null and remains so. In fact, your methods create nodes and return them:
if(node == null)
node = new Node(key, values);
...
return node
But you don't use the returned node.
Edit: longer explanation:
When you call from the other function like this: Node n = insert(key, value, rootNode); you are basically saying: Node n = insert(key, value, null);. On the receiving end, here:
public Node insert(K key, V value, Node node) { ,
you are creating a new variable called node with initial value null. Then you replace that value when you do:
node = new Node(key, values);
That value is for the node variable in the insert(K,V,N) method, in no way is rootNode retroactively updated. You could just do so right there:
if(node == null) {
node = new Node(key, values);
rootNode = node;
}