Find the same elements in C-struct - c++

I have to write a function that will add elements to C-struct, but it can't add the same element. Example:
Input:
1 2 1 3
Output:
ADDED 1
ADDED 2
NOT ADD 1
ADD 3
Elements are taken from array, here's piece of code that uses the function I need to write:
int tab[] = {1,4,1,3,5};
Node* head = 0;
for (size_t i = 0, e = std::size(tab); i != e; ++i) {
bool b = add(head,tab[i]);
cout << tab[i] << (b ? " " : " NOT ")
<< "added" << endl;
}
C-struct Node looks like that:
struct Node {
int data;
Node* next;
};
Here's what I wrote, but it adds all elements from array. I can't change the loop, only add function:
bool add(Node*& head, int data){
Node *n = new Node;
n->data = data;
n->next = 0;
if(!head)
head = n;
else{
Node *tmp = head;
while(tmp->next)
tmp = tmp->next;
tmp->next = n;
}
};

currently you just add the element without looking if it is already present or not
The definition can be something like
bool add(Node*& head, int data){
if(!head) {
head = new Node;
n->data = data;
n->next = 0;
return true;
}
Node *tmp = head;
while (tmp->next) {
if (tmp->data == data)
return false;
tmp = tmp->next;
}
if (tmp->data == data)
return false;
tmp->next = new Node;
tmp->next->data = data;
tmp->next->next = 0;
return true;
}
I encourage you to add a constructor to not have to set the data and next fields each time after you create a new instance
Exemple
Node::Node(int d) : next(0), data(d) {
}
// add should be a static method of Node, to be able to access next and data while they are private
bool add(Node*& head, int data){
if(!head) {
head = new Node(data);
return true;
}
Node *tmp = head;
while (tmp->next) {
if (tmp->data == data)
return false;
tmp = tmp->next;
}
if (tmp->data == data)
return false;
tmp->next = new Node(data);
return true;
}

Here's my attempt. Look for the existing data first then add if not present (no change there from existing code)
bool add(Node*& head, int data) {
Node *tmp = head;
while (tmp) {
if (tmp->data == data)
return false; // data already present
tmp = tmp->next;
}
Node *n = new Node;
n->data = data;
n->next = 0;
if (!head) {
head = n;
}
else {
Node *tmp = head;
while(tmp->next)
tmp = tmp->next;
tmp->next = n;
}
return true; // data added
}

So I did something like that and it works with the data I have. I suppose it works in general
bool add(Node*& head, int data){
Node *n = new Node;
n->data = data;
n->next = 0;
if(!head)
head = n;
else{
Node *tmp = head;
while(tmp->next){
if(tmp->data == data)
return false;
else
tmp = tmp->next;
}
tmp->next = n;
}
};

Related

How Can I Create A Single function that can create multiple Linked Lists

