The way I know how to represent a linked list is basically creating a Node class (more preferably a struct), and the creating the actual linkedList class. However, yesterday I was searching for the logic of reversing a singly linked list operation and almost 90% of the solutions I've encountered was including that the function, returning data type Node* . Thus I got confused since if you want to reverse a list no matter what operation you done, wouldn't it be in the type of linkedList again? Am I doing it the wrong way?
The linked list implementation I do all the time;
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *next;
};
class linkedList
{
public:
Node* firstPtr;
Node* lastPtr;
linkedList()
{
firstPtr=lastPtr=NULL;
}
void insert(int value)
{
Node* newNode=new Node;
newNode->data=value;
if(firstPtr==NULL)
firstPtr=lastPtr=newNode;
else {
newNode->next=firstPtr;
firstPtr=newNode;
}
}
void print()
{
Node *temp=firstPtr;
while(temp!=NULL)
{
cout<<temp->data<<" ";
temp=temp->next;
}
}
};
You approach isn't wrong, but you might be giving too much emphasis on your linkedList class.
What does that class actually contain? A pointer to the first node, and a pointer to the last node (which is redundant information, since you can find the last node by only knowing the first one). So basically linkedList is just a helper class with no extra information.
The member functions from linkedList could easily be moved inside Node or made free functions that take a Node as parameter.
Well, what is a linked list but a pointer to the first node? A list is fully accessible provided you can get to the first node, and all you need for that is a pointer to the first node.
Unless you want to store extra control information about the list (such as its length for example), there's no need for a separate data type for the list itself.
Now some implementations (such as yours) may also store a pointer to the last node in the list for efficiency, allowing you to append an item in O(1) instead of O(n). But that's an extra feature for the list, not a requirement of lists in general.
Those functions might be returning of type Node* because after reversing the linked-list they will return the pointer to the First node of the list.
Related
I am new to c++ and am working on an assignment involving vectors and a doubly linked list. I am given this struct as such.
struct Node {
std::vector<T> data;
Node<T>* next;
Node<T>* prev;
Node(): next(nullptr), prev(nullptr){} };
I am now required in another class to create a constructor for this Node to be used for various methods. I understand that the struct already has an initialization list for next and prev, I think I am just overthinking what the constructor should be.
Class LinkedVector {
Node<T>* head;
LinkedVector<T>::LinkedVector(){
head = NULL;
}
}
Is this the correct way of constructing the linked list? Again I am new to c++ and any help pointing me in the right direction is most helpful. Thank you and have a great day.
Yes, that is almost correct, you want to set head to nullptr instead of NULL of course.
Then when you create methods to add to the list you will need to check if it is empty and if so initialize head rather than adding an element elsewhere.
I was going through the linked list and I have confusion. maybe I am mixing the concept or something else. Here is the code of creating the header node.
struct node
{
int data;
struct node *link;
};
node *head;
void main()
{
head = new node;
}
1)The first thing I want to know is how can we write struct node *link; in inside the same node structure? because using first the node structure is created then we can declare pointer of that.
2) node *head; will already declare a memory of size node, then we need to do again head = new node;?
The self referential struct can hold a pointer to itself. Please do not confuse with size of pointer to size of structure. Size of pointer is constant irrespective of data type.
struct node
{
int data;
struct node *link;
};
Had it the struct node *link be something else like struct node link, It will not compile just like you think.
regarding why allocation by using the new is required, when we do node *head, it says that head points to memory location of actual node with area for data and link.
It might be useful to read pointer concept again
A link list is a chain of objects. What you are doing here is creating a struct with two variables. One is the date to store in this node. The other is a recursive struct. This where link lists get their name. One struct links to the next. When this node is created, link has no value but you can add nodes by creating a new node and storing it in link.
As for the rest of your code, I don't think you are doing it right. Usually nodes are wrapped in a link list class so that you can control the link list by adding, deleting and searching the nodes. When you are controlling a link list you need at least two pointers. One to point to the first node in the list (also called the "head"). The second pointer is the search pointer that will start at the head and go node by node until you find what you are looking for.
Now to answer your second question when you write node* head you are only declaring the pointer. You are not declaring "a memory of size node" so in the initialize function of the link list you need to create the first node and have the head point to it head = new node;
Now I know that why pointers are used in defining linked lists. Simply because structure cannot have a recursive definition and if there would have been no pointers, the compiler won't be able to calculate the size of the node structure.
struct list{
int data;
struct list* next; // this is fine
};
But confusion creeps up when I declare the first node of the linked list as:
struct list* head;
Why this has to be a pointer? Can't it be simply declared as
struct list head;
and the address of this used for further uses? Please clarify my doubt.
There's no definitive answer to this question. You can do it either way. The answer to this question depends on how you want to organize your linked list and how you want to represent an empty list.
You have two choices:
A list without a "dummy" head element. In this case the empty list is represented by null in head pointer
struct list* head = NULL;
So this is the answer to your question: we declare it as a pointer to be able to represent an empty list by setting head pointer to null.
A list with a "dummy" head element. In this case the first element of the list is not used to store actual user data: it simply serves as a starting "dummy" element of the list. It is declared as
struct list head = { 0 };
The above represents an empty list, since head.next is null and head object itself "does not count".
I.e. you can declare it that way, if you so desire. Just keep in mind that head is not really a list element. The actual elements begin after head.
And, as always, keep in mind that when you use non-dynamically-allocated objects, the lifetime of those objects is governed by scoping rules. If you want to override these rules and control the objects' lifetimes manually, then you have no other choice but to allocate them dynamically and, therefore, use pointers.
You can declare a list such a way
struct list head = {};
But there will be some difficulties in the realization of functions that access the list. They have to take into account that the first node is not used as other nodes of the list and data member of the first node data also is not used.
Usually the list is declared the following way
struct List
{
// some other stuff as for example constructors and member functions
struct node
{
int data;
struct node* next; // this is fine
} head;
};
and
List list = {};
Or in C++ you could write simply
struct List
{
// some other stuff as for example constructors and member functions
struct node
{
int data;
struct node* next; // this is fine
} head = nullptr;
};
List list;
Of course you could define the default constructor of the List yourself.
In this case for example to check whether the list is empty it is enough to define the following member function
struct List
{
bool empty() const { return head == nullptr; }
// some other stuff as for example constructors and member functions
struct node
{
int data;
struct node* next; // this is fine
} head;
};
In simple terms, if your head is the start node of the linked list, then it will only contain the address of the first node from where linked list will begin. This is done to avoid confusion for a general programmer. Since the head will contain only address, hence, it is declared as a pointer. But the way you want to declare is also fine, just code accordingly. Tip: If you later on want to make some changes in your linked list, like deletion or insertion operations at the beginning of the linked list, you will face problems as you will require another pointer variable. So its better to declare the first node as pointer.
I am currently writing a program in C++ that uses linked lists. The problem is, I can't really seem to figure out how to use linked lists. I know (A little) how to use classes though.
This is the LinkedList.h file given by the teacher (So I can't modify anything)
LinkedList.h
struct Node
{
void* data_;
Node* next_;
Node()
{
data_ = 0;
next_ = 0;
}
};
class LinkedList
{
private:
Node* first_;
Node* last_;
long listLen_;
public:
LinkedList();
~LinkedList();
void AddLinkToBack(void* ptr);
void* RemoveLinkFromFront();
Node* GetFirstNode();
long GetListLength();
};
I really just need advice on what to do for the Linked List function definitions but I will also listen to advice on improving my code. Thank you :)
Edit: Removed the other code in case someone in a future class stumbles upon this post.
I'm going to describe how to implement each function. Not going to give you the code.
LinkedList(): This is your constructor for the linked list. This function should be a part of the class where you have defined a linked list. It will be called whenever a linked list is initialised. You can use it define the first node of a linked list and set it to NULL.
~LinkedList(): This is your destructor for the linked list. It will deallocate all the memory allocated to the linked list. Implement it such that it deallocates memory for all elements of the linked list as opposed to just setting the first element to NULL.
AddLinkToBack(void* ptr): Add an element to the end of the linked list. This should traverse to the end of the linked list and set the next pointer of the last element to the pointer passed in the parameter. You should also dereference the void pointer before doing this.
RemoveLinkFromFront(): Remove the first element. To do this, you can set the first element of the list as first->next, and deallocate the memory given to the first element.
GetFirstElement(): Return a pointer to the first element of the linked list.
GetListLength(): Traverse the entire list and keep a pointer alongside which will increment every time you move to the next element. Return the counter when you reach the end of the linked list.
When using a linked list that stores numerous objects how would you go about access the data inside said object?.
Example code.
using namespace std;
typedef struct node
{
int data;
node* next;
} *nodePtr;
nodePtr head;
nodePtr current;
nodePtr temp;
void PrintList()
{
current = head;
while(current != NULL)
{
cout << current->data.getMakeModel();
cout << current->data.getRegNo();
cout << current->data.getEngineSize();
cout << current->data.getRented();
current=current->next;
}
}
My current way of doing it doesn't work and I'm not sure how to solve it.
All i need to do is access the template object data members which i have getter methods for and output the data.
Any ideas?
On a side note, would it be possible to search for a specific object(an object with specific data member value) in a linked list? with the objects still using templates of course
When using a linked list that stores numerous objects how would you go about access the data inside said object?
If you have a nodePtr you'll have to do ptr->data to access the int of the struct.
My current way of doing it doesn't work and I'm not sure how to solve it.
You are trying to access member functions on an object of type int, that does not have any. You probably meant to define another type for the data member object of node.
On a side note, would it be possible to search for a specific object(an object with specific data member value) in a linked list?
Of course, the implementation of such an algorithm is pretty trivial. You can implement it along the lines of:
nodePtr find(nodePtr head, int value) {
for (; head != NULL; head = head->next)
if (*head == value)
return first;
return NULL;
}
What I would suggest is to use the standard std::forward_list or std::list. If you do, you'll be able to use std::find for the "find"-algorithm.
The probem here is that data is of type int and not of a class type. You will have to change its type to a class type e.g Foo. A more advanced solution will use templates to make it work with arbitrary types (e.g std::list)
Also notice that your class definition is not considered good style. I would define it as:
struct node
{
typedef node* Ptr;
Foo data;
node* next;
};
While the typedef is only reasonable in some special cases (e.g if working extensively with smart pointers and reference counting). In normal cases one should go with node* (which is also smaller o.O)