Random access of a linked list element - c++

In an article about linked list, it is said that accessing a random element is not allowed and to access a certain node we need to traverse it from the head node
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node* next;
};
// This function prints contents of linked list
// starting from the given node
void printList(Node* n)
{
while (n != NULL) {
cout << n->data << " ";
n = n->next;
}
}
// Driver code
int main()
{
Node* head = NULL;
Node* second = NULL;
Node* third = NULL;
// allocate 3 nodes in the heap
head = new Node();
second = new Node();
third = new Node();
head->data = 1; // assign data in first node
head->next = second; // Link first node with second
second->data = 2; // assign data to second node
second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
printList(head);
return 0;
}
This was the example code on traversing a linked list and printing it's values
If i change the argument of printList() to second, it would still work
My question is, did i misinterpret the meaning to "access an element of a linkedlist", what does an element of a linkedlist contain?

I think you overinterpreted the article. You should store in your program only pointer to the first element (head) and in that case, you are not able to access n-th element directly. You need to find it "manually" by jumping to "next" element (n-1) times.
It doesn't mean that you are not able to access n-th element if you have pointer to that element.

accessing a random element is not allowed
That statement isn't quite precise about linked lists.
What is true is that given a linked list (and nothing more), it isn't possible find an element at any given index in constant time.
However, if you have an iterator or a reference to an element of a list, you can access that element in constant time through the iterator / reference.

To clear your confusion we probably should add the example of an array
Say we have an array
[1,2,3,4,5]
and a linkedlist
1->2->3->4->5
now if you want to access the 5th element in both the data structure what can you do
for array you just have to access the array[4] to get the element which is a O(1) operation to get the element
but for linkedList this doesn't happen
for accessing the 5th element of the linkedList you ll have to iterate in a manner like this
int element = 5;
while(element--){
head = head->next;
}
and when the loop ends you ll get your element

Related

std::list push back adds two elements instead of one

I'm trying to add elements to a list, but can't figure out why the push_back method is repeating the last added element. To illustrate:
Each node object consists of a data and head field. In the code below, I iterate through an array of ints, create a new node to store each int, and push_back the element to the list L. The repeated node is always the last one added to the list (in the picture above when iteratror i=1)
void addElements(std::list<node>& L, int arr[],std::list<node>::iterator Itor,int size){ //array decays to pointer
for (int i=1;i<size;i++){
node* n = new node;
n->data = arr[i];
n->head = Itor->head; //head of the first element in the list
L.push_back(*n);
}
}
I included the complete code of the disjoint data structure below. I read on cplusplus.com that push_back increases the container size by 1. So I'm a little perplexed why an extra node is being added to the list.
#include <iostream>
#include <list>
struct node{
int data;
node* head;
};
void makeSet(std::list<node>& L,int arr[]){ //asterick is before the variable name
node *headNode = new node;
headNode->data = arr[0]; //representative node
headNode->head = headNode; //point to itself
L.push_back(*headNode);
}
void addElements(std::list<node>& L, int arr[],std::list<node>::iterator Itor,int size){ //array decays to pointer
for (int i=1;i<size;i++){
node* n = new node;
n->data = arr[i];
n->head = Itor->head; //head of the first element in the list
L.push_back(*n);
}
}
int findSet(node* element){
return element->head->data;
}
int main(int argc, const char * argv[]) {
std::list<node>List;
std::list<node>::iterator Itor;
int dataArr[]={1,2,3,4,5};
int size = sizeof(dataArr)/sizeof(dataArr[0]);
Itor = List.begin();
makeSet(List,dataArr);
addElements(List,dataArr,Itor,size);
for (Itor = List.begin();Itor!=List.end();Itor++){
std::cout << Itor->data << std::endl;
}
}
Note that the size of the list in your example is 2. This means only nodes 0 and 1 are valid. This extra duplicate link is likely a Sentinel Value.
Often you'll find linked lists terminate with a null pointer, but it's just as easy to define the end of the list as a link that points to itself. This may have additional advantages, such as providing a one-past-the-end link to return as list::end.
Whatever its benefits, it is outside the bounds of the list so best that you not mess with it.

traversing a doubly-linked list and insert at its end (C++)

I have to face this problem: I have a doubly linked list and I have to make insertion at the tail. My list is made of Nodes such as
struct Node {
int val; // contains the value
Node * next; // pointer to the next element in the list
Node * prev; // pointer to the previous element in the list
};
and my class list declares only
private:
Node * first; // Pointer to the first (if any) element in the list
at first.
Now, I wrote such a method for inserting:
void List::insert(int n){
Node * tmp = new Node;
tmp->val = n;
tmp->next = 0;
if (!first) {
first = tmp;
}
else {
Node * p = new Node;
p = first;
while (p->next) {
p = p->next;
}
p->next = tmp;
tmp->prev = p;
}
};
and if I take several numbers from cin (say, 1 2 3 4), I call insert but I end up not having all the elements I wanted to store. I have only first and tmp, which contains the last number from the input (e.g. 4).
I struggle to figure out what's wrong - my first suggestion is variable scope.
Or is there anything wrong during the pointer setting?
OBS: I'd use a tail pointer of course, but the aim is traversing the list.
Any feedback is really appreciated.