as shown in the code , i have to use 2 similar functions for creating 2 linked lists . isn't there a way i can create as many lists as i want with just one function , i tried using struct Node **p and struct Node *p as a parameter to the function but the didn't work
can someone help me to create multiple linked lists using this same function
and i want to create a append function not a insert function which asks for position as well.
#include <iostream>
using namespace std;
struct Node
{
int data = 10 ;
struct Node *next;
} *first , *second , *third;
void Display(struct Node *p)
{
while (p)
{
cout<<p->data<<" ";
p = p->next ;
}
cout<<"\n";
}
void Append_1(int elem)
{
Node* t , *last;
t = new Node;
t->data = elem;
t->next = NULL;
if(first == 0)
first = last = t;
else
{
last->next = t;
last = t;
}
}
void Append_2(int elem)
{
Node* t , *last;
t = new Node;
t->data = elem;
t->next = NULL;
if(second == 0)
second = last = t;
else
{
last->next = t;
last = t;
}
}
//void SortMerge(struct Node *p , struct Node *q);
int main()
{
Append_1(3);
Append_1(7);
Display(first);
Append_2(10);
Append_2(14);
Append_2(21);
Display(second);
//SortMerge(first , second);
Display(third);
return 0;
}
You can create a class like here:
struct Node{
int data;
Node* next;
Node* previous;
};
class Graph{
public:
Graph(int = 0);
~Graph();
void display_left_right();
void display_right_left();
void append(int);
void append_at_pos(int,int);
void prepend(int);
int get_num_elt();
int get_data_at_pos(int);
private:
Node* head;
Node* tail;
int num_elt=0;
};
Graph::Graph(int first_data){
head = new Node;
head->next = NULL;
head->previous = NULL;
head->data = first_data;
tail = head;
num_elt++;
}
Graph::~Graph(){
Node* main_traverser = head;
while(main_traverser){
main_traverser = head->next;
delete head;
head = main_traverser;
}
std::cout <<"Graph deleted!" << std::endl;
}
void Graph::display_left_right(){
Node* traverser = head;
while(traverser != NULL){
std::cout << traverser->data << " ";
traverser = traverser->next;
}
std::cout << std::endl;
}
void Graph::display_right_left(){
Node* traverser = tail;
while(traverser != NULL){
std::cout << traverser->data << " ";
traverser = traverser->previous;
}
std::cout << std::endl;
}
void Graph::append(int new_data){
Node* add = new Node;
add->data = new_data;
add->next = NULL;
add->previous = tail;
tail->next = add;
tail = add;
num_elt++;
}
void Graph::append_at_pos(int pos, int new_data){
if(pos > num_elt+1 || pos<=0){std::cout << "Wrong position!" << std::endl; return;}
if(pos==1){
prepend(new_data);
return;
}
if(pos==num_elt+1){
append(new_data);
return;
}
Node* add = new Node;
Node* traverser = head;
add->data = new_data;
for(int i=0; i<pos-2; i++){
traverser = traverser->next;
}
add->next = traverser->next;
add->previous = traverser;
traverser->next->previous = add;
traverser->next = add;
}
void Graph::prepend(int new_data){
Node* add = new Node;
add->next = head;
add->previous = NULL;
add->data = new_data;
head->previous = add;
head = add;
num_elt++;
}
int Graph::get_num_elt(){
return num_elt;
}
int Graph::get_data_at_pos(int pos){
Node* traverser = head;
if(pos <=0 || pos> num_elt){std::cout << "Wrong position!" << std::endl; return 0;}
for(int i=0; i<pos-1; i++){
traverser = traverser->next;
}
return traverser->data;
}
main(){
Graph a(2);
a.append(3);
a.append(4);
a.prepend(1);
a.display_left_right();
a.append_at_pos(1,6);
a.display_left_right();
std::cout << "data at 1: " << a.get_data_at_pos(1) << std::endl;
}
When you say "create multiple linked lists," I think you mean creating nodes to a linked list, which you have 2 append functions. I think the reason you have these 2 functions is because you do not know where to start traversing your linked list. For this reason, I think in your main function you should declare the head of the linked list, a single node that is the start. Set it's data and next to null, and then pass the head value into a function so it can start traversing from the head. Here is a generic append function that adds a node on the end, where the parameters are a reference to the head node, and the value for the new node:
void append(Node ** head, int new_data)
{
Node * select_node = * head;
// select node is set to the head node, and will traverse until it is at the end
while (select_node -> next != NULL)
{
// select node is set to the next node until it is NULL (end of linked list)
select_node = select_node -> next;
}
// now that select node is the last node, we need to make it's next value a node
// and that node should be a new node (allocated in heap) with the value of the input value
//and the next value be NULL (because it's the end of the linked list)
Node * next_node = new Node();
next_node -> data = new_data;
next_node -> next = NULL;
select_node -> next = next_node;
}

C++: potential memory leak in linked list

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;
}
}
};

C++ Inserting into a linked list

