How could I create a list in c++? - c++

How can I create a list in C++? I need it to create a linked list. How would I go about doing that? Are there good tutorials or examples I could follow?

I take it that you know that C++ already has a linked list class, and you want to implement your own because you want to learn how to do it.
First, read Why do we use arrays instead of other data structures? , which contains a good answer of basic data-structures. Then think about how to model them in C++:
struct Node {
int data;
Node * next;
};
Basically that's all you need to implement a list! (a very simple one). Yet it has no abstractions, you have to link the items per hand:
Node a={1}, b={20, &a}, c={35, &b} d={42, &c};
Now, you have have a linked list of nodes, all allocated on the stack:
d -> c -> b -> a
42 35 20 1
Next step is to write a wrapper class List that points to the start node, and allows to add nodes as needed, keeping track of the head of the list (the following is very simplified):
class List {
struct Node {
int data;
Node * next;
};
Node * head;
public:
List() {
head = NULL;
}
~List() {
while(head != NULL) {
Node * n = head->next;
delete head;
head = n;
}
}
void add(int value) {
Node * n = new Node;
n->data = value;
n->next = head;
head = n;
}
// ...
};
Next step is to make the List a template, so that you can stuff other values (not only integers).
If you are familiar with smart pointers, you can then replace the raw pointers used with smart pointers. Often i find people recommend smart pointers to starters. But in my opinion you should first understand why you need smart pointers, and then use them. But that requires that you need first understand raw pointers. Otherwise, you use some magic tool, without knowing why you need it.

You should really use the standard List class. Unless, of course, this is a homework question, or you want to know how lists are implemented by STL.
You'll find plenty of simple tutorials via google, like this one. If you want to know how linked lists work "under the hood", try searching for C list examples/tutorials rather than C++.

If you are going to use std::list, you need to pass a type parameter:
list<int> intList;
list<int>* intListPtr = new list<int>;
If you want to know how lists work, I recommending googling for some C/C++ tutorials to gain an understanding of that subject. Next step would then be learning enough C++ to create a list class, and finally a list template class.
If you have more questions, ask back here.

Why reinvent the wheel. Just use the STL list container.
#include <list>
// in some function, you now do...
std::list<int> mylist; // integer list
More information...

I'm guessing this is a homework question, so you probably want to go here. It has a tutorial explaining linked lists, gives good pseudocode and also has a C++ implementation you can download.
I'd recommend reading through the explanation and understanding the pseudocode before blindly using the implementation. This is a topic that you really should understand in depth if you want to continue on in CS.

Boost ptr_list
http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_list.html
HTH

Create list using C++ templates
i.e
template <class T> struct Node
{
T data;
Node * next;
};
template <class T> class List
{
Node<T> *head,*tail;
public:
void push(T const&); // push element
void pop(); // pop element
bool empty() // return true if empty.
};
Then you can write the code like:
List<MyClass>;
The type T is not dynamic in run time.It is only for the compile time.
For complete example click here.
For C++ templates tutorial click here.

We are already in 21st century!!
Don't try to implement the already existing data structures.
Try to use the existing data structures.
Use STL or Boost library

Related

Tree traversal falls into infinite loop (with huffman algorithm implementation)

