I have written this delete function to delete a node in a binary search tree. The problem is it deletes the root node of the key itself. Tried Debugging but not clear whats wrong with it.
Also I don't understand why are we setting this node->m_left=deletenode(data,node->m_left);
#include "node.h"
#include <queue>
template<class T>
class bst
{
private:
Node<T>* root;
public:
bst()
{
root = nullptr;
}
~bst()
{
deletree(root);
}
Node<T>* gethead()
{
return this->root;
}
void addnode(Node<T>* node, T data)
{
if (this->root == nullptr) {
Node<T>* new_node = new Node<T>(data);
this->root = new_node;
}
else if (data > node->m_data) {
if (node->m_right != nullptr) {
addnode(node->m_right, data);
}
else {
Node<T>* new_node = new Node<T>(data);
node->m_right = new_node;
}
}
else if (data < node->m_data) {
if (node->m_left != nullptr) {
addnode(node->m_left, data);
}
else {
Node<T>* new_node = new Node<T>(data);
node->m_left = new_node;
}
}
}
void addnode(T data)
{
addnode(this->root, data);
}
Node<T>* deletenode(T data, Node<T>* node)
{
//base case
if (node == nullptr) {
return nullptr;
}
if (data < node->m_data) {
node->m_left = deletenode(data, node->m_left);
}
if (data > node->m_data) {
node->m_right = deletenode(data, node->m_right);
}
if (node->m_left == nullptr && node->m_right == nullptr) {
node = nullptr;
}
return nullptr;
}
};
Related
I want to save the number of element inside an instance of linked list class object. From the code below everytime I call addNodeFront() or addNodeBack() function, member variable len should be incremented by 1. But, when I run the code, the getLen function only return 1, while the linked list has 2 element. What should I fix from the my code?
#include <iostream>
class Node {
public:
int value;
Node* next;
Node(int value, Node* next) {
this->value = value;
this->next = next;
}
};
class LinkedList {
public:
Node* head;
Node* tail;
int len = 0;
LinkedList() {
this->head = nullptr;
this->tail = nullptr;
}
LinkedList(Node* node) {
this->head = node;
this->tail = node;
}
int getLen() {
return len;
}
void addNodeFront(Node* node) {
if(head==nullptr && tail==nullptr) {
this->head = node;
this->tail = node;
return;
}
Node* secondFirst = this->head;
this->head = node;
node->next = secondFirst;
this->len++;
}
void addNodeBack(Node* node) {
if(head==nullptr && tail==nullptr) {
this->head = node;
this->tail = node;
return;
}
this->tail->next = node;
this->tail = node;
this->len++;
}
void addNodeAfterNode(Node* prevNode, Node* node) {
if(prevNode == this->tail) {
this->tail = node;
prevNode->next = node;
return;
}
node->next = prevNode->next;
prevNode->next = node;
}
bool searchVal(int val) const {
Node* s = this->head;
while(s != nullptr) {
if(s->value == val) return true;
s = s->next;
}
return false;
}
void deleteNodeFront() {
if(this->head==this->tail) {
this->head = nullptr;
this->tail = nullptr;
return;
}
this->head = this->head->next;
}
void deleteNodeBack() {
Node* secondLast = this->head;
if(this->head==this->tail) {
this->head = nullptr;
this->tail = nullptr;
return;
}
while(secondLast->next != this->tail) {
secondLast = secondLast->next;
}
secondLast->next = nullptr;
this->tail = secondLast;
}
void deleteNodeMiddle(Node* node) {
if(node==this->head || node==this->tail) return;
Node* prevNode = this->head;
while(prevNode->next != node) {
prevNode = prevNode->next;
}
prevNode->next = prevNode->next->next;
}
void traverseLinkedList() {
Node* t = this->head;
if(head==nullptr && tail==nullptr) std::cout << "Empty Linked List";
while(t != nullptr) {
std::cout << t->value << "->";
t = t->next;
}
std::cout << "\n";
}
};
int main() {
Node node1(2,nullptr);
Node node4(4,nullptr);
LinkedList ls;
ls.addNodeFront(&node1);
ls.addNodeFront(&node4);
std::cout << ls.getLen() << std::endl;
ls.traverseLinkedList();
}
In the following function:
LinkedList(Node* node)
{
this->head = node;
this->tail = node;
}
Just add one of the following lines:
len++; //1
len = 1; //2
So the updated function:
LinkedList(Node* node)
{
this->head = node;
this->tail = node;
len++; //1
len = 1; //2
}
This is because as the head node and the tail node = node now, that means there is a node in the linked list, so we should add 1 to len.
I have implemented a function "searchkey" in order to return a node in a binary search tree if the key is present but it is returning the root node. I have added a minimal reproducible code.
While the same iterative method works. Also which would be the better way to implement this recursive or iterative.
template<class T>
class Node{
public:
T m_data;
Node<T>* m_left;
Node<T>* m_right;
Node(T data){
m_data=data;
m_left=nullptr;
m_right=nullptr;
}
};
template<class T>
class bst {
private:
Node<T>* root;
public:
bst() { root = nullptr; }
~bst() { deltree(root); }
void addnode(Node<T>* node, T data) {
if(this->root == nullptr) {
Node<T>* new_node= new Node<T>(data);
this->root = new_node;
} else if(data > node->m_data) {
if(node->m_right != nullptr) {
addnode(node->m_right, data);
} else {
Node<T>* new_node = new Node<T>(data);
node->m_right = new_node;
}
} else if(data < node->m_data) {
if(node->m_left != nullptr) {
addnode(node->m_left, data);
} else {
Node<T>* new_node = new Node<T>(data);
node->m_left = new_node;
}
}
}
void addnode(T data) { addnode(this->root, data); }
Node<T>* searchkey(T data) {
return searchkey(data,this->root);
}
Node<T>* searchkey(T data, Node<T> *node) {
if (node == nullptr) { // <-- check if node is null
return node;
} else if (data == node->m_data) {
return node;
} else if (node->m_data > data) {
searchkey(data, node->m_left);
} else if (node->m_data < data) {
searchkey(data, node->m_right);
}
return node;
}
void deltree(Node<T>* node) {
if(node) {
deltree(node->m_left);
deltree(node->m_right);
delete node;
}
};
It seems you are missing a few return statements in your search function. Also, the test for data == node->m_data isn't needed. The fallback return at the end of the function means that a match is found if you return when doing the recursive calls.
Node<T>* searchkey(T data, Node<T> *node) {
if (node == nullptr) { // <-- check if node is null
return node;
} else if (node->m_data > data) {
return searchkey(data, node->m_left);
} else if (node->m_data < data) {
return searchkey(data, node->m_right);
}
return node; // match found
}
In your original code, you called searchkey but did not return the value it returned. The function instead continued to return the same node that was given as an argument to the function, yielding the wrong result in all cases except when searching for the value stored in the root node.
An alternative view:
Node<T>* searchkey(T data, Node<T> *node) {
if (node != nullptr) {
if (node->m_data > data) {
node = searchkey(data, node->m_left);
} else if (node->m_data < data) {
node = searchkey(data, node->m_right);
} // else { here we know that node->m_data == data }
}
return node; // nullptr or the matching Node* is returned
}
Also which would be the better way to implement this recursive or iterative.
There's no definite answer. If you are likely to store many values, so the search depth becomes large, you don't want recursive calls because you may then get a stack overflow.
I was trying to use to insert into a binary tree using while loop. However it seems to have a bug: it only takes the first number and doesn't take the rest. I don't know where I made the mistake.
I've created the following code:
void BTC::Insert(int Data)
{Node *newNode = new Node;
if (head == 0)
{
head = node;
}
else
{
Node* ptr = head;
if(ptr->childs>2)
{
if (Data > ptr->data)
{
ptr->right = node;
}
else if (Data <= ptr->data)
{
ptr->left = node;
}
ptr->childs++;
}
else
{
While(ptr->childs==2)
{
if (Data > ptr->data)
{
ptr = ptr->right;
}
else if (Data <= ptr->data)
{
ptr = ptr->left;
}
}
}
}
class Node
{
public:
int data;
Node* right;
Node* left;
int childs;
Node() : right(0), left(0)
{}
Node(int data) : data(data), right(0), left(0),childs(0)
{}
}
}
I wrote this implementation of Linked list:
template<typename T> // implementation: Linked_list
class Linked_list {
private:
Node<T>* head;
Node<T>* tail;
Node<T>* current;
int size;
void init()
{
head = tail = current = new Node<T>();
size = 0;
}
Node<T>* search_previous()
{
if (current == head) {
return nullptr;
}
Node<T>* previous_node = head;
while (previous_node->next != current) {
previous_node = previous_node->next;
}
return previous_node;
}
public:
Linked_list()
{
init();
}
void clear()
{
while (head != nullptr) {
current = head;
head = head->next;
delete current;
}
init();
}
~Linked_list()
{
clear();
delete head;
}
void append(T p_element)
{
tail->next = new Node<T>(p_element);
tail = tail->next;
++size;
}
void insert(T p_element)
{
current->next = new Node<T>(p_element, current->next);
if (current == tail) {
tail = tail->next;
}
++size;
}
T remove()
{
if (current->next == nullptr) {
throw std::runtime_error("No element to remove");
}
T removed_element = current->next->element;
Node<T>* temporary_pointer = current->next;
current->next = current->next->next;
if (temporary_pointer == tail) {
tail = current;
}
delete temporary_pointer;
--size;
return removed_element;
}
T get_element()
{
if (current->next == nullptr) {
throw std::runtime_error("No element to get");
}
return current->next->element;
}
void go_to_start()
{
current = head;
}
void go_to_end()
{
current = tail;
}
void go_to_pos(int p_pos)
{
if ((p_pos < 0) || (p_pos >= size)) {
throw std::runtime_error("Index out of bounds");
}
current = head;
for (int index = 0; index < p_pos; ++index) {
current = current->next;
}
}
void next()
{
if (current != tail) {
current = current->next;
}
else {
throw std::runtime_error("There's no next positition");
}
}
void previous()
{
if (current != head) {
current = search_previous();
}
else {
throw std::runtime_error("There's no previous positition");
}
}
int get_pos()
{
int pos = 0;
Node<T>* temporary_pointer = head;
while (temporary_pointer != current) {
temporary_pointer = temporary_pointer->next;
++pos;
}
return pos;
}
int get_size()
{
return size;
}
void concat(Linked_list<T> p_list)
{
for (p_list.go_to_start(); p_list.get_pos() < p_list.get_size(); p_list.next()) {
append(p_list.get_element());
}
}
};
And here's the node:
template<typename T>
class Node {
public:
T element;
Node<T>* next;
Node(T p_element, Node<T>* p_next = nullptr)
{
element = p_element;
next = p_next;
}
Node(Node<T>* p_next = nullptr)
{
next = p_next;
}
};
The problem that I have is that when I try to use the method concat I get this message from Clang:
proofs(13417,0x7fff7bb9f000) malloc: * error for object 0x7fe10b603170: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
Abort trap: 6
What can I do for fix it?
The obvious error is this:
void concat(Linked_list<T> p_list)
You are passing a Linked_list by value. That means that a temporary copy of the linked list is created and destroyed. Since the destructor deletes the memory, it is also deleting the memory of the linked list that you are making the copy of.
Since your Linked_list class does not have a user-defined assignment operator or copy constructor to handle the members that point to dynamically allocated memory, the class cannot be safely copied (if you debugged, you should have seen that a destructor was called that you didn't expect, and that is the temporary being destroyed, thus corrupting the original object).
To prevent this, either pass by reference (not value),
void concat(Linked_list<T>& p_list)
or provide appropriate copy constructor and assignment operator.
See What is the rule of Three
I'm having a segmentation fault on the following piece of code:
main.cpp
List list;
Movie *m = new Movie();
list+m; //For testing the operator +
EDIT: Full List.cpp with all functions
#include "List.h"
using namespace std;
List::List() : head(0),tail(0),size(0) { }
List::~List()
{
Node *current = head;
while( current != 0 ) {
Node* next = current->getNext();
delete current;
current = next;
}
head = 0;
}
void List::addMovie(Movie *movie)
{
Node *curNode = new Node(movie);
if(head == NULL)
{
head = curNode;
tail = curNode;
curNode->setNext(NULL);
curNode->setPrevious(NULL);
}
else
{
curNode->setNext(NULL);
tail->setNext(curNode);
curNode->setPrevious(tail);
tail = curNode;
}
size++;
}
Node *List::first()
{
return head;
}
Node *List::last()
{
return tail;
}
void List::addMovie(List & list)
{
Node *curNode = list.first();
while(curNode)
{
addMovie(curNode->getContent());
curNode = curNode->getNext();
}
}
void List::removeMovie(Movie *movie)
{
if(size == 0) return;
bool found = false;
Node *curNode = head;
while(curNode)
{
if(curNode->getContent()->getTitle().compare(movie->getTitle()) == 0)
{
found = true;
break;
}
curNode = curNode->getNext();
}
if(!found) return;
if(curNode == head && curNode == tail)
{
head = NULL;
tail = NULL;
delete curNode;
return;
}
if(curNode == head && curNode != tail)
{
head = curNode->getNext();
curNode->getNext()->setPrevious(NULL);
delete curNode;
return;
}
if(curNode != head && curNode == tail)
{
tail = curNode->getPrevious();
curNode->getPrevious()->setNext(NULL);
delete curNode;
return;
}
if(curNode != head && curNode != tail)
{
curNode->getPrevious()->setNext(curNode->getNext());
curNode->getNext()->setPrevious(curNode->getPrevious());
delete curNode;
return;
}
size--;
}
void List::removeMovie(List &list)
{
Node *curNode = list.first();
while(curNode)
{
removeMovie(curNode->getContent());
curNode = curNode->getNext();
}
}
int List::getSize()
{
return size;
}
Movie *List::findMovie(string title)
{
Node *curNode = head;
while(curNode)
{
if(title.compare(curNode->getContent()->getTitle()) == 0) return curNode->getContent();
curNode = curNode->getNext();
}
return NULL;
}
void List::clean()
{
head = tail = NULL;
size = 0;
}
void List::operator =(const List& list)
{
head = list.head;
tail = list.tail;
size = list.size;
}
void List::operator +=(Movie *movie)
{
addMovie(movie);
}
void List::operator +=(const List& list)
{
Node *curNode = list.head;
while(curNode)
{
addMovie(curNode->getContent());
curNode = curNode->getNext();
}
}
List List::operator +(Movie *m)
{
cout << "ok" << endl;
List list = *this;
cout << "ok" << endl;
//list += m;
//Node *f = list.first();
/*while(f)
{
cout << f->getContent()->getTitle() << endl;
f = f->getNext();
}*/
//return list;
//Crashing after this
}
List List::operator +(const List& list)
{
List tmp = *this;
tmp.size++;
return tmp;
}
I get a seg fault after doing list+m, getting this while debugging:
No source available for "libstdc++-6!_ZNKSs7_M_dataEv() at 0x6fc5e26c"