Delete object pointer in hashtable - c++11

I have a hashtable with chaining where each node is:
struct Node
{
Object * objPtr;
Node * next;
}
When I read data from the file I create an object:
...
Object * currObj;
currObj = new Object; //Causes memory leaks (doesn't get deleted)
//Save data
currObj->setData(data);
//Insertion
insert(*currObj);
What would be the correct destructor for such a case? I have a destructor for table and destructor for Object, but currObj = new Object seems to cause leaks.
Table destructor:
//delete each chain
int i;
for (i = 0; i<capacity; i++)
{
Node * head = table[i];
Node * curr;
while (head)
{
curr = head->next;
head->next = NULL;
delete head;
head = curr;
}
}
//delete the array
delete[] table;
Object destructor
if (name)
delete[] name;
if (location)
delete[] location;
//more if with data members
UPD - Insert
void Table::insert(Object & obj_)
{
char key[200];
char curr[100];
obj_.getKeywords(key); //Get keywords for the passed obj
char * token;
token = strtok(key, "?"); //Ge the first keyword
//Loop to add nodes for each keyword from the passed object
while (token != NULL)
{
int index = calculateIndex(token); //calculate index based of the
//first keyword
//Create new node
Node * newNode = new Node;
newNode->obj = &obj_;
newNode->next = NULL;
//Link node and table
newNode->next = table[index];
table[index] = newNode;
size++;
token = strtok(NULL, "?"); //Get next keyword
}
}

You need a destructor for Node, which would need something like:
Node::~Node()
{
if ( objPtr != NULL ) {
delete objPtr;
objPtr = NULL;
}
if ( next != NULL ) {
delete next;
next = NULL;
}
}
When your table destructor calls delete head this is when the Node destructor is called. It will have a destructor by default but won't specifically free/delete the allocated object.

Related

Cannot insert and print out linked list

I'm trying to create a simple linked list class. The program runs but it gives me wrong output. And it seems like linked list doesn't insert the new nodes as I want.
class Node
{
public:
std::string name;
Node *next;
};
class ProductName
{
private:
Node *head;
public:
ProductName()
{
head = NULL;
}
void insertNode(std::string input)
{
Node *temp;
temp = new Node;
temp->name = input;
temp->next = head;
head = temp;
}
void printOut()
{
Node *p;
p = head;
while (p->next != NULL)
{
std::cout << p->name << " ";
p = p->next;
}
}
};
int main()
{
ProductName object;
object.insertNode("Hello");
object.insertNode("world!");
object.printOut();
}
I expect the output is Hello world!, but it prints out a string of random character 005C4BA0
Edit: I forgot the pointer... It's p->name not p in the print function. However, now my result is world!.
First issue: your are always inserting into the beginning by replacing the head. If you expect your nodes to appears in order of insertion you should insert them in the end:
class ProductName
{
private:
Node *head;
Node *tail; // additional member to track the last node
public:
ProductName()
: head(nullptr), tail(nullptr)
{ }
void insertNode(std::string input)
{
Node *temp = new Node{ std::move(input), nullptr };
if (tail) {
tail->next = temp;
tail = temp;
} else {
head = tail = temp;
}
}
}
Second issue: your are printing all the elements that have next which means that the last element won't be printed.
void printOut()
{
Node *p = head;
// print while p != nullptr
// this also properly handles the empty list when head == nullptr
while (p)
{
std::cout << p->name << " ";
p = p->next;
}
}

Linked list by reference or by value?

