I was wondering how to create a linked list with a remove(int num) and removeback(int num)? using the same format as provided in prepend?
#include "ll.h"
LL::LL()
{
head = NULL;
}
void LL::prepend(int num)
{
node* newNode = new node;
newNode->val = val;
newNode->next = NULL;
if (head == NULL)
{
head = newNode;
}
else
{
newNode->next = head;
head = newNode;
newNode = NULL;
}
}
void LL::remove(int num)
{
}
void LL:removeBack (int num)
{
}
I think remove and removeBack would be the same function? Correct? Also how do I pass that value back
I assume that remove(int num) removes the first node that has the same value as num. I'll leave removeBack as an exercise for you :).
void LL:remove(int num) {
if (!head) {
return;
}
else if (head->val == num) {
node* temp = head;
head = head->next;
delete temp;
return;
}
node* second = head;
node* first = head->next;
// Iterate until we find the target, or reach the end
while (first && first->val != num) {
second = first;
first = first->next;
}
// At this point, first points to either nullptr or the target
if (first) {
second->next = first->next;
delete first;
}
}
What about searching for the node and then deleting the node with that value?
void LL:remove (int num){
ListNode *nodePtr, *previousNode;
if (!head) {
return;
}
else if (head->value == num)
{
nodePtr = head->next;
delete head;
head = nodePtr;
}
else
{
nodePtr=head;
while (nodePtr != NULL && nodePtr->value !=num){
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
previousNode->next = nodePtr->next;
delete nodePtr;
}
}
Related
I want to use subscript operator overloading in linklist but everytime it give me Segmentation fault (core dumped) ERROR! MY TASK IS : (Overload [] operator. Use for loop in main to display it.) I ALSO PROVIDING THE TASK LINK BELOW
//task link
[LINK OF TASK] https://anonymfile.com/r1XKK/dsa-a3.pdf
//MY CODE IS :
#include <iostream>
using namespace std;
class LinkedList
{
private:
class Node
{
public:
int data;
Node * next;
Node(int data)
{
this->data = data;
this->next = NULL;
}
};
public:
Node *head;
LinkedList(){
head = NULL;
}
//Write a copy constructor. Also copy must be deep.
LinkedList(LinkedList& S)
{
head = S.head;
}
//Overload [] operator. Use for loop in main to display it.
void operator[](int i) {
head->data = i;
}
void InsertAtEnd(int data){
if (head == NULL)
{
head = new Node(data);
return;
}
Node * temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = new Node(data);
}
void Insert(int d1, int d2)//Add the node of data d2 after the node with data d1. If d2 is not available add it to the end.
{
if (head == NULL)
{
Node * n = new Node(d2);
n->next = head;
head = n;
return;
}
Node * temp = head;
while (temp != NULL)
{
if (temp->data == d1)
{
Node * temp1 = temp->next;
temp->next = new Node(d2);
temp->next->next = temp1;
}
temp = temp->next;
}
}
void Delete(int data){
Node * todelete;
if(head->data == data){
todelete = head;
head = head->next;
free(todelete);
return;
}
Node *temp = head;
while(temp->next != NULL){
if(temp->next->data == data){
todelete = temp->next;
temp->next = temp->next->next;
free(todelete);
break;
}
temp = temp->next;
}
} // Deletes a node with data.
int getSize(){
Node * temp = head;
int size = 0;
while(temp != NULL){
temp = temp->next;
size++;
}
return size;
} //returns the count of elements in the list
bool IsEmpty(){
if(head == NULL){
return true;
}
else{
return false;
}
} //Returns true if empty.
void Merge(Node * list){
//merge
Node * temp = head;
while(temp != NULL){
if(temp->next == NULL and list != NULL){
temp->next = list;
break;
}
temp = temp->next;
}
//DISPLAY
while(head!=NULL){
cout<<head->data<<"->";
head=head->next;
}
cout<<"NULL"<<endl;
} //Merges the to the calling class.
void Erase(){
Node * erase;
while(head!= NULL){
erase = head;
head = head->next;
head = NULL;
}
free(erase);
} //Deletes every node in an array.
void SelectiveErase(int num) //Find num and delete everything after num.
{
Node * temp = head;
Node * todelete;
while(temp != NULL){
if(temp->data == num){
Node * erase = temp->next;
while(temp->next != NULL){
erase = temp->next;
temp->next = temp->next->next;
temp->next = NULL;
}
free(erase);
break;
}
temp = temp->next;
}
}
int FindNCount(int find)//Find and return count of all occurrence.
{
int counter = 0;
bool flag = false;
Node * temp = head;
while(temp->data!= find){
temp = temp->next;
counter++;
}
return counter;
}
int RemoveDuplicate(int find)//Find and remove every duplicate element in the list. Make //elements unique.
{
Node * temp = head;
Node *temp1;
while(temp != NULL){
temp1 = temp;
while(temp1->next != NULL){
if(temp->data == temp1->next->data and temp->data == find and temp1->next->data == find){
Node *todelete = temp1->next;
temp1->next = temp1->next->next;
free(todelete);
}
else{
temp1 = temp1->next;
}
}
temp = temp->next;
}
return find;
}
void FindNReplace(int find, int data)//Find and replace all occurrence recursively.
{
Node * temp = head;
while(temp != NULL){
if(temp->data == find){
temp->data = data;
break;
}
temp = temp->next;
}
}
void Display(){
static Node * temp= head;
if(temp == NULL){ cout << "NULL" << endl; return;}
cout << temp->data<<"->";
temp = temp->next;
Display();
}
};
void Swap() // swap the contents of one list with another list of same type and size. Also write parameter
{
LinkedList L,L1;
cout<<"AFTER SWAPING THE VALUE OF FIRST LIST \n";
while(L.head != NULL && L1.head != NULL){
int temp = L.head->data;
L.head->data = L1.head->data;
L1.head->data = temp;
cout<<L.head->data<<"\n";
L.head = L.head->next;
L1.head = L1.head->next;
}
cout<<endl;
}
int main()
{
// You must call Display function after every function.
LinkedList L{};
L[23];
// LinkedList L1;
// L1.InsertAtEnd(5);
// L1.InsertAtEnd(6);
//L.Erase();
// cout<<L.FindNCount(1)<<endl;
//L.SelectiveErase(2);
//L.Display();
//L.Merge(L1.head);
//L.RemoveDuplicate(2);
//L.Display();
//Swap();
return 0;
}
Overloading the subscript operator should return something. The assignment looks a bit vague, but I hope this will fix it:
//Overload [] operator. Use for loop in main to display it.
Node* operator[](int i) {
Node* nodePtr = head;
int counter = 0;
while (nodePtr != NULL && counter != i) {
nodePtr = nodePtr->next;
counter++;
}
return nodePtr;
}
I want to implement a merge-sorting algorithm, that is good for a doubly linked list with two "watches".
The watches are: head and tail, where head->prev is equal to NULL, head->next is equal to the first item, tail->prev is equal to the last item and tail->next is equal to NULL
Here is a graphic representation on how a doubly linked list would look like:
I have implemented the merge sort algorithm as such:
//Function to merge two halves of list.
struct Node *merge(struct Node *first, struct Node *second)
{
//base cases when either of two halves is null.
if (!first)
return second;
if (!second)
return first;
//comparing data in both halves and storing the smaller in result and
//recursively calling the merge function for next node in result.
if (first->data < second->data)
{
first->next = merge(first->next,second);
first->next->prev = first;
first->prev = NULL;
//returning the resultant list.
return first;
}
else
{
second->next = merge(first,second->next);
second->next->prev = second;
second->prev = NULL;
//returning the resultant list.
return second;
}
}
//Function to split the list into two halves.
struct Node *splitList(struct Node *head)
{
//using two pointers to find the midpoint of list
struct Node *fast = head,*slow = head;
//first pointer, slow moves 1 node and second pointer, fast moves
//2 nodes in one iteration.
while (fast->next && fast->next->next)
{
fast = fast->next->next;
slow = slow->next;
}
//slow is before the midpoint in the list, so we split the
//list in two halves from that point.
struct Node *temp = slow->next;
slow->next = NULL;
return temp;
}
//Function to sort the given doubly linked list using Merge Sort.
struct Node *sortDoubly(struct Node *head)
{
if (!head || !head->next)
return head;
//splitting the list into two halves.
struct Node *second = splitList(head);
//calling the sortDoubly function recursively for both parts separately.
head = sortDoubly(head);
second = sortDoubly(second);
//calling the function to merge both halves.
return merge(head, second);
}
source: geeksforgeeks
However, upon running the code, when I try to write the sorted doubly linked list, I get an error, when the deconstructor tries deleting the last item, as the algorithm is not working with a head-tail type doubly linked list.
What is a fix I could try?
The full code here:
#include <fstream>
#include <iostream>
using namespace std;
class node {
public:
int value;
node* prev;
node* next;
};
class DLLista {
private:
node* head;
node* tail;
public:
DLLista();
~DLLista();
node* createNode(int value);
void freeNode(node* p);
void insertBefore(node* p, int value);
void insertAfter(node* p, int value);
void deleteBefore(node* p);
void deleteAfter(node* p);
void deleteNode(node* p);
void push_back(node* p);
void push_front(node* p);
void printFront();
void printBack();
node* firstItem();
node* lastItem();
};
DLLista::DLLista() {
head = new node;
tail = new node;
head->prev = NULL;
head->next = tail;
tail->prev = head;
tail->next = NULL;
}
DLLista::~DLLista() {
while (head->next != tail) {
deleteNode(lastItem());
}
delete head;
delete tail;
}
node* DLLista::createNode(int value) {
node* newnode = new node;
newnode->value = value;
newnode->prev = newnode->next = NULL;
return newnode;
}
void DLLista::freeNode(node* p) {
delete p;
}
void DLLista::insertBefore(node* p, int value) {
node* newnode = createNode(value);
p->prev->next = newnode;
newnode->prev = p->prev;
newnode->next = p;
p->prev = newnode;
}
void DLLista::insertAfter(node* p, int value) {
node* newnode = createNode(value);
newnode->next = p->next;
newnode->prev = p;
p->next->prev = newnode;
p->next = newnode;
}
void DLLista::deleteBefore(node* p) {
node* del = p->prev;
if (del != NULL) {
del->prev->next = p;
p->prev = del->prev;
freeNode(del);
}
else {
cout << "Error:deleteBefore";
}
}
void DLLista::deleteAfter(node* p) {
node* del = p->next;
if (del != NULL) {
p->next = del->next;
del->next->prev = p;
freeNode(del);
}
else {
cout << "Error:deleteAfter";
}
}
void DLLista::deleteNode(node* p) {
if (p != head && p != tail) {
p->prev->next = p->next;
p->next->prev = p->prev;
freeNode(p);
}
else {
cout << "Error:deleteNode";
}
}
void DLLista::push_back(node* p) {
tail->prev->next = p;
p->prev = tail->prev;
p->next = tail;
tail->prev = p;
}
void DLLista::push_front(node* p) {
head->next->prev = p;
p->next = head->next;
p->prev = head;
head->next = p;
}
void DLLista::printFront() {
node* p = head->next;
while (p != tail) {
cout << p->value << " ";
p = p->next;
}
}
void DLLista::printBack() {
node* p = tail->prev;
while (p != head) {
cout << p->value << " ";
p = p->prev;
}
}
node* DLLista::firstItem() {
return head->next;
}
node* DLLista::lastItem() {
return tail->prev;
}
//Implementation of merge sort algorithm
void input(const char* file, DLLista& list) {
ifstream fin(file);
int n;
fin >> n;
int tmp;
for (int i = 0; i < n; i++) {
fin >> tmp;
node* newnode = list.createNode(tmp);
list.push_back(newnode);
}
}
node* merge(node* first, node* second) {
if (first == NULL) {
return second;
}
if (second == NULL) {
return first;
}
if (first->value < second->value) {
first->next = merge(first->next, second);
first->next->prev = first;
first->prev = NULL;
return first;
}
else {
second->next = merge(first, second->next);
second->next->prev = second;
second->prev = NULL;
return second;
}
}
node* split(node* head) {
node* fast = head;
node* slow = head;
while (fast->next && fast->next->next) {
fast = fast->next->next;
slow = slow->next;
}
node* tmp = slow->next;
slow->next = NULL;
return tmp;
}
node* sort(node* head) {
if (head == NULL || head->next == NULL) {
return head;
}
node* second = split(head);
head = sort(head);
second = sort(second);
return merge(head, second);
}
int main() {
DLLista list;
input("input1.txt ", list);
list.printFront();
node* head = list.firstItem()->prev;
sort(head);
}
input1.txt:
6
1 2 6 5 4 3
expected output:
1 2 3 4 5 6
I was trying out Linked List and I have a bit of problem with my insertNode1 function. This function is supposed to insert a new node after the inputted node by the user. The result doesn't show what I wanted to show. I wanted the number 5 to be after 3, but it doesn't show how I wanted it.
#include <iostream>
using namespace std;
class List {
struct node {
float data;
node* next;
};
node* head;
public:
void appendNode(float);
void insertNode(float);
void insertNode1(float,float);
void deleteNode(float);
void displayList();
List(){
head = NULL;
}
~List(){
node *nodePtr, *nextNode;
nodePtr = head;
while (nodePtr != NULL){
nextNode = nodePtr->next;
delete nodePtr;
nodePtr = nextNode;
}
}
};
void List::appendNode(float d)
{
node *newNode, *nodePtr;
newNode = new node;
newNode->data = d;
newNode->next = NULL;
if (!head){
head = newNode;
}
else {
nodePtr = head;
while (nodePtr->next){
nodePtr = nodePtr->next;
}
nodePtr->next = newNode;
}
}
void List::insertNode(float d){
node *newNode, *nodePtr, *prevNode=NULL;
newNode = new node;
newNode->data = d;
if (head== NULL)
{
head = newNode;
newNode->next = NULL;
}
else {
nodePtr = head;
while (nodePtr != NULL && nodePtr->data < d){
prevNode = nodePtr;
nodePtr = nodePtr->next;
}
if (prevNode == NULL){
head = newNode;
newNode->next = nodePtr;
}
else {
prevNode->next = newNode;
newNode->next = nodePtr;
}
}
}
void List::insertNode1(float p, float d){
node *newNode, *nodePtr, *selectedNode=NULL;
newNode = new node;
newNode->data = d;
nodePtr = head;
selectedNode = nodePtr;
selectedNode->data = p;
if (head != NULL){
head = newNode;
newNode->next = NULL;
}
else {
while (nodePtr->next != NULL && nodePtr->data != p){
nodePtr = nodePtr->next;
}
if (selectedNode == NULL){
head = newNode;
selectedNode->next = NULL;
}
else {
selectedNode->next = newNode;
}
}
}
void List::deleteNode(float da){
node *nodePtr, *previousNode=NULL;
if (head == NULL){
return;
}
if (head ->data == da){
nodePtr = head->next;
delete head;
head = nodePtr;
}
else{
nodePtr = head;
while (nodePtr != NULL && nodePtr->data != da){
previousNode = nodePtr;
nodePtr = nodePtr->next;
}
previousNode->next = nodePtr->next;
delete nodePtr;
}
}
void List::displayList(){
node *nodePtr;
nodePtr = head;
while (nodePtr!= NULL){
cout << nodePtr->data << endl;
nodePtr = nodePtr->next;
}
}
int main(){
List lobj;
lobj.appendNode(3);
lobj.appendNode(6.4);
lobj.appendNode(4.5);
lobj.appendNode(7.8);
lobj.insertNode(1.5);
lobj.displayList();
cout << "after deleting and adding a new node" << endl;
lobj.deleteNode(6.4);
lobj.displayList();
lobj.insertNode1(3, 5);
lobj.displayList();
system("pause");
}
At the beginning of your void List::insertNode1(float p, float d) function:
nodePtr = head;
selectedNode = nodePtr;
selectedNode->data = p;
Here, selectedNode points at the head of the list and you seem to overwrite the data of that node with the value of p, which I cannot help but feel is not what you meant to do.
There are a few issues inside List::insertNode1.
nodePtr = head;
selectedNode = nodePtr;
selectedNode->data = p;
Here selectedNode points at head but then you set the first data value to p.
if (head != NULL){
head = newNode;
newNode->next = NULL;
}
This part only executes when head is not null. This means you get rid of the entire list every time this is run. This is why the last call to list::displayList only prints 5.
if (selectedNode == NULL){
head = newNode;
selectedNode->next = NULL;
}
Here selectedNode is NULL. first you set head to be a new node but this doesn't change selectedNode. If you ran this method on an empty list your program would segfault here. You should be setting the next of head or newNode to NULL here, not selectedNode.
else {
selectedNode->next = newNode;
}
Here selectedNode still points to head. You change nodePtr but this doesn't also change selectedNode.
I have implemented a linked list but I find that removal of the last element in the linked list always fails. I checked my code several times but didn't find the logic mistake. Remove from the head and middle node works fine. Below is my code:
#include<iostream>
using namespace std;
template<typename T>
class Node{ //
private:
T val;
Node *next;
Node *prev;
public:
Node(T value){
val = value;
next = nullptr;
prev = nullptr;
}
~Node(){
if(prev != nullptr){
prev->next = next;
}
if(next != nullptr){
next->prev= prev;
}
}
T& getVal(){ //
return val;
}
Node* getNext(){
return next;
}
Node* getPrev(){
return prev;
}
//insert node after this node
void insert(Node *n){
if(next != nullptr){
next->prev = n;
}
n->next = next;
n->prev = this;
next = n;
}
void deleteNode(){
if(prev != nullptr && next != nullptr){
prev->next = next;
next->prev = prev;
}
}
};
//build a linked list with deletion and push back function
template<typename T>
class LList{
private:
Node<T> *head;
Node<T> *tail;
public:
LList(){
head = nullptr;
tail = nullptr;
}
~LList(){
if(nullptr != head){
while(head->getNext() != nullptr){ //
delete head->getNext();
}
delete head;
}
}
void push_back(T val){
Node<T>* n = new Node<T>(val);
if(head == nullptr){
head = n ;
tail = head;
}
else{
tail->insert(n);
tail = n;
}
}
void deleteItem(T item){
Node<T> *node = head;
//delete head
if(node->getVal() == item){
head = node->getNext();
node->deleteNode();
return;
}
//delete middle and tail
while(node->getVal() != item && node->getNext() != nullptr ){
node = node->getNext();
}
if(node->getVal() == item && node == tail){
tail = node->getPrev();
node->deleteNode();
return;
}
if(node->getVal() == item && node != tail){
node->deleteNode();
return;
}
else {
cout<<"didnt find the item "<<item<<endl;
}
}
void print(){
Node<T> *node = head;
while(node->getNext() != nullptr){
cout<<node->getVal()<<endl;
node = node->getNext();
}
cout<<node->getVal()<<endl;
}
};
int main(){
LList<double> list;
list.push_back(3.13);
list.push_back(2.8);
list.push_back(23);
list.push_back(4);
list.print();
list.deleteItem(3.13);
list.deleteItem(2);
list.deleteItem(4);
list.print();
return 0;
}
Here it is:
void deleteNode(){
if(prev != nullptr && next != nullptr){
prev->next = next;
next->prev = prev;
}
}
};
For the last element i guess that next equals nullptr and so the whole condition fails.
What I don't understand, is why removing the first element doesn't fail too, you probably should x-check your code for this.
[edit]
Here's my solution to fix this bug, it's basically the same as in the destructor for node:
void deleteNode(){
if(prev != nullptr){
prev->next = next;
}
if(next != nullptr){
next->prev= prev;
}
};
I think all cases have been considered in this:
Head := prev == null & next->prev = nullptr (assuming prev for this node was nullptr before)
Middle := prev->next = next & next->prev = prev
Tail := prev->next = null (assuming as above) & next == null
Head&Tail := prev == null & next == null (Only element of the list is deleted, so no references to be changed)
[/edit]
I'm having some trouble printing out the contents of a linked list. I'm using an example code that I found somewhere. I did edit it a bit, but I don't think that's why it's crashing.
class stringlist
{
struct node
{
std::string data;
node* next;
};
node* head;
node* tail;
public:
BOOLEAN append(std::string newdata)
{
if (head)
{
tail->next = new node;
if (tail->next != NULL)
{
tail=tail->next;
tail->data = newdata;
return TRUE;
}
else
return FALSE;
}
else
{
head = new node;
if (head != NULL)
{
tail = head;
head->data = newdata;
return TRUE;
}
else
return FALSE;
}
}
BOOLEAN clear(std::string deldata)
{
node* temp1 = head;
node* temp2 = NULL;
BOOLEAN result = FALSE;
while (temp1 != NULL)
{
if (temp1->data == deldata)
{
if (temp1 == head)
head=temp1->next;
if (temp1==tail)
tail = temp2;
if (temp2 != NULL)
temp2->next = temp1->next;
delete temp1;
if (temp2 == NULL)
temp1 = head;
else
temp1 = temp2->next;
result = TRUE;
}
else // temp1->data != deldata
{
temp2 = temp1;
temp1 = temp1->next;
}
}
return result;
}
BOOLEAN exists(std::string finddata)
{
node* temp = head;
BOOLEAN found = FALSE;
while (temp != NULL && !found)
{
if (temp->data == finddata)
found=true;
else
temp = temp->next;
}
return found;
}
void print()
{
node* tmp = head;
while (tmp)
{
printf("%s", tmp->data.c_str());
tmp = tmp->next;
}
}
stringlist()
{
head=NULL;
tail=NULL;
}
};
My main() function is really simple:
int main()
{
stringlist mylist;
if (mylist.append("something"))
count++;
if (mylist.append("else"))
count++;
if (mylist.append("yet"))
count++;
cout<<"Added "<<count<<" items\n";
mylist.print();
return 0;
}
For some reason in Print() tmp is never NULL
in node, add a constructor to initialize next to null
As #rmn pointed out, you're not initializing the value of node->next.
BOOLEAN append(std::string newdata)
{
if (head)
{
tail->next = new node;
if (tail->next != NULL)
{
tail=tail->next;
tail->data = newdata;
tail->next = NULL; // <- this is the part that is missing
return TRUE;
}
else
return FALSE;
}
else
{
head = new node;
if (head != NULL)
{
tail = head;
head->data = newdata;
head->next = NULL; // <- it's also missing here.
return TRUE;
}
else
return FALSE;
}
}
You could solve this by having a default constructor for node:
struct node
{
std::string data;
node* next;
node() : next(NULL) { }
};
With the default constructor you won't need to add tail->next = NULL;.
You aren't initializing head->tail appropriately in append when head==NULL initially.
Correct. That's because tail is only NULL in your code when the linked list is initially created. After you add a node, you set tail = head, and from that point in time, every time you add an element, you set tail->next = new node, and then tail = tail->next... so that tail->next always = tail.