I am writing a program that modifies a linked list. The problem I am having is when inserting nodes into the linked list. The first few nodes are inserted and moved properly, but when reaching the end of the linked list some nodes are either removed or not displayed.
Function for inserting
void LinkedList::insert(int num, int pos)
{
Node *temp1 = new Node;
temp1->data = num;
temp1->next = NULL;
if(pos == 0)
{
temp1->next = head;
head = temp1;
return;
}
Node *temp2 = head;
for(int i = 0; i < pos-1; i++)
{
temp2 = temp2->next;
}
temp1->next = temp2->next;
temp2->next = temp1;
}
Node structure
struct Node
{
int data;
Node *next;
};
int size;
Node *head, *tail;
Driver code
nums.insert(1, 0); // 1 in location 0
nums.insert(5, 4); // 5 in location 4
nums.insert(3, 7); // 3 in location 7
List before insert
8 6 7 8 0 9
List after insert
1 8 6 7 5 8
Expected after insert
1 8 6 7 5 8 0 9 3
Would the values excluded from being display needed to be stored and inserted afterwards? Or is the inserting itself not being coded properly/missing elements?
Thanks for your help.
Full code
#include "linkedlist.h"
LinkedList::LinkedList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LinkedList::~LinkedList()
{
if(head != nullptr)
{
Node *temp;
while(head != nullptr)
{
temp = head->next;
// deletes head
delete head;
// goes to next element
head = temp;
}
}
}
void LinkedList::display()
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
cout << temp->data << "\t";
temp = temp->next;
}
cout << endl;
}
void LinkedList::append(int num)
{
// list is empty
if(head == nullptr)
{
head = new Node;
head->data = num;
head->next = nullptr;
// sets tail to head
tail = head;
}
else
{
// creates new node
Node *temp = new Node;
// sets new node data
temp->data = num;
temp->next = nullptr;
// sets previous tail link to new node
tail->next = temp;
// sets this node to new tail
tail = temp;
}
// increments size
size++;
}
void LinkedList::pop()
{
if(size > 1)
{
Node *temp = head;
// loops to node before tail
while(temp->next->next != nullptr)
{
temp = temp->next;
}
// deletes tail
delete tail;
// sets new tail
tail = temp;
tail->next = nullptr;
}
// if there's only one item
else if(size == 1)
{
Node *temp = tail;
// head and tail are now null
head = nullptr;
tail = nullptr;
// deletes node
delete temp;
}
size--;
}
int LinkedList::min()
{
int min = head->data;
struct Node *temp = head;
while(temp != nullptr)
{
if(min > temp->data)
{
min = temp->data;
}
temp = temp->next;
}
return min;
}
int LinkedList::max()
{
int max = head->data;
struct Node *temp = head;
while(temp != nullptr)
{
if(max < temp->data)
{
max = temp->data;
}
temp = temp->next;
}
return max;
}
int LinkedList::mean()
{
int sum = 0;
int average = 0;
struct Node *temp = head;
while(temp != nullptr)
{
sum += temp->data;
temp = temp->next;
}
average = sum / size;
return average;
}
void LinkedList::sort()
{
Node *current1 = head;
Node *current2 = head;
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size - 1; j++)
{
if(current1->data < current2->data)
{
int temp = current1->data;
current1->data = current2->data;
current2->data = temp;
}
current2 = current2->next;
}
current2 = head;
current1 = head->next;
for(int p = 0; p < i; p++)
{
current1 = current1->next;
}
}
}
void LinkedList::reverse()
{
Node *current1 = head;
Node *current2 = head;
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size - 1; j++)
{
if(current1->data > current2->data)
{
int temp = current1->data;
current1->data = current2->data;
current2->data = temp;
}
current2 = current2->next;
}
current2 = head;
current1 = head->next;
for(int p = 0; p < i; p++)
{
current1 = current1->next;
}
}
}
int LinkedList::linearSearch(int key)
{
Node *search = nullptr;
Node *temp = head;
Node *current = head;
int count = 0;
while(current != NULL && current->data != key)
{
count++;
temp = current;
current = current->next;
}
if(current != NULL)
{
search = current;
current = current->next;
}
key = count;
return key;
}
void LinkedList::insert(int num, int pos)
{
Node *temp1 = new Node;
temp1->data = num;
temp1->next = NULL;
if(pos == 0)
{
temp1->next = head;
head = temp1;
return;
}
Node *temp2 = head;
for(int i = 0; i < pos-1; i++)
{
temp2 = temp2->next;
}
temp1->next = temp2->next;
temp2->next = temp1;
}
You have a size member that your display function uses, but you never increment it in insert. So while the element gets added, you don't increase the size of the list.
Reading your whole code and getting to the solution may consume lot of time but if you want i have a code ready which is properly working. If you wanted to use this. Please go for it and also, please feel free to ask my anything though this link
#include <iostream>
using namespace std;
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;
}
}
node* gethead()
{
return head;
}
static void display(node *head)
{
if(head == NULL)
{
cout << "NULL" << endl;
}
else
{
cout << head->data << endl;
display(head->next);
}
}
static void concatenate(node *a,node *b)
{
if( a != NULL && b!= NULL )
{
if (a->next == NULL)
a->next = b;
else
concatenate(a->next,b);
}
else
{
cout << "Either a or b is NULL\n";
}
}
};
int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
linked_list b;
b.add_node(3);
b.add_node(4);
linked_list::concatenate(a.gethead(),b.gethead());
linked_list::display(a.gethead());
return 0;
}

