How to store an array of LinkedList heads in C++? - data-structures

Given a binary tree, I'm trying to make a linked list of elements for each depth. That makes D lists for depth D. I'm doing a non-recursive implementation and using level order traversal in my C++ code. Though I don't see any error while compilation, I know that my heads are not storing in the array of pointers. Please have a look at my code. Any help or suggestion would be great since I'm new to data structures. Thanks!
#include <iostream>
#include <queue>
using namespace std;
struct BTnode
{
int data;
BTnode* left;
BTnode* right;
};
struct LLnode
{
int data;
LLnode* next;
};
BTnode* newNode(int data)
{
BTnode* node = new BTnode;
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
void MakeLL(LLnode* &head, int data)
{
LLnode* temp = new LLnode;
temp->data = data;
if (head == NULL)
{
head = temp;
temp->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
LLnode** LevelElementsLinkedlist(BTnode* &root)
{
if (root == NULL)
return NULL;
queue<BTnode*>nodeQ;
nodeQ.push(root);
int level = 0;
LLnode **arr;
while(1)
{
int count = nodeQ.size();
if (count == 0)
break;
LLnode* head = NULL;
arr[level] = head;
level ++;
while (count > 0)
{
BTnode* node = nodeQ.front();
MakeLL(head,node->data);
nodeQ.pop();
if (node->left)
nodeQ.push(node->left);
if (node->right)
nodeQ.push(node->right);
count--;
}
}
return arr;
}
void printLL(LLnode* head)
{
if (head == NULL)
return;
LLnode* temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
}
int main()
{
BTnode* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(40);
root->left->right = newNode(5);
root->right->left = newNode(60);
root->right->right = newNode(7);
root->left->left->left = newNode(8);
root->left->left->right = newNode(9);
root->left->right->left = newNode(10);
root->left->right->right = newNode(11);
root->right->left->left = newNode(12);
root->right->left->right = newNode(13);
root->right->right->left = newNode(14);
root->right->right->right = newNode(15);
LLnode** arr = LevelElementsLinkedlist(root);
int n = sizeof(arr)/sizeof(arr[0]);
cout << n;
for (int i = 0; i < n; i++)
{
printLL(arr[i]);
cout << endl;
}
cout << endl;
return 0;
}

There are a few problem that I noticed in your code.
In the function LevelElementsLinkedlist, you are not allocating space for arr. It should be LLnode *arr = new LLnode *[100].
Check the line where you have written the following:
LLnode* head = NULL;
arr[level] = head;
You are assigning NULL to head and then adding it to the array. Your whole array will contain nothing else but NULLs.
Try fixing these issues and try executing your code again.

Related

Delete smallest node in a linkedlist

I have an assignment to delete the smallest node in a linked list. I wrote the function minelement for this, but it doesn't delete the smallest node. It just deletes all nodes... why does that happen?
My code:
#include <iostream>
#include <string>
using namespace std;
class linkedlist {
private:
struct node {
int item;
node* next;
};
node* first;
node* last;
int count;
public:
linkedlist()
{
first = last = NULL;
count = 0;
}
bool isempty()
{
return (first == NULL);
}
void insertnode(int value) {
node* newNode = new node;
newNode->item = value;
if (count == 0)
{
first = last = newNode;
newNode->next = NULL;
}
else
{
newNode->next = first;
first = newNode;
}
count++;
}
void insertfromLast(int value)
{
node* newNODE = new node;
newNODE->item = value;
if (count == 0)
{
first = last = newNODE;
newNODE->next = NULL;
}
else
{
last->next = newNODE;
newNODE->next = NULL;
last = newNODE;
}
}
void removefirst()
{
node* curr = first;
if (count == 0)
{
cout << "empty list cannot be deleted" << endl;
}
else if (count == 1)
{
delete first;
last = first = NULL;
count--;
}
else
{
first = first->next;
delete curr;
count--;
}
}
void removelast()
{
if (count == 0)
{
cout << "empty list cannot be deleted" << endl;
}
else if (count == 1)
{
delete first;
last = first = NULL;
count--;
}
else
{
node* curr = first->next;
node* prev = first;
while (curr != last)
{
prev = curr;
curr = curr->next;
}
delete curr;
prev->next = NULL;
last = prev;
count--;
}
}
void position(int pos)
{
node* curr = first;
if (count == 0)
{
cout << "Element's positon cannot be found" << endl;
}
else
{
if (pos > count||pos<0)
{
cout << "Out of range so we can't return info of kth element" << endl;
}
else
{
for (int i = 0; i < pos; i++)
{
curr = curr->next;
}
cout << curr->item;
}
count++;
}
}
void remove_existed_element(int element)
{
if (count == 0)
{
cout << "Empty list cannot be deleted" << endl;
}
node* curr = first->next;
node* prev = first;
if (first->item == element)
{
curr = first;
first = first->next;
delete curr;
count--;
}
else
{
while (curr != NULL)
{
if (curr->item == element)
{
break;
}
prev = curr;
curr = curr->next;
}
if (curr == NULL)
{
cout << "Element cannot be found to delete" << endl;
}
else
{
prev->next = curr->next;
delete curr;
count--;
}
}
}
void maxelement()
{
int max = first->item;
node* curr = first->next;
while (curr != NULL)
{
if (curr->item > max)
{
max = curr->item;
}
curr = curr->next;
}
cout << "MAX ELEMENT IS " << max << endl;
count++;
}
void minelement()
{
int min = first->item;
node* curr = first->next;
node* prev = first;
if (isempty())
{
cout << "Empty linked list cannot be deleted" << endl;
}
else if (count == 1)
{
delete first;
count--;
}
else
{
while (curr != NULL)
{
if (min > curr->item)
{
min = curr->item;
}
curr = curr->next;
}
while (curr->item != min) //10 6 5 2//
{
prev = curr;
curr=curr->next;
}
prev->next = curr->next;// prev->next=NULL;
delete (curr);
count--;
}
}
void print()
{
node* curr = first;
while (curr != NULL)
{
cout << curr->item << " ";
curr = curr->next;
}
cout << endl;
}
};
int main()
{
linkedlist l;
l.insertnode(2);
l.insertnode(5);
l.insertnode(6);
l.insertnode(10);
l.minelement();
l.print();
}
Some of the issues:
curr is dereferenced when it is certain that it is NULL:
while (curr != NULL)
{
if (min > curr->item)
{
min = curr->item;
}
curr = curr->next;
}
while (curr->item != min) // <-- curr will be NULL!!!
the function starts with dereferencing first, which is not safe: when the list is empty this will be an invalid reference. So the first thing to do is to check whether the list is empty.
When count == 1, the first member is not set to NULL, ...etc. But since you already have that logic elsewhere, just call removefirst()
It is a pity that you have 2 loops: one to find what is the minimum value, and another to find the node that precedes that minimum value. You should do both in one loop.
Here is the updated function:
void minelement()
{
if (isempty()) // Check this first!
{
cout << "Empty linked list cannot be deleted" << endl;
}
else if (count == 1)
{
removefirst(); // Use your method
}
else
{
// Only access first members when it is safe:
int min = first->item;
node* beforemin = NULL;
node* curr = first->next;
node* prev = first;
while (curr != NULL)
{
if (min > curr->item)
{
min = curr->item;
// Remember where you found it
beforemin = prev;
}
prev = curr; // keep updated
curr = curr->next;
}
if (beforemin == NULL) {
removefirst();
} else if (beforemin->next == NULL) {
removelast();
} else {
curr = beforemin->next;
beforemin->next = curr->next;
delete (curr);
count--;
}
}
}
Unrelated to your question, but you should obviously also update the maxelement function. The position function has some issues too, like:
count++; should not occur there.
pos > count should really be pos >= count, because you seem to use position 0 for the head node, and so the last node has position count-1.
Finally, try to avoid code duplication. There are too many places where you delete and update count. Try to centralise such common code in a method and call it where needed.

my code creates undifined behaviour when I remove cout<<endl;

this is my header
/**
* Title: Trees
* Description: NgramTree class to count and store ngrams in a given string
*/
#ifndef NGRAMTREE_H
#define NGRAMTREE_H
#include <iostream>
#include <string>
using namespace std;
typedef string TreeItemType;
struct TreeNode {
TreeItemType item;
TreeNode *leftChildPtr, *rightChildPtr;
int count;
};
// NgramTree.h
class NgramTree {
public:
NgramTree();
~NgramTree();
void addNgram( string ngram );
int getTotalNgramCount();
bool isComplete();
bool isFull();
bool isFull(TreeNode* curr);
void generateTree( string fileName, int n );
ostream& print_recursive( ostream &out, TreeNode *curr );
ostream& print( ostream &out );
private:
// ...
TreeNode *root;
friend ostream& operator<<( ostream& out, NgramTree &tree );
void destroyTree(TreeNode *& treePtr);
int getTotalNgramCount(TreeNode *node);
};
#endif
this is the cpp
/**
* Title: Trees
* Assignment: 2
* Description: implementation of NgramTree class
*/
#include "NgramTree.h"
//empty constructor
NgramTree::NgramTree():root(NULL){};
//destructor
NgramTree::~NgramTree(){
destroyTree(root);
}
bool NgramTree::isFull(){
return isFull(root);
}
bool NgramTree::isFull(TreeNode* curr){
if(curr->leftChildPtr != NULL && curr->rightChildPtr != NULL ){
return isFull(curr->leftChildPtr) && isFull(curr->rightChildPtr);
}
// on leaf node
else if( curr->leftChildPtr == NULL && curr->rightChildPtr == NULL ){
return true;
}
else if( curr == NULL ){
return true;
}
//ever other condition
return false;
}
void NgramTree::addNgram( string ngram ){
if(root == NULL){
cout<<endl;
TreeNode *tmp = new TreeNode;
tmp->item = ngram;
tmp->count = 1;
root = tmp;
return;
}
for( TreeNode *curr = root; curr != NULL; ){
if( ngram.compare(curr->item) == 0){
curr->count++;
return;
}
else if( ngram.compare(curr->item) < 0 ){
// if the node is leaf or node has just right child we have to add ngram to the leftChildPtr
if( curr->leftChildPtr == NULL ){
TreeNode *tmp = new TreeNode;
tmp->item = ngram;
tmp->count = 1;
tmp->leftChildPtr = NULL;
tmp->rightChildPtr = NULL;
curr->leftChildPtr = tmp;
return;
}
else{
curr = curr->leftChildPtr;
}
}
else if( ngram.compare(curr->item) > 0 ){
// if the node is leaf or node has just left child we have to add ngram to //the leftChildPtr
if( curr->rightChildPtr == NULL ){
TreeNode *tmp = new TreeNode;
tmp->item = ngram;
tmp->count = 1;
tmp->leftChildPtr = NULL;
tmp->rightChildPtr = NULL;
curr->rightChildPtr = tmp;
return;
}
else{
curr = curr->rightChildPtr;
}
}
}
}
void NgramTree::generateTree( string fileName, int n ){
string s;
s = "";
//first loop to find words
for(size_t i = 0; i < fileName.length(); ++i){
if(fileName[i] != ' '){
s += fileName[i];
}
//after a word end there is a ' '
if(fileName[i] == ' ' || i == fileName.length()-1 ){
for(size_t j = 0; j <= s.length() - n; ++j ){
addNgram( s.substr(j,n) );
}
s = "";
}
}
}
int NgramTree::getTotalNgramCount(){
return getTotalNgramCount(root);
}
int NgramTree::getTotalNgramCount(TreeNode *node){
if( node != NULL){
// total count is node->count + count(leftSubTree) + count(rightSubTree)
return node->count
+ getTotalNgramCount(node->leftChildPtr)
+ getTotalNgramCount(node->rightChildPtr);
}
else{
return 0;
}
}
void NgramTree::destroyTree(TreeNode *&treePtr){
if (treePtr != NULL){
destroyTree(treePtr->leftChildPtr);
destroyTree(treePtr->rightChildPtr);
delete treePtr;
treePtr = NULL;
}
}
ostream& NgramTree::print_recursive( ostream &out, TreeNode *curr ) {
if( curr == NULL ) return out;
out<<endl;
out<<"item= "<<curr->item<<", frequency= "<<curr->count;
print_recursive(out, curr->leftChildPtr);
return print_recursive(out, curr->rightChildPtr);
}
ostream& NgramTree::print( ostream &out ){
TreeNode *tmp = root;
return print_recursive(out, tmp);
}
ostream& operator<<( ostream& out, NgramTree &tree ){
return tree.print(out);
}
int main(){
NgramTree t;
string s1 = "berkan naber";
int n1 = 3;
t.generateTree(s1, n1);
cout<<t.getTotalNgramCount();
cout<<t<<endl;
return 0;
}
when I remove cout<<endl from void NgramTree::addNgram( string ngram ) method I get undifined behaviour. I removed it and added in different line and it worked again. I also added it before the if statement and it worked again. What cout<<endl might change in method is it releated to function call stack may be? I am not even sure that the problem comes from this method? I am open to solutions that offering somthing to put instead of cout<<endl; which doesn't affect the terminal output unlike cout<<endl.

Reversing singly linked list using recursion

I have written code to reverse singly linked list using recursion. It is working fine on lists of length less than or equal to 174725. But on lists of length greater than 174725 it gives a segmentation fault(Segmentation fault: 11) while reversing it via reverse() call. Can someone please explain this to me ?
#include <iostream>
using namespace std;
class Node
{
public:
int val;
Node *next;
};
class Sll
{
public:
Node *head;
private:
void reverse(Node *node);
public:
Sll();
void insert_front(int key);
void reverse();
void print();
};
void Sll::reverse(Node *node)
{
if (node == NULL) return;
Node *rest = node->next;
if (rest == NULL)
{
head = node;
return;
}
reverse(rest);
rest->next = node;
node->next = NULL;
return;
}
Sll::Sll()
{
head = NULL;
}
void Sll::insert_front(int key)
{
Node *newnode = new Node;
newnode->val = key;
newnode->next = head;
head = newnode;
return;
}
void Sll::print()
{
Node *temp = head;
while (temp)
{
temp = temp->next;
}
cout << endl;
return;
}
void Sll::reverse()
{
reverse(head);
return;
}
int main()
{
Sll newList = Sll();
int n;
cin >> n;
for (int i = 0; i < n; i++) newList.insert_front(i + 1);
newList.reverse();
// newList.print();
return 0;
}
List reversing function must be tail-recursive, otherwise it is going to overflow the stack when recursing over a long list, like you observe. Also, it needs to be compiled with optimisations enabled or with -foptimize-sibling-calls gcc option.
Tail-recursive version:
Node* reverse(Node* n, Node* prev = nullptr) {
if(!n)
return prev;
Node* next = n->next;
n->next = prev;
return reverse(next, n);
}
An iterative list reversion can be more easily inlined though and it does not require any optimization options:
inline Node* reverse(Node* n) {
Node* prev = nullptr;
while(n) {
Node* next = n->next;
n->next = prev;
prev = n;
n = next;
}
return prev;
}

Print a singly linked list from start and end one by one

Print a singly linked list from start and end one by one.
Example:
1->2->3->4->5->6
Expected Output:
1,6,2,5,3,4
Checked!
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int data;
struct Node *next;
};
Node* newNode(int key)
{
Node *temp = new Node;
temp->data = key;
temp->next = NULL;
return temp;
}
void reverselist(Node **head)
{
Node *prev = NULL, *curr = *head, *next;
while (curr)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
*head = prev;
}
void printlist(Node *head)
{
while (head != NULL)
{
cout << head->data << " ";
if(head->next) cout << "-> ";
head = head->next;
}
cout << endl;
}
void arrange(Node **head)
{
Node *slow = *head, *fast = slow->next;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
Node *head1 = *head;
Node *head2 = slow->next;
slow->next = NULL;
reverselist(&head2);
*head = newNode(0);
Node *curr = *head;
while (head1 || head2)
{
if (head1)
{
curr->next = head1;
curr = curr->next;
head1 = head1->next;
}
if (head2)
{
curr->next = head2;
curr = curr->next;
head2 = head2->next;
}
}
*head = (*head)->next;
}
int main()
{
Node *head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3);
head->next->next->next = newNode(4);
head->next->next->next->next = newNode(5);
head->next->next->next->next->next = newNode(6);
printlist(head);
arrange(&head);
printlist(head);
return 0;
}

Find the Error or memory leak

I was writing LinkedList Program in C++
Here is the Code. Find the Error and Memory Leak or anything else.
I want to write a perfect code.
#ifndef LEARN_REVERSELINKLIST_H
#define LEARN_REVERSELINKLIST_H
#include <string>
#include <utility>
#include <iostream>
#include <boost/assert.hpp>
class ReverseLinkList {
private:
struct Node {
std::string string;
Node *Previous{};
Node *Next{};
};
Node *head;
Node *tail;
int count;
public:
ReverseLinkList();
~ReverseLinkList();
void insert(std::string string);
void insertAt(std::string string, int position);
void iterator() const;
void reverseIterator() const;
void remove(const std::string &string);
void removeAt(int position);
int size() const;
Node *getHead() const;
Node *getTail() const;
};
#endif //LEARN_REVERSELINKLIST_H
and Here is the CC File
#include "ReverseLinkList.h"
ReverseLinkList::~ReverseLinkList() {
if (count != 0) {
Node *temp = head;
while (temp != tail->Next) {
delete temp->Previous;
temp = temp->Next;
}
tail = nullptr;
head = nullptr;
}
}
ReverseLinkList::ReverseLinkList()
: head(nullptr), tail(nullptr), count(0) {
}
void ReverseLinkList::iterator() const {
BOOST_ASSERT_MSG(count != 0, "List is empty");
Node *temp;
temp = head;
while (temp != tail->Next) {
std::cout << temp->string << std::endl;
temp = temp->Next;
}
}
void ReverseLinkList::reverseIterator() const {
BOOST_ASSERT_MSG(count != 0, "List is empty");
Node *temp;
temp = tail;
while (temp != head->Previous) {
std::cout << temp->string << std::endl;
temp = temp->Previous;
}
}
void ReverseLinkList::insert(std::string string) {
auto *newNode = new Node;
newNode->string = std::move(string);
count++;
if (head == nullptr && tail == nullptr) {
newNode->Previous = nullptr;
newNode->Next = nullptr;
head = newNode;
tail = newNode;
} else {
tail->Next = newNode;
newNode->Next = nullptr;
newNode->Previous = tail;
tail = newNode;
}
}
int ReverseLinkList::size() const {
return count;
}
void ReverseLinkList::remove(const std::string &string) {
BOOST_ASSERT_MSG(count != 0, "List is empty");
if (count == 1) {
if (head->string == string) {
delete head;
head = nullptr;
tail = nullptr;
}
count--;
return;
}
if (head->string == string) {
Node *temp;
temp = head->Next;
delete head;
head = temp;
head->Previous = nullptr;
count--;
return;
}
if (tail->string == string) {
Node *temp;
temp = tail->Previous;
delete tail;
tail = temp;
temp->Next = nullptr;
count--;
return;
}
Node *temp;
temp = head;
bool verbose = true;
while (temp != tail->Next) {
if (temp->string == string) {
verbose = false;
break;
}
temp = temp->Next;
}
if (verbose) {
std::cerr << "Node not present" << std::endl;
return;
}
Node *previous, *next;
previous = temp->Previous;
next = temp->Next;
delete temp;
previous->Next = next;
next->Previous = previous;
count--;
}
void ReverseLinkList::insertAt(std::string string, int position) {
if (position > count)
return;
if (position == 0) {
if (head == nullptr) {
insert(string);
return;
}
auto *newNode = new Node;
newNode->string = string;
newNode->Previous = nullptr;
head->Previous = newNode;
newNode->Next = head;
head = newNode;
count++;
return;
}
if (position == count - 1) {
insert(string);
return;
}
Node *temp;
temp = head;
while (position != 0) {
temp = temp->Next;
position--;
}
Node *next;
next = temp->Next;
auto *newNode = new Node;
newNode->string = string;
temp->Next = newNode;
newNode->Previous = temp;
newNode->Next = next;
next->Previous = newNode;
count++;
}
ReverseLinkList::Node *ReverseLinkList::getHead() const {
return head;
}
ReverseLinkList::Node *ReverseLinkList::getTail() const {
return tail;
}
void ReverseLinkList::removeAt(int position) {
BOOST_ASSERT_MSG(count != 0, "List is empty");
if (position > count)
return;
Node *temp;
if (count == 1) {
delete head;
head = nullptr;
tail = nullptr;
count--;
return;
}
if (position == 0) {
temp = head->Next;
delete head;
head = temp;
head->Previous = nullptr;
count--;
return;
}
if (position == count) {
temp = tail->Previous;
delete tail;
tail = temp;
tail->Next = nullptr;
count--;
return;
}
temp = head;
while (position != 0) {
temp = temp->Next;
position--;
}
Node *previous;
Node *next;
previous = temp->Previous;
next = temp->Next;
delete temp;
previous->Next = next;
next->Previous = previous;
count--;
}
I would like to have some suggestion how can I write better code and Implement it. If you have some functions you would like to add please do post.
My next move is to make this code using templates

Resources