Find the first element in list. C++

this is my program for list implementation in C++. And want to print the first element in it.
I write element until I reach 0
Can You show me the way to do it. Thanks
#include "stdafx.h"
#include "iostream"
using namespace std;
struct Node {
int data;
Node *next;
};
int main()
{
Node *first = 0;
Node *p;
cout << "Enter a list" << endl;
int i;
while (true) {
cin >> i;
if (i == 0) break;
p = new Node;
p -> data = i;
p -> next = first ;
first = p;
}
cout << "List: ";
p = first;
while (p) {
cout << p -> data;
p = p -> next;
}
cout << endl;
return 0;
}
Your program has a problem with keeping the initial element of the list: the code that you have assigns the last element to the variable called first, so your second loop will end as soon as it starts.
You need to change the logic around assigning first: for example, rather than assigning it unconditionally, you could assign it only if it is 0:
if (first == 0) {
first = p;
}
In addition to fixing this, you should add code to free the objects that you allocate with new. Use delete to free up the nodes in the list. This can be done in the same way as your second loop:
p = first;
while (p) {
Node* tmp = p;
p = p -> next;
delete tmp;
}
What you created is a stack (LIFO). You are adding new elements to its top, so first actually points to the last added element when you are traversing the data structure.
So, you can traverse it till the element's next is NULL - that's your actual first element.
Or you can change your program to use a different data structure, where you add elements to the tail and not to the head, or where you keep a pointer to the first element.
Just visit your linked list until you hit a node whose next pointer is 0.
This is the first node. Print its value and you are done.
Keep a pointer on the last node to be able to traverse the linked list.
If you need that first node often, keep an extra pointer for it.

Pointer in linked list/vector

I'm trying to implement my own linked list using vectors and pointers. The problem I'm have is that I can't get the first node to point to the second node.
Here's my code and what I've tried:
struct Node {
Node* previous;
Node* next;
int data;
};
// Initialize: Create Vector size 20 and first node
void LinkedList::init() {
vecList.resize(20, NULL); // Vector of size 20
Node* head = new Node(); // Create head node
head->previous = NULL; // Previous point set to null
head->next = vecList[1]; // Next pointer set to next position
head->data = 0; // Data set at value 0
vecList[0] = head; // Put head node in first position
count = 1; // Increase count by 1
}
// Add Node to array
void LinkedList::push_back(Node* node, int data) {
count += 1;
node = new Node();
node->next = vecList[count + 1];
node->previous = vecList[count - 1];
node->data = data;
vecList[count - 1] = node;
}
The data has been passed in and will displayed using:
cout << linkedlist.vecList[1]->data << endl;
But if I try this way to display I get error saying the next pointer is <Unable to read memory>
cout << linkedlist.vecList[0]->next->data << endl;
You forgot to set the next pointer of the previous Node in the push_back method.
If count is a member variable of the list containing the number of entries you have to change the method like this:
EDIT: actually you have to increment count in the end because array indices start with zero.
void LinkedList::push_back(Node * node, int data){
node = new Node();
node->next = NULL; // NULL because next element does not exist yet
node->previous = vecList[count - 1];
node->data = data;
vecList[count] = node;
vecList[count-1]->next = vecList[count];
count++;
}
Still it's a bit strange that you try to implement a linked list with a vector or array because that actually defeats the advantages of a list...
It looks like vecList is a vector/array of pointers to Node.
When you init, you let the first element point to the second element:
void LinkedList::init(){
...
head->next = vecList[1];
But at this point, the second element does not exist yet. So you cannot point to it yet. Something similar is wrong at the push_back function.

with single how loop to print last 3rd element from given single linked list?

With single loop how can we print last 3rd element from given single linked list
lets take there are 10 node in give linked list and i am supposed to find last 3rd node?
below code is for inserting a node at beginning now how can i print last 3rd element with sing loop? please help me
struct node
{
int data;
struct *next; //hold address of next node
}
void insert_begin(struct node**ptr)
{
node *temp;
temp=(struct *node) malloc(sizeof(struct node));
cout<<"enter ur data"<<endl;
cin>>temp->data;
temp->next=*ptr;
*ptr=temp;
}
int main()
{
node *head=0 // making head node or 1st node null
insert_begin(&head);
insert_begin(&head);
insert_begin(&head);
.....upto 10
}
Keep three pointers:
node * prevPrev = null;
node * prev = null;
node * current = head;
Iterate over the list with current until current->next is null.
At each iteration, update prev and prevPrev
prevPrev = prev;
prev = current;
current = current->next;
When current->next is null, prevPrev points to the last 3rd element.
You could use two pointers *p1,*p2 and initialize them so that *p1 points to the first element and *p2 points to the third element of your list. Then loop until *p2 reaches the end of your list, moving both pointers to the next element in each loop. When *p2 reaches the end print the element pointed by *p1.
OK, to do this in easy way what you can do is first manage counter variable for length of link i.e. 'count'. now:
int len = count;
*temp = ptr;
while(tmp->next != null)
{
len--;
if(len==3)
{
//you are at the last third element
// do your work and break the loop
}
else
{
temp = temp->next;
}
}