How can I partition a singly linked list around a value, using two seperate functions in main() - one lesserThan and the other greaterThan - in C/C++

I have the following linked list:
2->1->9->8->3->1->nullptr.
I want to partition the linked list around the value 4, such that all values less than 4, come before all values greater than or equal to 4.
I can partition the linked list using a single function. But, I want to do it using two function - a function lesserThan(head,x) and a function greaterThan(head, x) - where x is the value around which I want to partition the list.
But, I am running into the following problem: If I use both functions together, the list nodes are modified by the first function - and, the second function works on that modified nodes. The functions work fine, when the other one is commented out. That is, lesserThan(head,x) works fine, when greaterThan(head, x) is commented out, and vice-versa.
How can I partition the linked list, by still using both the functions in main()? The main problem I am having is that the nodes are getting modified in both lesserThan and greaterThan functions, and that is getting reflected in main().
Following is the code:
struct Node
{
int data;
Node* next;
};
Node* newNode(int data)
{
Node* temp = new Node;
temp->data = data;
temp->next = nullptr;
return temp;
}
Node* lesserThan(Node* head, int x)
{
if (head == nullptr)
{
return nullptr;
}
Node* list1=nullptr, *temp1 = nullptr;
if ((head)->data < x)
{
temp1=list1 = head;
}
else
{
while (head && head->data >= x)
{
head = head->next;
}
if (head && head->data < x)
{
temp1 = list1 = head;
}
}
Node* curr = temp1;
if(curr)
curr = curr->next;
while (curr)
{
Node* next = curr->next;
if (curr->data<x)
{
list1->next = curr;
list1 = curr;
list1->next = nullptr;
}
curr = next;
}
return temp1;
}
Node* greaterThan(Node* head, int x)
{
Node* temp2 = nullptr, *list2=nullptr;
if (head->data >= x)
{
temp2 =list2= head;
}
else
{
while (head && head->data < x)
{
head = head->next;
}
if (head && head->data >= x)
{
temp2 = list2 = head;
}
}
Node* curr = list2;
if (curr)
curr = curr->next;
while (curr)
{
Node* next = curr->next;
if (curr->data >= x)
{
list2->next = curr;
list2 = curr;
list2->next = nullptr;
}
curr = next;
}
return temp2;
}
int main()
{
Node* head = newNode(2);
head->next = newNode(1);
head->next->next = newNode(9);
head->next->next->next = newNode(8);
head->next->next->next->next = newNode(3);
head->next->next->next->next->next = newNode(1);
int x = 4;
Node* p1 = lesserThan(head,x);
Node* p2 = greaterThan(head, x);
if (p1 != nullptr)
p1->next = p2;
while (p1)
{
cout << p1->data << " ";
p1 = p1->next;
}
cout << endl;
return 0;
}
Following are the two functions, that fail to work together, because the List nodes are modified by the first function (and second function), and that is reflected in main() -
How can I have the two functions in main, so that they don't effect each other? I tried creating different variables for head, and passing them to the functions. But that didn't work. Thanks for the help!
It will be better to use insert recursive function instead of your style and note that you have undeleted allocated nodes. I didn't consider them. Any way, I think the following code works as intented
struct Node
{
Node() = default;
Node( int dataVal ):data{dataVal}{}
int data{};
Node* next{};
};
Node*& lessThan( Node* const & head, int x){
if( !head ) throw std::invalid_argument("Empty linked list");
Node* toBeReturned;
Node* currentHeadNode = head;
Node** currentReturned = & toBeReturned;
while( currentHeadNode ){
if(currentHeadNode -> data < x ){
*currentReturned = new Node{ currentHeadNode -> data };
currentReturned = &((*currentReturned) -> next);
}
currentHeadNode = currentHeadNode->next;
}
return toBeReturned;
}
int main()
{
Node* head = new Node(2);
head->next = new Node(1);
head->next->next = new Node(9);
head->next->next->next = new Node(8);
head->next->next->next->next = new Node(3);
head->next->next->next->next->next = new Node(1);
int x = 4;
Node* p1 = lessThan(head,x);
while (p1)
{
std::cout << p1->data << " ";
p1 = p1->next;
}
std::cout << std::endl;
return 0;
}

