Hi could you please help me change this linked list into a doubly linked list ?
I would be very grateful for help :)
#include <iostream>
using namespace std;
template <class T>
struct node
{
T data;
node<T> *next;
node<T> *prev;
};
template <class T>
class Container
{
public:
//constructs a new empty Kontener
Container()
{
head = new node<T>;
head->next = head;
head->prev = head;
};
//constructs a new jp_list that is a copy of an existing list
Container(const Container<T>& rt_side)
{
head = new node<T>;
head->next = head;
head->prev = head;
node<T> *crt_ptr = rt_side.head->next;
while(crt_ptr != rt_side.head)
{
push_back(crt_ptr->data);
crt_ptr = crt_ptr->next;
}
};
//adds a data node to the front of the list
void push_front(T nw_data)
{
node<T> *temp = new node<T>;
temp->data = nw_data;
temp->next = head->next;
head->next->prev = temp;
temp->prev = head;
head->next = temp;
};
//adds a data node to the end of the list
void push_back(T nw_data)
{
node<T> *temp = new node<T>;
temp->data = nw_data;
head->prev->next = temp;
temp->prev = head->prev;
temp->next = head;
head->prev = temp;
};
//removes the first node and returns the data
T pop_front()
{
node<T> *temp = head->next;
T temp_data = head->next->data;
head->next = temp->next;
temp->next->prev = head;
delete temp;
return temp_data;
};
//removes the last node and returns the data
T pop_back()
{
node<T> *temp = head->prev;
T temp_data = head->prev->data;
head->prev = temp->prev;
temp->prev->next = head;
delete temp;
return temp_data;
};
//resturns the size of the list
int size()
{
int size = 0;
node<T> *crt_ptr; //pointer to current node
crt_ptr = head->next;
while(crt_ptr != head)
{
size += 1;
crt_ptr = crt_ptr->next; //advance to the next node then loop
}
return size;
};
//prints out all the data in the list
void display_all()
{
node<T> *crt_ptr = head->next;
for(int i = 0; crt_ptr != head; i++)
{
cout << "Node " << (i+1) << ": " << crt_ptr->data << endl;
crt_ptr = crt_ptr->next;
}
};
Container& operator= (const Container& rt_side)
{
if(this == &rt_side)
return *this;
node<T> *crt_ptr = head->next;
//empty this list so the rt_side can be coppied in
while(crt_ptr != head)
{
crt_ptr = crt_ptr->next;
pop_front();
}
crt_ptr = rt_side.head->next;
while(crt_ptr != rt_side.head)
{
push_back(crt_ptr->data);
crt_ptr = crt_ptr->next;
}
return *this;
};
virtual ~Container()
{
int list_size = size();
for(int i = 0; i < list_size; i++)
{
pop_front();
}
delete head;
};
private:
node<T> *head;
};
#endif
I am just a beginner so please help me :)
The tail would always point to the last item that was inserted into the list.
However, I do not think that having a tail pointer makes it necessarily a doubly linked list. A singly linked list can also have a tail pointer (however useless it might be). I believe you are asking to create a double ended doubly linked list.
You already have the next and previous pointers to enable the double link. All you have to do, is when you push something into the list, you need to make the tail pointer point to the node that is being added. Similarly, when removing a node, you need the tail pointer to point to tail's previous BEFORE deleting the last node.
* UPDATE *
Here is some code. I am assuming a double ended doubly linked list with two ends.
void push_front(T nw_data)
{
node<T> *temp = new node<T>;
temp->data = nw_data;
if(head == nullptr)
{
head = temp;
tail = temp;
}
else if(head == tail)
{
head->next = temp;
temp->prev = head;
tail = temp;
}
else
{
temp->next = head->next;
head->next->prev = temp;
temp->prev = head;
head->next = temp;
}
};
//adds a data node to the end of the list
void push_back(T nw_data)
{
node<T> *temp = new node<T>;
temp->data = nw_data;
if(head == nullptr)
{
head = temp;
tail = temp;
}
else if(head == tail)
{
head->next = temp;
temp->prev = head;
tail = temp;
}
else
{
temp->prev = tail;
tail->next = temp;
tail = temp;
}
};
T pop_back()
{
node<T> *temp = tail;
T temp_data = tail->data;
tail = tail->prev;
tail->next = null;
delete temp;
return temp_data;
};
* UPDATE * Copy Constructor
In your copy constructor, if the push_back sets the tail, then all you need to do is to push_back the nodes like you are doing. head->next = head and head->prev = head makes the linked list cyclical.
Container(const Container<T>& rt_side)
{
this->head = rt_side.head;
node<T> * crt_ptr = rt_side.head->next;
while (crt_ptr != null)
{
push_back(crt_ptr->data);
crt_ptr = crt_ptr->next;
}
};
Related
I'm writing a class of linked list, I feel that for the member function that used to delete specific element might cause the memory leak. The code is below.
struct node
{
int data;
node *next;
};
class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}
void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;
if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}
void DelElem(int locat)
{
int j{1};
node* tmp = new node;
if (locat == 1)
{
tmp = head->next;
head = tmp;
delete tmp;
}
else
{
node* n = head;
while (j < locat - 1)
{
n = n->next;
j++;
}
tmp = n->next;
n->next = tmp->next;
delete tmp;
}
}
For function 'DelElem', I firstly created a pointer tmp by new operator. However, I assign different address for it which means I lost the original one at the initialization.
How can I fix this problem?
There are few issues with your instance of code, I have corrected that:-
As pointed by others, you are not required to use `new` keyword to declare a pointer.
When one tries to delete the first node of the linked list, then according to your code, it will delete the second node, because of the following
tmp = head->next;
head = tmp;
delete tmp;
Here, tmp is initially pointing to second node,because head->next refers to 2nd node. So instead of that, it should have been like this:-
tmp = head;
head = head->next;
delete tmp;
Now, tmp will point to 1st node, in second line, head will point to 2nd node, and then the first node, pointed by tmp gets deleted.
Here is the corrected version of code:-
struct node {
int data;
node* next;
};
class linked_list {
private:
node *head, *tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}
void add_node(int n)
{
node* tmp = new node;
tmp->data = n;
tmp->next = NULL;
if (head == NULL) {
head = tmp;
tail = tmp;
}
else {
tail->next = tmp;
tail = tail->next;
}
}
void DelElem(int locat)
{
int j{ 1 };
node* tmp;
if (locat == 1) {
tmp = head;
head = head->next;
delete tmp;
}
else {
node* n = head;
while (j < (locat - 1)) {
n = n->next;
j++;
}
tmp = n->next;
n->next = tmp->next;
cout << tmp->data;
delete tmp;
}
}
};
#include <iostream>
#include <stdlib.h>
using namespace std;
struct Node{
int data;
Node* next;
Node* prev;
};
Node* head;
void display(){
Node* temp = head;
while(temp!=NULL){
cout<<temp->data<<" ";
temp = temp->next;
}
cout<<endl;
}
void insert(int value){
Node* temp = (Node*)malloc(sizeof(Node));
temp->data = value;
temp->prev = NULL;
temp->next = NULL;
if(head==NULL){
head = temp;
}
else{
Node* t = head;
while(t->next!=NULL){
t = t->next;
}
t->next = temp;
temp->next = NULL;
temp->prev = t;
}
}
void insertAtFirst(int value){
Node* temp = (Node*)malloc(sizeof(Node));
temp->data = value;
temp->prev = NULL;
temp->next = head;
head->prev = temp;
head = temp;
}
void sortedInsert(int value){
Node* curr = head;
while(curr->next!=NULL)
curr = curr->next;
Node* temp = (Node*)malloc(sizeof(Node));
temp->data = value;
if(head==NULL || temp->data < head->data){
temp->prev = NULL;
temp->next = head;
head->prev = temp;
head = temp;
}
else if(head->next!= NULL && temp->data >= head->data){
Node* pred = head;
while(temp->data > pred->data){
pred = pred->next;
}
pred->prev->next = temp;
temp->prev = pred->prev;
temp->next = pred;
pred->prev = temp;
}
else if(curr->next==NULL){
curr->next = temp;
temp->prev = curr;
temp->next = NULL;
}
}
int main()
{
insert(10);
insert(20);
insert(25);
insert(35);
insertAtFirst(1);
insertAtFirst(29);
sortedInsert(30);
sortedInsert(40);
//1 10 20 25 29 30 35 40
display();
return 0;
}
I think I have implemented the doubly linked list probably. However, the problem I am facing is that when I try to input a node that has a greater data than the existing data of the last node, it doesn't save. There is probably something wrong with the logic I have employed - looked up some previous answers but failed to fix the problem.
As you try to insert sorted elements in your linked list, you cannot avoid using pointer of pointers in order to keep trace of the current and previous element.
Consider the following function:
void sortedInsert(int value)
{
Node **curr = nullptr;
Node **prev = nullptr;
int cc = 0;
for (curr = &head;
*curr && ((cc = ((*curr)->data < value)));
prev=curr, curr = &(*curr)->next);
Node* newElem = (Node*)malloc(sizeof(Node));
newElem->data = value;
newElem->next = *curr;
newElem->prev = *prev;
*curr = newElem;
}
Try to draw a diagram of your elements with their address...it helps a lot to understand how pointers and super-pointers work.
Z.
Fairly new to implementing stacks and was looking for some possible feedback. My code gives the correct output, but I know this doesn't always mean it is working as it is suppose to. I chose to take the approach that implementing a stack using a linked list was essentially the same as your regular linked list implementation except that all the operations are done on the end of the list. I was not too sure if this approach was correct, but it followed the first in last out approach, and has the same complexity for access & search (O(n)) and insertion and deletion O(1). Such as pop() would just be deleting a node from the end of the linked list, and push() would just be appending a node to the end of the linked list. I have pasted my code below with comments within them explaining what I am doing or trying to do (if it is incorrect).
#include <iostream>
struct Node{
int data;
Node* next;
};
bool isEmpty(Node** stack){
if(*stack == NULL){
return true;
}
return false;
}
void push(Node** stack, int data){
Node* new_node = new Node();
new_node->data = data;
new_node->next=NULL;
// stack similar to "head"
if(isEmpty(&(*stack))){
*stack = new_node;
return;
}
Node* temp = *stack;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = new_node;
}
void pop(Node** stack){
// checking if stack is empty
if(isEmpty(&(*stack))){
std::cout<<"Stack underflow"<<std::endl;
return;
}
Node* deleteMe = *stack;
// if at the first element in the stack
if(deleteMe->next == NULL){
*stack = (*stack)->next;
delete deleteMe;
return;
}
while(deleteMe->next != NULL){
if(deleteMe->next->next==NULL){
// saving the current location of the node before the node which I want to delete
Node* temp = deleteMe;
// updating the deleteMe pointer to the node which I want to delete
deleteMe = deleteMe->next;
// setting the current node before the deleteMe node to point to NULL instead of the node which I want to delete
temp->next = NULL;
delete deleteMe;
return;
}
deleteMe = deleteMe->next;
}
}
void printList(Node* stack){
Node* temp = stack;
while(temp!=NULL){
std::cout<<temp->data<<" ";
temp = temp->next;
}
std::cout<<"\n";
}
int top(Node** stack){
Node* top = *stack;
while(top->next!=NULL){
top = top->next;
}
return top->data;
}
int main(){
Node* stack = NULL;
// testing implementation below
push(&stack,10);
std::cout<<top(&stack)<<std::endl;
push(&stack,20);
std::cout<<top(&stack)<<std::endl;
push(&stack,30);
push(&stack,40);
printList(stack);
std::cout<<top(&stack)<<std::endl;
pop(&stack);
pop(&stack);
push(&stack,40);
std::cout<<top(&stack)<<std::endl;
}
Your implementation looks fine, one additional improvement can be done by maintaining head and tail pointer so that you can remove 1st and last element as needed. Here is example c++ code.
#include <iostream>
using namespace std;
template <class T> class node {
public:
node<T>() {}
~node<T>() {}
T data;
node<T> *next;
};
template <class T> class linked_list {
public:
linked_list<T>() : head(NULL), tail(NULL) {}
~linked_list<T>() {}
virtual void addFirst(T data) {
node<T> *n = new node<T>();
if (head == NULL)
tail = n;
n->data = data;
n->next = head;
head = n;
size++;
}
virtual void addLast(T data) {
node<T> *n = new node<T>();
n->data = data;
if (tail == NULL) {
head = n;
} else {
tail->next = n;
}
n->next = NULL;
tail = n;
}
virtual void reverse() {
if ((head == NULL) || (head->next == NULL))
return;
node<T> *current = head;
node<T> *previous = NULL;
node<T> *next = current->next;
tail = current;
while (current) {
next = current->next;
current->next = previous;
previous = current;
current = next;
}
head = previous;
}
virtual void print_nodes() {
node<T> *temp = head;
while (temp) {
cout << temp->data << " " << flush;
temp = temp->next;
}
cout << endl;
}
virtual void removeLast() {
node<T> *temp = head;
while (temp->next->next) {
temp = temp->next;
}
tail = temp;
delete temp->next;
temp->next = NULL;
}
virtual void removeFirst() {
node<T> *temp = head;
head = head->next;
delete temp;
}
private:
node<T> *head;
node<T> *tail;
uint32_t size;
};
int main(int argc, const char *argv[]) {
linked_list<uint32_t> *llist = new linked_list<uint32_t>();
llist->addLast(1);
llist->addFirst(5);
llist->addFirst(10);
llist->addFirst(15);
llist->addFirst(20);
llist->addLast(30);
llist->addFirst(40);
llist->print_nodes();
llist->reverse();
llist->print_nodes();
llist->removeLast();
llist->print_nodes();
llist->removeFirst();
llist->print_nodes();
return 0;
}
I am creating a generic single linked list for the first time. I have this error that states:
No viable overloaded '='
So I decided to overload the '=' operator to make it work but I am still receiving the same error and I am not sure why. Here is my header file:
#ifndef LinkedList_hpp
#define LinkedList_hpp
#include <iostream>
template<class T>
struct Node {
T data;
Node<T>* next;
};
template<class T>
class SingleLinkedList {
private:
Node<T>* head, tail;
SingleLinkedList & operator=(const SingleLinkedList &rhs) {
head = rhs.head;
tail = rhs.tail;
return *this;
}
public:
SingleLinkedList() {
head = nullptr;
tail = nullptr;
}
void createNode(const T& theData) {
Node<T>* temp = new Node<T>;
temp->data = theData;
temp->next = nullptr;
if(head == nullptr) {
head = temp;
tail = temp;
temp = nullptr;
}
else {
tail->next = temp;
tail = temp;
}
}
void display() {
Node<T>* temp = new Node<T>;
temp = head;
while(temp != nullptr) {
std::cout << temp->data << "\t";
temp = temp->next;
}
}
void insert_start(const T& theData) {
Node<T>* temp = new Node<T>;
temp->data = theData;
temp->next = head;
head = temp;
}
void insert_position(int pos, const T& theData) {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
Node<T>* temp = new Node<T>;
temp = head;
for(int i = 1; i < pos; i++) {
previous = current;
current = current->next;
}
temp->data = theData;
previous->next = temp;
temp->next = current;
}
void delete_first() {
Node<T>* temp = new Node<T>;
temp = head;
head = head->next;
delete temp;
}
void delete_last() {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
current = head;
while(current->next != nullptr) {
previous = current;
current = current->next;
}
tail = previous;
previous->next = nullptr;
delete current;
}
void delete_position(int pos) {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
current = head;
for(int i = 1; i < pos; i++) {
previous = current;
current = current->next;
}
previous->next = current->next;
}
Node<T>* search(Node<T>* head, const T& target) {
}
};
Should I create an assignment operator in the struct Node? I am not sure what else to try.
Here is where I am getting an error:
I'm trying to create a linked list that can append/delete/display items. I got the header and the test complete, and it seems to have worked. It successfully appended, deleted, and displayed the results. However, immediately after the results were displayed, I get a runtime pop-up saying "Debug Assertion Failed! Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)"
So I did some debugging, and obviously it's a memory leak (or at least I'm pretty sure it is). I swear my destructor was written correctly. My test works, the linked list works (plus it's member functions) works, so what am I doing wrong?
Here's my class declarations, default constructor, and destructor
template <typename T>
class Node
{
public:
T Value;
Node<T> *next;
Node(T nodeValue)
{
value = nodeValue;
next = NULL;
}
};
template <typename T>
class LinkedList
{
private:
Node<T> *head;
public:
LinkedList()
{ head = NULL; }
~LinkedList()
{
Node<T> *temp;
Node<T> *nextNode;
temp = head;
while (temp != NULL)
{
nextNode = temp->next;
delete temp;
temp = nextNode;
}
}
}
And here's the rest of the Linked List (even though it works but in case you ask)
void appendNode(T newValue)
{
Node<T> *newNode;
Node<T> *temp;
newNode = new Node<T>(newValue);
if (!head)
head = newNode;
else
{
temp = head;
while (temp->next)
temp = temp->next;
temp->next = newNode;
}
}
void deleteNode(T searchValue)
{
Node<T> *temp;
Node<T> *prev = NULL;
if (!head)
return;
if (head->value == searchValue)
{
temp = head->next;
delete head;
head = temp;
}
else
{
temp = head;
while (temp != NULL && temp->value != searchValue)
{
prev = temp;
temp = temp->next;
}
if (temp)
{
prev->next = temp->next;
delete temp;
}
}
}
void displayList() const
{
Node<T> *temp;
temp = head;
while (temp)
{
cout << temp->value << " ";
temp = temp->next;
}
}