I am trying implementing the huffman algorithm following the steps described in this tutorial: https://www.programiz.com/dsa/huffman-coding, and so far I got this code:
void encode(string filename) {
List<HuffmanNode> priorityQueue;
List<Node<HuffmanNode>> encodeList;
BinaryTree<HuffmanNode> toEncode;
//Map<char, string> encodeTable;
fstream input;
input.open(filename, ios_base::in);
if (input.is_open()) {
char c;
while (!input.eof()) {
input.get(c);
HuffmanNode node;
node.data = c;
node.frequency = 1;
int pos = priorityQueue.find(node);
if(pos) {
HuffmanNode value = priorityQueue.get(pos)->getData();
value++;
priorityQueue.update(pos, value);
} else {
priorityQueue.insert(node);
}
}
}
input.close();
priorityQueue.sort();
for(int i=1; i<=priorityQueue.size(); i++)
encodeList.insert( priorityQueue.get(i) );
while(encodeList.size() > 1) {
Node<HuffmanNode> * left = new Node<HuffmanNode>(encodeList.get(1)->getData());
Node<HuffmanNode> * right = new Node<HuffmanNode>(encodeList.get(2)->getData());
HuffmanNode z;
z.data = 0;
z.frequency = left->getData().frequency + right->getData().frequency;
Node<HuffmanNode> z_node;
z_node.setData(z);
z_node.setPrevious(left);
z_node.setNext(right);
encodeList.remove(1);
encodeList.remove(1);
encodeList.insert(z_node);
}
Node<HuffmanNode> node_root = encodeList.get(1)->getData();
toEncode.setRoot(&node_root);
}
full code for the main.cpp here: https://pastebin.com/Uw5g9s7j.
When I try run this, the program read the bytes from the file, group each character by frequency and order the list, but when I try generate the huffman tree, I am unable to traverse this tree, always falling into a infinte loop (the method get stuck in the nodes containing the 2 first items from the priorityQueue above).
I tried the tree class with BinaryTree<int>, and everything works fine in this case, but with the code above the issue happens. The code for the tree is this (in the code, previous == left and next == right - I am using here the same Node class already implemented for my List class): https://pastebin.com/ZKLjuBc8.
The code for the List used in this example is: https://pastebin.com/Dprh1Pfa. And the code for the Node class used for both the List and the BinaryTree classes is: https://pastebin.com/ATLvYyft. Anyone can tell me what I am missing here? What I am getting wrong here?
UPDATE
I have tried a version using only c++ stl (with no custom List or BinaryTree implementations),but the same problem happened. The code is that: https://pastebin.com/q0wrVYBB.
Too many things to mention as comments so I'm using an answer, sorry:
So going top to bottom through the code:
Why are you defining all methods outside the class? That just makes the code so much harder to read and is much more work to type.
Node::Node()
NULL is C code, use nullptr. And why not use member initialization in the class?
class Node {
private:
T data{};
Node * previous{nullptr};
Node * next{nullptr};
...
Node::Node(Node * node) {
What is that supposed to be? You create a new node, copy the value and attach it to the existing list of Nodes like a Remora.
Is this supposed to replace the old Node? Be a move constructor?
Node::Node(T data)
Write
Node<T>::Node(T data_ = T{}) : data{data_} { }
and remove the default constructor. The member initialization from (1) initializes the remaining members.
Node::Node(T data, Node * previous, Node * next)
Again creating a Remora. This is not inserting into an existing list.
T Node::getData(), void Node::setData(T value)
If everyone can get and set data then just make it public. That will also mean it will work with cons Node<T>. Your functions are not const correct because you lack all the const versions.
Same for previous and next. But those should actually do something when you set the member. The node you point to should point back to you or made to do so:
void Node::setPrevious(Node * previous) {
// don't break an existing list
assert(this->previous == nullptr);
assert(previous->next == nullptr);
this->previous = previous;
previous->next = this;
}
Think about the copy and move constructors and assignment.
Follow the rule of 0/3/5: https://en.cppreference.com/w/cpp/language/rule_of_three . This goes for Node, List, ... all the classes.
List::List()
Simpler to use
Node<T> * first{nullptr};
List::~List()
You are deleting the elements of the list front to back, each time traversing the list from front till you find index number i. While horrible inefficient the front nodes have also already been deleted. This is "use after free".
void List::insert(T data)
this->first = new Node<T>();
this->first->setData(data);
just write
first = new Node<T>(data);
And if insert will append to the tail of the list then why not keep track of the tail so the insert runs in O(1)?
void List::update(int index, T data)
If you need access to a list by index that is a clear sign that you are using the wrong data structure. Use a vector, not a list, if you need this.
void List::remove(int index)
As mentioned in comments there are 2 memory leaks here. Also aux->next->previous still points at the deleted aux likely causing "use after free" later on.
int List::size()
Nothing wrong here, that's a first. But if you need this frequently you could keep track of the size of the list in the List class.
Node * List::get(int index)
Nothing wrong except the place where you use this has already freed the nodes so this blows up. Missing the const counterpart. And again a strong indication you should be using a vector.
void List::set(int index, Node * value)
What's this supposed to do? Replace the n-th node in a list with a new node? Insert the node at a specific position? What it actually does it follow the list for index steps and then assign the local variable aux the value of value. Meaning it does absolutely nothing, slowly.
int List::find(T data)
Why return an index? Why not return a reference to the node? Also const and non-const version.
void List::sort()
This code looks like a bubblesort. Assuming it wasn't totaly broken by all the previous issues, would be O(n^4). I'm assuming the if(jMin != i) is supposed to swap the two elements in the list. Well, it's not.
I'm giving up now. This is all just the support classes to implement the BinaryTree, which itself is just support. 565 lines of code before you even start with your actual problem and it seems a lot of it broken one way or another. None of it can work with the state Node and List are in. Especially with copy construction / copy assignment of lists.

Linked Lists in another Linked list

I'm trying to make a List that contains another linked lists and then I want to concatenate them into one list. I have some difficulties with this. So first I make this:
typedef List DList; - It makes a type of linked lists;
Then for example I make DList A and B. I insert some numbers like 1,2,3... in both of them;
Then I add them in the main linked list which is like:
List<DList> L;
L.Add_Node(A);
L.Add_Node(B);
And everything seems to be fine at this stage of the program. After this I'm trying to make a function to concatenate the separete Linked lists. I make a new List NewList where the values will be stored. And here comes my problem. I don't know how to write the function.
I make something like this: First I make a function that will loop the nodes in the L list(there are the two little lists). Then I go to my concatenation function. You can see them in the code below:
template<class T>
void Start(List<T> L, List<T> NewList)
{
List<T> *temp = L.start_ptr; //I get the position of the first element;
while(temp)
{
NewList = Concat(NewList, temp->data);
temp = temp->next;
}
}
template<class T>
List Concat(List<T> L1, List<T> L2)
{
List<T> *temp1, *temp2;
List<T> NewList;
temp1 = L1.start_ptr;
temp2 = L2.start_ptr;
while(temp1)
{
NewList.Add_Node(temp1->data);
temp1 = temp1->next;
}
while(temp2)
{
NewList.Add_Node(temp2->data);
temp2 = temp2->next;
}
return NewList;
}
These are my functions. Maybe they are completely wrong... The compiler gives me error that the members start_ptr, data and next are private(And it's true). It gives me much more errors.. Something like this is written in the book from which I'm learning, but it is so complicated there... If you don't want to spend you time in helping me I will be thankful even if you give me a good source from which I can read more about this type of Lists.
In your function start, you are going through two List of type T.
But then, you're concatenating a whole list with a value of the other list, while you're concatenating two lists in your Concat method.
Also, you are passing the parameters by copy, which probably not something you want to do.
I think what you meant to do is something like that :
void Start(List< List <T> > & L, List<T> &NewList)
Passing by copy means that your program send a copy of the parameter to your function.
It means that the list you pass will be copied (which can be pretty heavy, if your list is big), and that only the copy will be modified.
On the new version of the Start function that I gave you, you can notice that I added &. It means that the value is passed by reference. Basically, it means that it is actually your object being used, and not a copy.
Finally, about the members being private, you should add public accessors, so that they can be used outside of you class.
In your case, you can add a public method in your class :
template<class T>
const List<T> *get_start_ptr() const
{
return (start_ptr);
}
And then add public methods to move, like :
template<class T>
const List<T> *next() const
{
return (next);
}
The accessor returns the value as const, to be sure that they are not involuntary modified during the process. Even if you obviously don't modify it in your code, it is a good practice to use constness as much as possible, and to be explicit when you actually want to modify a value.

Custom iterator on a tree structure in c++

I am implementing a tree structure in c++ with a node class like this:
class Node {
protected:
// relations
Node *_parent;
std::vector<Node*> _children;
public:
// some example method
void someMethod(Node *node) {
// do something with *node
for (int i = 0; i < node->_children; i++) {
_children[i]->myFunction;
}
}
}
Now, to work on the nodes in my tree I am implementing recursive functions like someMethod in my example.
It works, but I end up writing the same recursion code over and over again for every new function that works on my tree.
Is there a generic way to iterate a tree structure like I would on a plain array?
Some method that returns the next object, until I'm done with the whole branch.
EDIT:
Thanks to everybody who has commented so far, with your help I could narrow down the problem.
From my understanding (I'm new to c++), I need an iterator class that encapsulates the code for traversing my tree.
Accessing all tree members should be as simple as that:
for (Node<Node*>::iterator it = _node.begin(); it != _node.end(); ++it) {
Node *node = *it;
// do something with *node
}
Now the question is:
How do I implement such an iterator?
Pass a function pointer to the recursive function that returns the node that you are seeking.
This is the power of function pointers and function pointer arrays in C/C++.
Many function do not simply iterate over all nodes, if the tree is (normally) sorted, then to find the largest value you will only look in the right subtree.
If you search the minimum it is in the left most subtree.
Therefore not always it makes sense, to have an iterator that iterates the whole tree.
But if you need exactly to iterate over all nodes, you can use function pointers, or the Visitor Pattern (Erich Gamma, Design Patterns).

Better to use a grounded list, or no?

I'm a csci student at Colorado Mesa University. The department head teaches a grounded method for linked lists:
struct nodeType
{
int id;
nodeType *link;
};
void createList(nodeType *&head, nodetype *&tail)
{
head = new nodetype;
tail = new nodetype;
head->id=-1; //some initialize value
head->link=tail;
tail->link=NULL;
}
void insertList(nodeType *&head, nodeType *&tail)
{
nodetype *knew,*prior, *next;
knew = new nodetype;
knew ->name = name
prior = head;
next = head->link;
while(next != tail && knew->id > next->id)
{
prior = next;
next = next->link;
}
prior->link = knew;
knew->link = next;
}
She teaches this for obvious reasons. With the grounded head and tail, It's easier to insert from, as you call the above function, and then write a function to append all the data inside those two nodes, and it's slightly easier when writing your delete function, as you never delete head or tail, and thus it makes it harder to lose the list and create garbage.
My algorithms professor says that everywhere else that I encounter lists "in the real world," a non-grounded list would be better. Other languages, using the STL and on the internet, I wouldn't find list functions that implement a head and tail.
I just want to be prepared for programming in the actual real world, not what my professors think is the real world, so my question is this: Is it better to use one or the other, to use whichever I find easier, or to approach each problem with both in mind?
Thank you in advance for your time helping me resolve this feud.
In "the real world", you will use a list that other programmers have designed, implemented, optimized, and tested, and you won't ever know whether it is "grounded", since that is just an implementation detail.
What's important to take away from your algorithms courses is:
Performance characteristics. Does a linked-list or vector have faster random-access? Faster append? Faster removal of the first element? Using the right container is NOT premature optimization.
Seeing enough different implementation styles so that if you ever have to step through your code with a debugger, you won't be royally confused. If you saw the at-end-of-list test return true, but the next-node pointer isn't NULL, you'd probably be really confused if you'd never seen a "grounded" list implementation before.

Pointing to the first object in a linked list, inside or outside class?

Which of these is a more correct way to store the first object in a linked list?
Or could someone please point out the advantages/disadvantages of each. Thanks.
class Node
{
int var;
Node *next;
static Node *first;
Node()
{
if (first == NULL)
{
first = this;
next = NULL;
}
else
//next code here
}
}
}
Node* Node::first = NULL;
new Node();
-- OR --
class Node
{
int var;
Node *next;
Node()
{
//next code here
}
}
Node* first = new Node();
The latter is definitely preferable. By making the first node pointer a static class member, you are basically saying that there will only be a single linked list in your whole program.
The second example lets you create several lists.
The first example has the definite drawback of only being able to create a single linked list in your entire program, so I wouldn't do that.
The second works fine, but doesn't shield the user of the class from how the linked list works. It would be better to add a second class, for example named LinkedList, that stores the 'first' pointer and performs list management.
Even better, you could use std::list instead.
It's most usual to have a separate List class and a separate Node class. Node is usually very simple. List holds a pointer to the first Node and implements the various list operations (add, remove, find and so on).
Something like the following
class List
{
public:
List()
{
first = new Node();
}
void insert(int val);
void remove(int val);
// ... and so on
~List()
{
// ... clean up
}
private:
struct Node
{
int val;
Node* next;
Node(int val_ = 0, Node* next_ = 0)
: val(val_), next(next_)
{}
};
Node* first;
};
Note that you can place Node outside List if you want to, but this usually doesn't make much sense.
Presumably you may have more than one list? In which case, the static option is a non-starter.
You definitely don't want the "first" to be a static. This implies there's only one linked list in your entire program. static means that every Node in every linked list in your entire program has the same beginning.
That being said you want your Node to have the fewest responsibilities-- It make sense for it to store its value and be able to get to the next Node. It adds complexity to add the job of1 maintaining the "first" pointer. For example what happens when you insert a new element at the beginning? Then you'd have to update everyone's "first" pointer. Given the two choices above I'd chose the second choice.
I would furthermore add a third choice. Add a "linked list" wrapper that gave you easy access to "first", "last" and allow you to easily insert into and iterate through the list. Something like:
class LinkedList
{
Node* First;
Node* Last;
public:
Node* GetFirst() {return First;}
Node* GetLast() {return Last;}
// insert after "where"
void Insert(Node* where, Node* newNode);
...
}
Not uselessly limiting your code to a single list instance is one very good argument for code variant 2.
However, just from superficially looking at the two examples, the sheer number of lines of code also gives a good indication that variant 2 has merits over variant 1 by being significantly shorter.