I'm trying to write a function which removes an element in a linked list. I'm only having trouble with removing the head of the list. I'm able to remove any other element just fine. Here's my code (I only included the part of the function which deals with deleting the head).
template <class T>
void SinglyLinkedList<T>::remove(std::size_t i) {
//i is the element to be deleted
SinglyLinkedListNode *p=head;
// checks if the size is 0 or if the node isn't in the list
if( size()==0 && i>=size())
return;
//check if first element
if(i==0){
head=head->next;
//delete p;
}
}
My problem is with freeing the memory (I commented out the deleting here). When I comment it out like I am now it works fine (but obviously results in a memory leak) but when I uncomment it I get a segmentation fault and I'm not sure why. Any help would be appreciated.
Update: I'm sorry, I forgot to include the rest of my code: Here's the implementation:
template <class T>
class SinglyLinkedList {
// Nested class representing the nodes in the list.
class SinglyLinkedListNode {
public:
// The value stored in this node.
T value;
// The next node in the sequence.
SinglyLinkedListNode *next;
SinglyLinkedListNode(T value) :
value(value), next(nullptr) {}
SinglyLinkedListNode(T v, SinglyLinkedListNode *n) :
value(v), next(n) {}
// Return the size (length) of the linked list.
std::size_t size();
};
SinglyLinkedListNode *head;
SinglyLinkedListNode *tail;
public:
// Constructs a new SinglyLinkedList from an initializer_list of type T[].
// This is mostly for convenience, especially when testing.
SinglyLinkedList(std::initializer_list<T> items): head(nullptr), tail(nullptr)
{
if (items.size() == 0) {
return;
}
// initializer_lists were designed to be used iteratively,
// so thats what we do.
auto it = items.begin();
while (it != items.end()) {
this->push_back(*it++);
}
}
T* at(std::size_t i);
void push_back(T value);
void push_front(T value);
std::size_t size();
void remove(std::size_t i);
void insert(std::size_t i, T value);
void append(SinglyLinkedList<T> list);
So I'm creating a linked list using an initializer list and then trying to remove that element. But it's failing
SinglyLinkedList<int> lst = {100, 200, 300, 400, 500};
lst.remove(0);
Update 2: By request here's my push_back function
template <class T>
void SinglyLinkedList<T>::push_back(T value) {
//when empty
if(head==nullptr){
head= new SinglyLinkedListNode(value);
tail=head;
}
//when not empty
else{
tail->next= new SinglyLinkedListNode(value);
tail= tail->next;
}
}
Related
Linked List Class
class LinkedList
{
protected:
class Element
{
private:
Element *next;
int data;
public:
~Element() {};
Element() {};
Element(int value): next(NULL), data(value) {};
Element(Element *elem, int value): next(elem), data(value) {};
void setNext(Element *elem) {next = elem;}
void setValue(int value) {data = value;}
Element *getNext() const {return next;}
int getValue() const {return data;}
};
Element *head;
Element *tail;
public:
LinkedList(): head(NULL), tail(NULL) {};
~LinkedList() {};
Element* returnHead() {return head;};
Element* returnTail() {return tail;};
void setTail(Element *elem) {tail = elem;};
void setHead(Element *elem) {head = elem;};
// Basic functions
void print();
void printEnds();
void insertFront(int value);
void insertAfter(int afterValue, int value);
void deleteAt(int value);
void reverse();
// Question functions
void mthElemLast(int m);
void makeConnection();
bool isCyclic();
void weave();
void removeDup();
void deleteMiddle();
void partition(int value);
void palindrome();
void sumList(Element *head1, Element *head2);
void createIntersection(LinkedList *L1, LinkedList *L2, LinkedList *L3);
void getIntersection(LinkedList *L1, LinkedList *L2);
};
Insert Front Function
void LinkedList::insertFront(int value)
{
Element *newElem = new Element(value);
if (head == NULL)
{
head = newElem;
tail = newElem;
}
else
{
newElem->setNext(head);
head = newElem;
}
// delete newElem ------------> Adding this line Breaks the complete Linked List
}
Here above I have displayed my Linked List implementation using raw pointers. The problem I am facing is when I add a new element to the list in the front I create a new Element() add it to the list and make necessary adjustments to the list to make sure head is updated.
But when I delete the temporarily created element, it breaks my complete linked list and I am unable to understand why.
If I choose not to delete the temporary element, it creates memory leaks.
Help would be appreciated.
Thank You.
The is fine just as it is, without the call to delete. You say:
If I choose not to delete the temporary element
however, the object pointed to by newElem is not temporary. It is allocated on the heap and is now part of the linked list.
void LinkedList::insertFront(int value)
{
Element *newElem = new Element(value);
if (head == NULL)
{
head = newElem;
tail = newElem;
}
else
{
newElem->setNext(head);
head = newElem;
}
// No need to delete newElem, it is not a temporary object
}
I am writing a program that implements stacks as linked lists. The program complies but when I run it, it crashes. I ran the debugger and says unhandled exception when it gets inside the Pop() function and to the line "topPtr = topPtr->next". I was wondering if anyone noticed something in there that is causing this error. I attached the portion of main and the pop function that I believe i sbeing affected. thanks
template<class ItemType>
struct NodeType
{
ItemType info;
NodeType* next;
};
template<class ItemType>
class Stack
{
private:
int stacklength;
NodeType<ItemType>* topPtr; // It points to a singly-linked list
public:
void Pop(ItemType &x);
template<class ItemType>
void Stack<ItemType>::Pop(ItemType &x)
{
NodeType<ItemType>* tempPtr;
tempPtr = topPtr;
topPtr = topPtr->next;
delete tempPtr;
stacklength--;
}
int main()
{
Stack <int> IntStack;
int x;
IntStack.Pop(x);
}
First off, you don't initialize your pointers.
template<class ItemType>
struct NodeType
{
//...
NodeType() : next(nullptr) {} ///Initialize next so we can check for null
};
template<class ItemType>
class Stack
{
public:
Stack() : topPtr(nullptr), stacklength(0) { } ///initialize
//...
Then, in your Pop, you need to check for an empty stack (you can't pop if there are no elements).
template<class ItemType>
void Stack<ItemType>::Pop(ItemType &x)
{
if (!topPtr)
{
//Here, we need to decide how to handle this.
//One way would be to throw an exception,
//another way would be to change the method signature
//and return a bool.
}
///...
}
I am hoping someone can help me. I'm struggling to correctly implement the push_back and pop_front methods for a custom list I'm making. When I run my main program it freezes and windows reports it stops working. This list is being used to build a queue. I have already made my queue class and tested it with the stl list (for my assignment I need to make a custom list as well) so I am fairly certain the problem lies in my list. I think I have not coded push_back and pop_front correctly. Sorry if this is a dumb question, I tried searching for cases similar to mine but I couldn't find any. I would appreciate any help.
my node classs
template<typename T>
class cNode{
public:
T nodeVal;
cNode<T> *next;
cNode<T> *prev;
cNode<T>();
cNode<T>(const T& v, cNode<T> *n, cNode<T> *p);
};
//Methods
//defualt constructor
template<typename T>
cNode<T>::cNode(){
};
//constructor with value value next and prev
template<typename T>
cNode<T>::cNode(const T& v, cNode<T> *n=NULL, cNode<T> *p=NULL){
nodeVal=v;
next=n;
prev=p;
};
and my list, I commented out the other methods because they are not being using is the queue class
#include "cNode.h"
using namespace std;
template <typename T>
class cList{
private:
cNode<T> *frontNode;
cNode<T> *backNode;
int sizeOfList;
public:
cList();
bool empty();
// void push_front(const T& val);
void push_back(const T& val);
void pop_front();
// void pop_back();
T front();
// T back();
int size();
};
//Methods
//Constructor
template <typename T>
cList<T>::cList(){
frontNode = NULL;
backNode = NULL;
};
//Returns true if empty
template<typename T>
bool cList<T>:: empty(){
return frontNode == NULL;
};
//Adds to the back of the list
template<typename T>
void cList<T>:: push_back(const T& val){
cNode<T> *newNode;
newNode = new cNode<T>;
newNode->nodeVal=val;
//inserting in place
newNode->prev = backNode->prev;
newNode->next = backNode;
backNode->prev->next = newNode;
backNode->prev = newNode;
//update size
sizeOfList++;
};
//Removes from the front of the list
template<typename T>
void cList<T>:: pop_front(){
cNode<T> *df;
df = new cNode<T>;
df = frontNode;
df->next->prev=df->prev;
frontNode=frontNode->next;
delete df;
//update size
sizeOfList--;
};
//Returns value of of the front
template<typename T>
T cList<T>:: front(){
return frontNode->nodeVal;
};
//Returns the size of the list
template<typename T>
int cList<T>:: size(){
return sizeOfList;
};
You will find a diagram very useful here - drawing out pointers is one way to be absolutely sure what is referencing what.
That said, here are a few things that jump out:
you initialize frontNode and backNode to NULL in the constructor. What will happen when you try to dereference these NULLs during your very first push_back operation?
related: what value will frontNode have after a single push_back operation? And what value should it have?
what will happen if you try to pop an item off of an empty list?
at each end of the list, the end node should have one of prev and next be NULL or another value indicating that they point nowhere.
The main points here are that you've got a lot of NULLs being dereferenced and you're not updating everything you need to be. The way to wrap your head around the problem is to make a diagram with arrows and boxes and walk through, step by step, what needs to happen when you start with an empty list, add two or three nodes to it, and then successively pop them off.
What is spotted right after looking at your code,
you init backNode and frontNode with NULL value,
but after that in push_back you use operator-> for them,
you need allocate memory for them, before usage.
Little modification of your algorithm to make it works:
#include <cassert>
#include <cstdlib>
template <typename T> struct cNode {
T nodeVal;
cNode<T> *next;
cNode<T> *prev;
cNode<T>(const T &v = T(), cNode<T> *n = NULL, cNode<T> *p = NULL)
: nodeVal(v), next(n), prev(p) {}
};
template <typename T> class cList {
private:
cNode<T> head_;
size_t sizeOfList_;
typedef cNode<T> NT;
public:
cList() : sizeOfList_(0) {
head_.next = &head_;
head_.prev = &head_;
}
~cList() {
for (NT *p = begin(); p != end();) {
NT *next = p->next;
delete p;
p = next;
}
}
cNode<T> *cbegin() const { return head_.next; }
cNode<T> *begin() { return head_.next; }
cNode<T> *end() { return &head_; }
bool empty() const { return head_.next == &head_; }
void push_back(const T &val) {
NT *newNode = new NT(val);
NT *prev_end = end()->prev;
prev_end->next = newNode;
newNode->prev = prev_end;
newNode->next = end();
end()->prev = newNode;
++sizeOfList_;
}
void pop_front() {
if (empty())
return;
NT *next_in_list = begin()->next;
NT *prev_in_list = begin()->prev;
delete begin();
head_.next = next_in_list;
if (prev_in_list == end())
end()->prev = end();
--sizeOfList_;
}
T front() const {
assert(!empty());
return cbegin()->nodeVal;
}
size_t size() const { return sizeOfList_; }
};
int main() {
cList<int> l;
assert(l.size() == 0);
assert(l.empty());
l.push_back(10);
assert(!l.empty());
assert(l.size() == 1);
assert(l.front() == 10);
l.pop_front();
assert(l.size() == 0);
assert(l.empty());
for (int i = 5; i < 17; ++i)
l.push_back(i);
assert(l.size() == (17 - 5));
assert(l.front() == 5);
assert(!l.empty());
{
cNode<int> *p;
int i;
for (p = l.begin(), i = 5; p != l.end(); p = p->next, ++i) {
assert(p->nodeVal == i);
}
assert(i == 17);
}
l.pop_front();
assert(l.size() == (17 - 5 - 1));
assert(l.front() == 6);
assert(!l.empty());
l.pop_front();
assert(l.size() == (17 - 5 - 2));
assert(l.front() == 7);
assert(!l.empty());
}
I'm writing list and iterator classes function and I'm almost done, but I get some errors in the main file, that when I write the list remove_all function, but when I delete it there is no error anywhere, I don't know why!! Also, actually I'm not sure about my Iterator operators and the bool Iterator::is_item()
Any help is appreciated. Thanks
here is my codes:
Node.h
pragma once
namespace list_1
{
template <typename T>
struct Node
{
T data;
Node<T> *next;
// Constructor
// Postcondition:
Node<T> (T d);
};
template <typename T>
Node<T>::Node(T d)
{
}
}
Iterator.h
// Template CLASS PROVIDED: Iterator
#pragma once
#include "Node.h"
namespace list_1
{
template<typename T>
class Iterator
{
public:
Iterator<T> (Node<T> *np);
// precondition: is_item is true
// post condition n points to the next item in the list
void operator++();
// precondition:
// postcondition: returns true if there is a valid item
bool is_item();
// precondition: is_item == true
// postcondition returns data that n is pointing at
T operator* ();
private:
Node<T>* n;
};
List.h
#ifndef LIST_H
#define LIST_H
#include "Node.h"
#include "Iterator.h"
namespace list_1
{
template <typename T>
class list
{
public:
// CONSTRUCTOR
list( );
// postcondition: all nodes in the list are destroyed.
~list();
// MODIFICATION MEMBER FUNCTIONS
//postcondition: entry is added to the front of the list
void insert_front(const T& entry);
//postcondition: entry is added to the back of the list
void add_back(const T& entry);
// postcondition: all nodes with data == entry are removed from the list
void remove_all(const T& entry);
// postcondition: an iterator is created pointing to the head of the list
Iterator<T> begin(void);
// CONSTANT MEMBER FUNCTIONS
// postcondition: the size of the list is returned
int size( ) const;
private:
Node<T>* head;
};
Your syntax errors are because you are missing a couple closing curly brackets on your "else" blocks at the end of the remove_all function.
Try replacing it with this
(edit: included the suggestion about cout mentioned in the comments above)
void list<T>::remove_all(const T& entry)
{
if(head == 0)
{
std::cout<<" node cannot be delted";
}
else
{
Node<T> *curr = head;
Node<T> *trail = 0;
while( curr != 0)
{
if(curr->entry == entry)
{
break;
}
else
{
trail = curr;
curr = curr->next;
}
}
if(curr == 0)
{
std::cout<<" Node " << entry<< " is not found";
}
else
{
if ( head == curr)
{
head = head->next;
}
else
{
trail->next = curr->next;
}
} // missing this one
delete curr;
} // and this one as well
}
I have a template linkedList that I would like to dynamically create "head" pointers for...
I seem unable to get any syntax to work.. my best guess is:
linkedList<int>** ptr;
ptr = new (linkedList<int>*)[1];
But it doesn't work. I'm fairly new to C++ so any help is appreciated! Thanks!
To get a pointer, do:
T* ptr = new T;
where T is your type.
For a pointer-to-pointer, do:
T** ptrptr = new T*;
allocating the space for one pointer, which still needs to be filled like the first method:
*ptrptr = new T;
Now you got a valid pointer-to-pointer.
Is there some reason you are not using std::list? (or std::forward_list)
Check out the header files for std::list, or your nearest C++ book, or in fact
cppreference.com
Your linked list class template should have a function to return the head of the list. Look at std::list::begin() in your compiler's c++ library. The std::list::iterator type is a pointer to whatever goes in the list. (ie T*)
Though I'm not sure pointer array is really needed for your linked
list, as for just new construct, the following form will be compiled.
ptr = new (linkedList<int>*[1]);
EDIT:
This allocates pointer array:
linkedList<int>** ptr = new (linkedList<int>*[1]);
This allocates array:
linkedList<int>* ptr = new linkedList<int>[1];
This allocates one element:
linkedList<int>* ptr = new linkedList<int>;
Normally the head of a linked list would look something like:
node<int> *head = NULL;
When you want to create and insert a node, you'd use something like:
insert(node<int> *&list, int value) {
// insert new node containing `value` at head of `list`.
node<int> *temp = new node(value);
temp->next = list;
list=temp;
}
You could use this something like:
node<int> *list = NULL;
for (int i=0; i<10; i++)
insert(list, i);
Of course, unless this is for homework (or something on that order), you should stop working on this immediately, and just std::list (or boost::slist, if you want a singly-linked list).
Edit: I'm adding more detail mentioned by the OP in comment. For the moment, the avl_tree::insert does not attempt to maintain balance. It's just a plain-jane un-balanced insert, but it should be adequate to demonstrate what we care about at the moment.
template <class T>
struct linked_list {
node *head;
void insert(T v) {
node<T> *n = new node(v, head);
head = n;
}
linked_list() : head(NULL) {}
template <class T>
struct node {
node *next;
T data;
node(T const &v, node *n=NULL) : data(v), next(n) {}
};
};
template <class keyType, class dataType>
class avl_tree {
struct node {
node *left, *right;
char balance;
keyType key;
dataType data;
node(keyType const &k, dataType const &d)
: left(NULL), right(NULL), balance(0), key(k), data(d)
{ }
bool operator<(node const &other) {
return key < other.key;
}
} *root;
bool insert(node const *new_node, node *&tree) {
if (tree == NULL) {
tree = new_node;
return true;
}
else if (*new_node < *tree)
return insert(new_node, tree->left);
else if (*new_node > *tree)
return insert(new_node, tree->right);
else // new_node == tree
return false; // couldn't insert -- already present.
}
public:
avl_tree() : root(NULL) {}
void insert(keyType const &key, dataType const &data) {
node *temp = new node(key, data);
insert(temp, root);
}
};