template<typename B>
void linkedlist<B>::addNode(B x){
node * n = new node; //initialize new node
n->x = x;
n->next = nullptr;
if(head == nullptr){ //if the list is empty
head = (unique_ptr<node>)n; //cast the normal pointer to a unique pointer
}else{ //if there is an existing link
current = head.get(); //get the address that is being pointed by the unique_ptr head
while(current->next != nullptr) //loop until the end then stop
current = (current->next).get();
current->next = (unique_ptr<node>) n; //connect the new node to the last node
}
}
template<typename B>
void linkedlist<B>::deleteNode(B x){
current = head.get(); //set current to the head
if(current->x == x){ //head is being deleted
//tricky
head = move(head->next); //transfer the ownership of the next pointer to the head, thus freeing the first node.
//not head
} else{
while(current->x != x && current->next != nullptr){ // traverse and set traverse limits
tail = current; //set tail sa current
current= (current->next).get(); //move the current
}
if(current->next == nullptr && current->x != x){ //check if you reached the end of the node and there is no x
cout<<"value isnt here!"<<endl;
} else{ //once it founds it.
//delete operation
if(current->next != nullptr) //if there node after
tail->next = move(current->next);
else // if there is no node after.
(tail->next).reset();
current = nullptr;
}
}
}
template<typename B>
void linkedlist<B>::traverseNode(){
current = head.get(); //set current to head
if(head != nullptr){ //if the list exist
cout<<"val: "<<head->x<<endl;
while(current->next != nullptr){ //traverse
current = (current->next).get();
cout<<"val: "<<current->x<<endl;
}
}else{ //if there are no elements in the list
cout<<"there is no element in the list"<<endl;
}
}
int main() {
//initalize
linkedlist<int> l;
//add values
l.addNode(1);
l.addNode(2);
l.addNode(3);
l.addNode(4);
l.addNode(5);
//add and delete
l.traverseNode();
cout<<"deleting first value: ";
l.deleteNode(1);
cout<<"deleting third value: ";
l.deleteNode(3);
cout<<"adding new value: 6"<<endl;
l.addNode(6);
cout<<"traversing updated values.........."<<endl;
l.traverseNode();
system("pause");
return 0;
}
Output
1 2 3 4 5 6 7 8 9 10 11 12 13
val: 1
val: 2
val: 3
val: 4
val: 5
deleting the first value: a node has been freed
deleting the third value: a node has been freed
adding new value: 6
traversing updated values....................
val: 2
val: 4
val: 5
val: 6
Please check my implementation, any constructive inputs will be appreciated.
If you want a code review then please sort out your formatting (by editing you opening post, not reposting!)
Modern IDEs don't need the old 80 col max rule to be strictly applied (the default width of the console in the "old days"), but that doesn't mean really long lines of code are a good idea.
Is there something that i shouldnt have done? like bad allocations or bad practices.
Well: Never cast away an error.
What you do is a major abuse of unique_ptr. As the name imply the intention is that you have only one pointer at any time to a certain object. So don't use unique_ptr if that isn't what you want.
> As the name imply the intention is that you have only one pointer at any time to a certain object.
> So don't use unique_ptr if that isn't what you want.
The intent is that there is only one owning-pointer to an object. There can be other non-owning-pointers or references to the object owned by a unique pointer.
A few suggestions:
addNode() can be made O(1) if the value of the member node* tail; is maintained.
addNode() can support move seamantics.
(Either overloads for lvalue and rvalue references or a universal reference with perfect forwarding.)