Here is the question. Say a linked list is implemented as follows (Java):
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
Consider the linked list:
1 -> 2 -> 3 -> 4
I do something like:
ListNode newHead = head;
newHead = head.next.next;
//Now newHead is pointing to (3) in the linked list.
Now I perform the magic:
newHead.val = 87
The linked list becomes:
1 -> 2 -> 87 -> 4
If I printed head and NOT newHead.
Why is this? I didn't modify anything with head but it still changed?
So you can use this:
Node Class:
public class IntNode {
int value;
IntNode next;
public IntNode(int value) {
this.value = value;
}
}
Singly Linked List Class:
/**
* A singly-linked list of integer values with fast addFirst and addLast methods
*/
public class LinkedIntList {
IntNode first;
IntNode last;
int size;
/**
* Return the integer value at position 'index'
*/
int get(int index) {
return getNode(index).value;
}
/**
* Set the integer value at position 'index' to 'value'
*/
void set(int index, int value) {
getNode(index).value = value;
}
/**
* Returns whether the list is empty (has no values)
*/
boolean isEmpty() {
return size == 0;
}
/**
* Inserts 'value' at position 0 in the list.
*/
void addFirst(int value) {
IntNode newNode = new IntNode(value);
newNode.next = first;
first = newNode;
if(last == null)
last = newNode;
size++;
}
/**
* Appends 'value' at the end of the list.
*/
void addLast(int value) {
IntNode newNode = new IntNode(value);
if(isEmpty())
first = newNode;
else
last.next = newNode;
last = newNode;
size++;
}
/**
* Removes and returns the first value of the list.
*/
int removeFirst() {
if(isEmpty()) {
System.out.println("RemoveFirst() on empty list!");
System.exit(-1);
}
int value = first.value;
if(first == last) {
// List has only one element, so just clear it
clear();
}
else {
first = first.next;
size--;
}
return value;
}
/**
* Removes and returns the last value of the list.
*/
int removeLast() {
if(isEmpty()) {
System.out.println("RemoveLast() on empty list!");
System.exit(-1);
}
int value = last.value;
if(first == last) {
// List has only one element, so just clear it
clear();
}
else {
// List has more than one element
IntNode currentNode = first;
while(currentNode.next != last)
currentNode = currentNode.next;
currentNode.next = null;
last = currentNode;
size--;
}
return value;
}
/**
* Removes all values from the list, making the list empty.
*/
void clear() {
first = last = null;
size = 0;
}
/**
* Returns a new int-array with the same contents as the list.
*/
int[] toArray() {
int[] array = new int[size];
int i = 0;
for(IntNode n = first; n != null; n = n.next, i++)
array[i] = n.value;
return array;
}
/**
* For internal use only.
*/
IntNode getNode(int index) {
if(index < 0 || index >= size) {
System.out.println("GetNode() with invalid index: " + index);
System.exit(-1);
}
IntNode current = first;
for(int i = 0; i < index; i++)
current = current.next;
return current;
}
}
See the comments in the code for description.

Insertion in BST

I was doing a problem on insertion. This is the right answer.
/*
Node is defined as
typedef struct node
{
int data;
node * left;
node * right;
}node;
*/
node * insert(node * root, int value)
{
if(root == NULL)
{
node *temp = new node();
temp->left = NULL;
temp->right = NULL;
temp->data = value;
root = temp;
return root;
}
if(value > root->data)
{
root->right = insert(root->right, value);
}
else
root->left = insert(root->left, value);
return root;
}
The only difference with the solution I made is that in the if/else statements I did not assign anything. This is my code.
Node is defined as
typedef struct node
{
int data;
node * left;
node * right;
}node;
*/
node * insert(node * root, int value)
{
if(root == NULL)
{
node *temp = new node();
temp->left = NULL;
temp->right = NULL;
temp->data = value;
root = temp;
return root;
}
if(value > root->data)
{
insert(root->right, value);
}
else
insert(root->left, value);
return root;
}
I am not sure I understand why this is necessary because basically calling this function recursively will find a right place for the node with the data value.
Then, I create node with right data and just insert it there.
I will leave a link to the problem. https://www.hackerrank.com/challenges/binary-search-tree-insertion
Thanks for help!

Traverse binary tree - no recursion, no stack, no tree modification

