This is not an homework. I am just totally blocked on this. I know what to do but I am having difficulty manipulating the tree. please help.
I am trying to delete and node from an BST. I am able to lookup and find the parent and store it an tree.
package com.test.binarytree;
public class BinaryTreeDelete {
private Node root;
//create null binary tree
public BinaryTreeDelete(){
root = null;
}
//delete
public void delete(int target){
root = delete(root, target);
}
public Node delete(Node node, int target){
NodeWithParent temp = lookupFindParent(root, null, target);
if( node == null){
return null;
}
else{
if( node.left == null || node.right == null) //leaf node
{
//WHAT DO I DO HERE
//temp.parent.left = null;
//temp.parent.right = null;
//return null;
}
if( node.left != null && node.right == null ) //one child only on left
{
//WHAT DO I DO HERE
}
if( node.right != null && node.left == null ) //one child only on right
{
//WHAT DO I DO HERE
}
if( node.left != null && node.right != null ) //two children
{
//WHAT DO I DO HERE
}
}
return null;
}
private NodeWithParent lookupFindParent(Node node, Node parentNode, int target){
if( node == null ){
return null;
}
if( node.data == target){
return new NodeWithParent(node, parentNode);
}
else if( node.data > target ){
parentNode = node;
return lookupFindParent(node.left, parentNode, target);
}
else{
parentNode = node;
return lookupFindParent(node.right, parentNode, target);
}
}
//insert
public void insert(int data){
root = insert(root, data);
}
public Node insert (Node node, int data){
if(node == null){
node = new Node(data);
}
else{
if( data <= node.data ){
node.left = insert(node.left, data);
}
else{
node.right = insert(node.right, data);
}
}
return node;
}
//print tree
public void printTree(){
printTree(root);
System.out.println();
}
//print tree
private void printTree(Node node) {
if (node == null) return;
// left, node itself, right
printTree(node.left);
System.out.print(node.data + " ");
printTree(node.right);
}
//node class
public static class Node{
Node left;
Node right;
int data;
Node(int newNode){
data = newNode;
left = null;
right = null;
}
}
//node class
public static class NodeWithParent{
Node current;
Node parent;
NodeWithParent(Node current, Node parent){
this.current = current;
this.parent = parent;
}
}
public static void main(String[] args) {
BinaryTreeDelete bt = new BinaryTreeDelete();
//insert with inserts - tree increases on right if inserted in order
bt = new BinaryTreeDelete();
bt.insert(5);
bt.insert(3);
bt.insert(7);
bt.insert(1);
bt.insert(4);
bt.insert(6);
bt.insert(9);
bt.printTree();
//bt.delete(3);
//bt.delete(4);
//bt.delete(6);
bt.delete(9);
//bt.delete(5);
bt.printTree();
}
}
I'm going to provide you the logic (that means you have to write the code yourself) of how to delete a node in a BST.
There are three cases.
Node to be deleted has both left and right child as null: Delete the node and make the parent point to null.
Node to be deleted has either left or right child (but not both) as null: Delete the node but make sure that the parent points to the valid child of the to-be-deleted node.
Node to be deleted has nether left child nor right child as null: In this case, you have to find the next greater element of the to-be-deleted node. This next greater element is the least element of the right subtree of the to-be-deleted node. Since this is the least element, it has at least one of its child as null. So swap the values of the to-be-deleted node with the next greater node. After you swap, delete this next greater node using points 1 and 2 (whichever is fitting to the situation). Now, why the next greater node and not any node. Because if you replace a node with its next greater node, the BST remains a BST. Try it out in an example and it will be clear.
Related
my assignment involves using recursive method. Write a program that reverses a LinkedList. This is the code i have done below, can anyone see what i am doing wrong, thank you very much!
PS: this is done in jGRASP
// Java program for reversing the linked list
class MyLinkedList {
static Node head;
static class Node {
int data;
Node next;
Node(int d) {
data = d;
next = null;
}
}
/* Function to reverse the linked list */
Node reverse(Node node) {
Node prev = null;
Node current = node;
Node next = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
node = prev;
return node;
}
// prints content of double linked list
void printList(Node node) {
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
}
public static void main(String[] args) {
MyLinkedList list = new MyLinkedList();
list.head = new Node(85);
list.head.next = new Node(15);
list.head.next.next = new Node(4);
list.head.next.next.next = new Node(20);
System.out.println("Given Linked list");
list.printList(head);
head = list.reverse(head);
System.out.println("");
System.out.println("Reversed linked list ");
list.printList(head);
}
}
debug result
Attached my code for trying to delete a node in bst.
If I want to delete node 1, when specifying tmp = del in "if (del_node->l_ == NULL)", and remove tmp, then del is removed as well, and the tree data is lost. how can I solve this issue?
Example tree:
3
/ \
1 5
\
2
all data members and functions are declared public for simplicity.
void BST::DeleteNode(int data) {
BinaryTreeNode* &del_node = BST_Search(head_, data);
if (!del_node->l_ && !del_node->r_)
{
delete del_node;
del_node = nullptr;
return;
}
if (del_node->l_ == NULL)
{
BinaryTreeNode* tmp = del_node;
del_node = del_node->r_;
tmp = nullptr;
delete tmp;
return;
}
if (del_node->r_ == NULL)
{
BinaryTreeNode* tmp = del_node;
del_node = del_node->l_;
delete tmp;
return;
}
else
{
del_node->data_ = smallestRightSubTree(del_node->r_);
}
}
int BST::smallestRightSubTree(BinaryTreeNode* rightroot)
{
// if rightroot has no more left childs
if (rightroot && !rightroot->l_)
{
int tmpVal = rightroot->data_;
BinaryTreeNode* tmp = rightroot;
rightroot = rightroot->r_;
delete tmp;
return tmpVal;
}
return smallestRightSubTree(rightroot->l_);
}
int main()
{
BST bst;
bst.BST_Insert(bst.head_, 3);
bst.BST_Insert(bst.head_, 5);
bst.BST_Insert(bst.head_, 1);
bst.BST_Insert(bst.head_, 2);
bst.DeleteNode(1);
return 0;
}
Thanks for help!
EDIT: this is how tmp and del_node look like after the line "del_node = del_node->r_)" in the condition "if(del->l = null)"
void BST::BST_Insert(BinaryTreeNode*& head, int data) {
if (head == nullptr) {
head = new BinaryTreeNode(data, nullptr, nullptr);
return;
}
if (data > head->data_) {
BST_Insert(head->r_, data);
}
else {
BST_Insert(head->l_, data);
}
}
BinaryTreeNode* BST::BST_Search(BinaryTreeNode* root, int key) {
if (root == nullptr || root->data_ == key)
return root;
if (key > root->data_)
return BST_Search(root->r_, key);
return BST_Search(root->l_, key);
}
If your BST_Search returns a BinaryTreeNode* by value, what is the reference in BinaryTreeNode* &del_node = BST_Search(head_, data); actually referencing? It allocates a new temporary and references that. You probably wanted it to reference the variable that is holding the pointer in the tree so that you can modify the tree.
Your BST_Search would have to look like this:
BinaryTreeNode*& BST::BST_Search(BinaryTreeNode*& root, int key) {
if (root == nullptr || root->data_ == key)
return root;
if (key > root->data_)
return BST_Search(root->r_, key);
return BST_Search(root->l_, key);
}
I can't check whether this actually works, because you didn't provide a self-contained compilable example. But something along these lines.
The TreeNode class is defined with only left and right child.
public class TreeNode {
public int val;
public TreeNode left, right;
public TreeNode(int val) {
this.val = val;
}
}
My code finds the next lowest node in O(n). I was wondering if it's possible to find it in lg(N) given that the node doesn't have a pointer to its parent node.
// run time O(n)
public static Integer findNextLowest(TreeNode root, int target) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || stack.size() > 0) {
while (cur != null) {
stack.push(cur);
cur = cur.right;
}
TreeNode node = stack.pop();
if (node.val < target) return node.val; // found the next lowest
cur = node.left;
}
return null;
}
private static TreeNode findNextLowest(TreeNode root, int target){
TreeNode node = root;
TreeNode res = null;
while(node != null){
while(node != null && node.val >= target){
node = node.left;
}
while(node != null && node.val < target){
res = node;
node = node.right;
}
}
return res;
}
No, because you haven't implemented a Binary Search Tree, just a Binary Tree.
A BST will constrain its values such that left.val < val < right.val, so you can do
// run time O(log(n)) if cur is balanced
public static Integer findNextLowest(TreeNode cur, int target) {
if (target < cur.val) { return cur.left != null ? findNextLowest(cur.left, target) : null; }
if (curr.right != null)
{
Integer result = findNextLowest(cur.right, target);
if (result != null) { return result; }
}
return cur.val;
}
You should use something like a R-B tree to ensure it is balanced
I am trying to delete the largest node in binary search tree, I thougth that these code below should be able to do it but for some reason it is not. Could someone help please!
public void remove() {
Node current = root;
while(true){
Node parent = current;
current = current.getRighChild();
if (current == null){
parent.setRighChild(null);
return;
}
}
}
public void remove()
{
root = deleteMax(root);
}
private Node deleteMax(Node x ) {
if (x.getRighChild() == null)
{
return x.getLeftChild();
}
x.setRighChild(deleteMax(x.getRighChild()));
return x;
}
In your code if the right node is empty you are still deleting it. Instead of deleting the current if it is the max. Try something like this:
removeLargest() {
current = getRoot();
rightNode == null;
while (root.Right){
current == root.Right
}
if (current.left()){
rotate()
}
current.delete()
}
import java.util.*;
public class MyTwoWayLinkedList<E> extends java.util.AbstractSequentialList<E> {
private Node<E> head, tail;
private int size = 0;
private List<E> list;
/** Create a default list */
public MyTwoWayLinkedList() {
list = new LinkedList<E>();
}
public MyTwoWayLinkedList(E[] objects) {
list = new LinkedList<E>();
for (int i = 0; i < objects.length; i++)
add(objects[i]);
}
/** Return the head element in the list */
public E getFirst() {
if (size == 0) {
return null;
}
else {
return head.element;
}
}
/** Return the last element in the list */
public E getLast() {
if (size == 0) {
return null;
}
else {
return tail.element;
}
}
/** Add an element to the beginning of the list */
public void addFirst(E e) {
Node<E> newNode = new Node<E>(e); // Create a new node
newNode.next = head; // link the new node with the head
head.previous = newNode; //link the old node with new head
head = newNode; // head points to the new node
size++; // Increase list size
if (tail == null) // the new node is the only node in list
tail = head;
}
/** Add an element to the end of the list */
public void addLast(E e) {
Node<E> newNode = new Node<E>(e); // Create a new for element e
if (tail == null) {
head = tail = newNode; // The new node is the only node in list
}
else {
tail.next = newNode;// Link the new with the last node
newNode.previous = tail;
tail = tail.next; // tail now points to the last node
}
size++; // Increase size
}
#Override /** Add a new element at the specified index
* in this list. The index of the head element is 0 */
public void add(int index, E e) {
if (index == 0) {
addFirst(e);
}
else if (index >= size) {
addLast(e);
}
else {
Node<E> current = tail;
for (int i = size - 1; i > index; i--) {
current = current.previous;
}
Node<E> temp = current.next;
current.next = new Node<E>(e);
(current.next).previous = current;
(current.next).next = temp;
size++;
}
}
/** Remove the head node and
* return the object that is contained in the removed node. */
public E removeFirst() {
if (size == 0) {
return null;
}
else {
Node<E> temp = head;
head = head.next;
head.previous = null;
size--;
if (head == null) {
tail = null;
}
return temp.element;
}
}
/** Remove the last node and
* return the object that is contained in the removed node. */
public E removeLast() {
if (size == 0) {
return null;
}
else if (size == 1) {
Node<E> temp = head;
head = tail = null;
size = 0;
return temp.element;
}
else {
Node<E> temp = tail;
tail = tail.previous;
tail.next = null;
size--;
return temp.element;
}
}
#Override /** Remove the element at the specified position in this
* list. Return the element that was removed from the list. */
public E remove(int index) {
if (index < 0 || index >= size) {
return null;
}
else if (index == 0) {
return removeFirst();
}
else if (index == size - 1) {
return removeLast();
}
else {
Node<E> previous = tail;
for (int i = size - 1; i > index; i--) {
previous = previous.previous;
}
Node<E> current = previous.next;
(current.next).previous = previous;
previous.next = current.next;
size--;
return current.element;
}
}
#Override /** Override toString() to return elements in the list */
public String toString() {
StringBuilder result = new StringBuilder("[");
Node<E> current = tail;
for (int i = size - 1; i > 0; i--) {
result.append(current.element);
current = current.previous;
if (current != null) {
result.append(" ,"); // Separate two elements with a comma
}
else {
result.append("["); // Insert the closing ] in the string
}
}
return result.toString();
}
#Override /** Clear the list */
public void clear() {
size = 0;
head = tail = null;
}
#Override /** Override iterator() defined in Iterable */
public ListIterator<E> listIterator() {
Node<E> current = head; // Current index
return list.listIterator();
}
#Override /** Override iterator() defined in Iterable */
public ListIterator<E> listIterator(int index) {
Node<E> current = head; // Current index
for (int i = 0; i < index; i++) { // sets current int to the parameter
current = current.next;
}
return list.listIterator();
}
#Override
public int size()
{
return size;
}
public class Node<E> {
E element;
Node<E> next;
Node<E> previous;
public Node(E element) {
this.element = element;
}
}
}
This is my original class, I will include my test case below but first let me explain my problem. I am trying to create a Doubly linked list and iterate backwards through it. However I am getting a Null Pointer Exception by just adding elements to the list. I have looked over the section of code for my addFirst method for about 2 hours now and don't see any logic errors(doesn't mean there arent any), please help!
Here is my test case as promised.
public class TestMyLinkedList {
/** Main method */
public static void main(String[] args) {
// Create a list for strings
MyTwoWayLinkedList<String> list = new MyTwoWayLinkedList<String>();
// Add elements to the list
list.add("America"); // Add it to the list
System.out.println("(1) " + list);
list.add(0, "Canada"); // Add it to the beginning of the list
System.out.println("(2) " + list);
list.add("Russia"); // Add it to the end of the list
System.out.println("(3) " + list);
list.addLast("France"); // Add it to the end of the list
System.out.println("(4) " + list);
list.add(2, "Germany"); // Add it to the list at index 2
System.out.println("(5) " + list);
list.add(5, "Norway"); // Add it to the list at index 5
System.out.println("(6) " + list);
list.add(0, "Poland"); // Same as list.addFirst("Poland")
System.out.println("(7) " + list);
// Remove elements from the list
list.remove(0); // Same as list.remove("Australia") in this case
System.out.println("(8) " + list);
list.remove(2); // Remove the element at index 2
System.out.println("(9) " + list);
list.remove(list.size() - 1); // Remove the last element
System.out.print("(10) " + list + "\n(11) ");
for (String s: list)
System.out.print(s.toUpperCase() + " ");
list.clear();
System.out.println("\nAfter clearing the list, the list size is "
+ list.size());
}
}
I'm not completely sure why you are using a LinkedList within your own implementation of a Double Linked List. In regards to your question about your addFirst method however, I have the following comments and an example of how I would approach this solution.
Head is null when you call the addFirst method.
Head has not been initialized as a new Node.
Therefore newNode.next = head; is actually newNode.next = null; There is your null pointer exception, I would imagine!
public void addFirst (E e)
{
Node<E> newNode = new Node<E>(e); //create new node
if (head != null){ //if head exists
newNode.next = head; //the new node's next link becomes the old head
}
head = newNode; //the new head is the new node
if (tail == null){ //if the tail is non existent ie head the only object in list
tail = head; //the head and the tail are the same
head.next = tail; //the 'next' value of head will be tail
}
head.prev = tail; //the previous node to head will always be tail
size++;
}
}