All of nodes in linkedlist are the same, seems insertion is not working

I have a linked list in C++, after inserting several nodes now I see that all of them are the same, although I'm using different values to add to node each time, but it's like all of them are the same, even when trying to change a node all of them are changing together or it's the same node that is always being returned, I don't know.
class node
{
public:
int ochance = 3;
string question;
string option1;
int peopleeffectop1;
int courteffectop1;
int treasuryeffectop1;
string option2;
int peopleeffectop2;
int courteffectop2;
int treasuryeffectop2;
node *next;
};
class list
{
private:
node *head, *tail;
public:
list()
{
head=NULL;
tail=NULL;
}
void createnode(int value , string q , string ans1 , int ans1ef1 , int ans1ef2, int ans1ef3 , string ans2, int ans2ef1 , int ans2ef2, int ans2ef3 )
{
node *temp = new node;
temp->ochance = value;
temp->question = q;
temp->option1 = ans1;
temp->peopleeffectop1 = ans1ef1;
temp->courteffectop1 = ans1ef2;
temp->treasuryeffectop1 = ans1ef3;
temp->option2 = ans2;
temp->peopleeffectop2 = ans2ef1;
temp->courteffectop2 = ans2ef2;
temp->treasuryeffectop2 = ans2ef3;
temp->next = NULL;
if(head == NULL)
{
head = temp;
tail = temp;
temp = NULL;
}
else
{
tail->next = temp;
tail = temp;
}
}
node getnth(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
return *tmp;
}
i++;
tmp = tmp->next;
}
}
int getlen()
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
i++;
tmp = tmp->next;
}
return i;
}
void minus(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
tmp->ochance -=1;
}
i++;
tmp = tmp->next;
}
}
void delete_first()
{
node *temp = new node;
temp = head;
head = head->next;
delete temp;
}
void delete_last()
{
node *current = new node;
node *previous = new node;
current = head;
while(current->next != NULL)
{
previous = current;
current = current->next;
}
tail = previous;
previous->next = NULL;
delete current;
}
void delete_position(int pos)
{
node *current = new node;
node *previous = new node;
current = head;
for(int i = 1; i < pos; i++)
{
previous = current;
current = current->next;
}
previous->next = current->next;
}
};
For starters many member functions has a memory leak as for example in this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
//
At first memory was allocated and its address was stored in the pointer tmp and then the pointer is reassigned. As a result the address of the allocated memory is lost and the memory is not deleted.
These statements
node* tmp = new node;
tmp= head;
must be substituted for this one statement
node* tmp = head;
Moreover this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
int i =0 ;
while(tmp!=NULL){
if (i=pos) {
return *tmp;
}
i++;
tmp = tmp->next;
}
}
has undefined behavior in case when pos is higher than there are nodes in the list. In this case the function returns nothing.
In the function minus there is used the assignment operator instead of the comparison operator
while(tmp!=NULL){
if (i=pos) {
^^^^^
In this function
void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
there is no check whether head is equal to NULL and tail is not adjusted if it is point to the first node.
The same problems are also in the function delete_last only that instead of the adjacent of the tail node as in the previous function you have to adjust the head node.
This function delete_position has the same drawbacks as the previous functions but also it has a bug in the loop
for(int i=1;i<pos;i++)
A node at position 1 will never be deleted.