So for an application I am building I need to be able to traverse a binary tree without using recursion, stack or modifying the tree in any way after it's been created. My node struct is as follows:
typedef struct
{
ValueType value; //Data stored in node
int left_index; //Left child
int right_index; //Right child
int parent_index; //Parent node
}
I am storing my tree as a 1D array where the left child of each node is at index 2*i + 1, the right child is at 2*i + 2 and the parent is at [i-1]/2. If a node doesn't have a parent or child, it's associated index is -1.
The only iterative non-stack based algorithm I found was something called "Morris Traversal" as seen here: http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
However Morris Traversal modifies the tree during the traversal which I cannot do.
I am willing to add whatever information is needed to each node just as long as I can write the algorithm given the above constraints.
Is what I'm asking for even possible? And if so, how would I go about doing it? Not really sure how to even begin.
Wouldn't a "while(!done)" loop be suffcient?
What you want is a threaded binary tree. The right pointer of all leaf nodes points to the node's in-order successor.
It's easy to create such a thing, and not difficult at all to update it when you insert or delete a node. If you have control of the node structure, then this is almost certainly what you want.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode parent;
public void traverse() {
TreeNode current = this.leftMost();
while (current != null) {
System.out.println("Current at " + current.val);
current = current.inOrderNext();
}
}
public TreeNode inOrderNext() {
if (right != null) {
return right.leftMost();
} else {
TreeNode current = this;
TreeNode above = this.parent;
while (true) {
if (above == null) {
return null;
} else {
if (above.left == current) {
return above;
} else {
current = above;
above = above.parent;
}
}
}
}
}
public TreeNode leftMost() {
TreeNode result = this;
while (result.left != null) {
result = result.left;
}
return result;
}
public static void main(String args[]) {
TreeNode first = new TreeNode();
first.val = 4;
TreeNode second = new TreeNode();
second.val = 2;
second.parent = first;
first.left = second;
TreeNode third = new TreeNode();
third.val = 1;
third.parent = second;
second.left = third;
third = new TreeNode();
third.val = 3;
third.parent = second;
second.right = third;
second = new TreeNode();
second.val = 6;
second.parent = first;
first.right = second;
third = new TreeNode();
third.val = 5;
third.parent = second;
second.left = third;
third = new TreeNode();
third.val = 7;
third.parent = second;
second.right = third;
first.traverse();
}
}

I don't know what's wrong with my code - Binary Tree

I'm now making a Binary Tree in C++, using friend class.
But, something is wrong, and I cannot know what should I change
template <class Type>
class BinaryTree{
public:
BinaryTree(){
root = new BTNode<Type>();
currentNode = NULL;
}
~BinaryTree(){
delete root, currentNode;
};
void insertItem(Type data){
if(currentNode==NULL){
Item = data;
currentNode = root;
}
if(data<currentNode){
if(currentNode->Left.is_empty()){
currentNode->Left = new BTNode(data);
currentNode = root;
return;
}
else{
currentNode = currentNode->Left;
return insertItem(data);
}
}
if(data>currentNode){
if(currentNode->Right.is_empty()){
currentNode->Right = new BTNode(data);
currentNode = root;
return;
}
else{
currentNode = currentNode->Right;
return insertItem(data);
}
}
currentNode = root;
return;
}
void deleteItem(Type data){}
void is_empty(){
if (this == NULL) return 1;
else return 0;
}
void printInOrder(){
if(!(currentNode->Left).is_empty()){
currentNode = currentNode->Left;
}
}
private:
BTNode<Type>* currentNode;
BTNode<Type>* root;
};
and here the BTNode class that store the item of BinaryTree, and point the next Node:
template <class Type>
class BTNode{
public:
friend class BinaryTree<Type>;
BTNode(){}
BTNode(Type data){
Item = data;
}
~BTNode(){}
private:
Type Item;
BTNode<Type> *Left, *Right;
};
The Binary Tree class's BTNode*root point the first Node, and currentNode will point the 'current node' while doing something like insertion or merging the nodes.
But when I compile, the Compiler Error C2143 occurs in the BinaryTree class,
here:
BTNode<Type>* root;
BTNode<Type>* currentNode;
The error says that there is no toke ; in front of <
but I cannot know what is wrong
It appears as though BTNode isn't correctly defined inside the BinaryTree class. The compiler is not understanding that BTNode is a type. Make sure you're including and linking the files correctly.

Resources