I'm learning C++ and experimenting with it. Now, I have came to a point where I don't really like one of my solutions.
#include <iostream>
using namespace std;
//template<class T>
class List{
public:
struct ListElem {
ListElem(int iElem, ListElem* iNext, ListElem* iPrev): mElem(iElem), pNext(iNext), pPrev(iPrev){
if(pNext != nullptr){
pNext->pPrev = this;
}
if(pPrev != nullptr){
pPrev->pNext = this;
}
}
friend ostream& operator<<(ostream& os,const ListElem& crArg) {
os << " " << crArg.mElem;
if (crArg.pNext)
os << *crArg.pNext;
return os;
}
public:
int mElem;
ListElem* pNext;
ListElem* pPrev;
};
void push_front(int iElem){
if(mHead == nullptr){
mTail = mHead = new ListElem(iElem,mHead,nullptr);
}else{
mHead = new ListElem(iElem,mHead,nullptr);
}
}
void push_back(int iElem){
if(mTail == nullptr){
mHead = mTail = new ListElem(iElem,nullptr,mTail);
}else{
mTail = new ListElem(iElem,nullptr,mTail);
}
}
void invert(){
for(ListElem* elem = mHead; elem != nullptr; elem = elem->pPrev){
ListElem* tmp = elem;
tmp = elem->pNext;
elem->pNext = elem->pPrev;
elem->pPrev = tmp;
}
ListElem* pTmpTail = mTail;
mTail = mHead;
mHead = pTmpTail;
}
friend ostream& operator<<(ostream& os,const List& crArg) {
if (crArg.mHead)
os << *crArg.mHead;
return os;
}
private:
ListElem* mHead = nullptr;
ListElem* mTail = nullptr;
};
int main(){
List l;
l.push_back(1);
l.push_front(10);
l.push_back(40);
l.push_back(30);
// l.push_front(10);
// l.push_front(20);
// l.push_back(30);
cout << l << endl;
l.invert();
cout << l << endl;
return 0;
}
This is my code and I want to invert the list. My function works invert() but it's ugly and, to me, not very good. It's a task that I found and it says: I can only go 1 time through the List and don't use any other helper list or dynamic data structure. Also, it should work for even and odd elements of the list.
What do you think? is there a better way to solve this. Maybe smarter and more readable?
void invert(){
ListElem* lo = mHead;
ListElem* hi = mTail;
while (lo != hi && //have not met
lo->pPrev != hi) // have not crossed
{
std::swap(lo->mElem, hi->mElem);
lo = lo->pNext;
hi = hi->pPrev;
}
}
What this does:
Points lo and hi at the beginning and end of the list
Tests that lo and hi have not yet converged.
Empty list case handled lo and h are both pointing NULL and equal
1 item case handled lo and hi are both pointing to the same node and equal.
Swaps the data at lo and hi's nodes. It does not swap the nodes. For an int, it's much easier to swap the data than to it is to change the 4 links that must be updated. For larger data, this may not hold, but the complexity of the function goes way up. Your call as to whether or not it would be worth it.
Re-points lo and hi to bring them closer to convergence.
Go to 2.
Because the data in the list swaps its way to convergence, there are never more than length / 2 iterations.
The code seems fine to me, but if you want to make thing look better, you can use std::swap.
for(auto elem = mHead; elem; elem = elem->pPrev)
std::swap(elem->pNext, elem->pPrev);
std::swap(mHead, mTail);
Related
There is an issue with my code. I need to write a program that creates a linked list and performs insertion, deleting from the beginning, deleting from the end, and printing. Everything in the program works fine, but the delete the first node function. It throws an error in the printing function (posted a picture of the error below). Does anyone know what seems to be the problem? The function that deletes the last node works and prints perfectly.
LINKED LIST PROGRAM:
struct Node {
int data;
Node* next;
};
void insert(Node** head,int n) //insertion method
{
Node* newNode = new Node;
newNode->data = n;
newNode->next = (*head);
(*head) = newNode;
}
Node* deleteFront(struct Node* head)//deleting first node in the list
{
if (head == NULL)
return NULL;
else
{
Node* t = head;
head = head->next;
free(t);
t = NULL;
}
return head;
}
Node* deleteEnd(struct Node* head)//deleting last node in the list
{
if (head == NULL)
return NULL;
else if (head->next == NULL) {
free(head);
head = NULL;
}
else {
Node* prev = head;
Node* prev2 = head;
while (prev->next != NULL)
{
prev2 = prev;
prev = prev->next;
}
prev2->next = NULL;
free(prev);
prev = NULL;
}
return head;
}
void printLL(Node* h)
{
while (h != NULL)
{
cout << h->data << " ";
h = h->next;
}
cout << endl;
}
int main()
{
cout << "Linked list question 2: " << endl;
//linked list question 2
Node* n = NULL;
insert(&n, 60);
insert(&n, 40);
insert(&n, 20);
printLL(n);
deleteFront(n);
cout << "after deleting first node: ";
printLL(n);
deleteEnd(n);
cout << "after deleting last element: ";
printLL(n);
}
A picture of the error:
error
output
Take it easy. I read your code and there are no errors in logic. However, there are some mistakes in the selection of parameters. It is not necessary to use ** in the insert. Using * can meet the requirements, and use & to achieve assignment to the linked list. The same is true for deleteFront and deleteEnd. I modified your code and now the program can run normally, hope it helps.
#include<iostream>
using namespace std;
struct Node {
int data;
Node* next;
};
void insert(Node*& head, int n) //insertion method
{
Node* newNode = new Node;
newNode->data = n;
newNode->next = head;
head = newNode;
}
Node* deleteFront(struct Node*& head)//deleting first node in the list
{
if (head == NULL)
return NULL;
else
{
Node* t = head;
head = head->next;
free(t);
t = NULL;
}
return head;
}
Node* deleteEnd(struct Node*& head)//deleting last node in the list
{
if (head == NULL)
return NULL;
else if (head->next == NULL) {
free(head);
head = NULL;
}
else {
Node* prev = head;
Node* prev2 = head;
while (prev->next != NULL)
{
prev2 = prev;
prev = prev->next;
}
prev2->next = NULL;
free(prev);
prev = NULL;
}
return head;
}
void printLL(Node* h)
{
while (h != NULL)
{
cout << h->data << " ";
h = h->next;
}
cout << endl;
}
int main()
{
cout << "Linked list question 2: " << endl;
//linked list question 2
Node* n = NULL;
insert(n, 60);
insert(n, 40);
insert(n, 20);
printLL(n);
deleteFront(n);
cout << "after deleting first node: ";
printLL(n);
deleteEnd(n);
cout << "after deleting last element: ";
printLL(n);
}
Since you're returning head in deleteFront(n) and deleteLast(n), however you're not updating head in main(). That's why its n is pointing to some garbage memory. Update your main() by storing head in n variable.
int main()
{
cout << "Linked list question 2: " << endl;
//linked list question 2
Node* n = NULL;
insert(&n, 60);
insert(&n, 40);
insert(&n, 20);
printLL(n);
n = deleteFront(n);
cout << "after deleting first node: ";
printLL(n);
n = deleteEnd(n);
cout << "after deleting last element: ";
printLL(n);
}
The bugs in your code have been mentioned in other answers and there were proposals to fix.
I would like to add an additional observation regarding your design of the Linked List. In standard implementations, Node is not visible to the outside world. The Node is not the LinkedList. The linked list contains Nodes. So, you would create a class List and it would contain the definition of a Node and a head pointer to the first node instance.
Then you would add all you functions as methods to the outer class List. These methods would work with the internal Node-chain. According to object oriented model you would encapsulate the interna of the methods and expose only what is needed to the outside world.
What you should also note is that your list is a forward list only. It has only one link to the next element. This makes some operations difficult, because you may need to always go from the beginning the list through the element what you what operate on. See your function delete_end. Here you even need to remember the previous element.
In double linked list, you could simply access also the previous element.
Therefore, if you check the CPP reference for a std::forward_list, you will find some maybe strange sounding functions like insert_after or erase_after or an iterator before_begin. This is all the result of having just forward references. A function like delete_last which would be pop_back in CPP language, is even not existing.
Therefore you maybe need to confirm, if you should implement a singly linked list or maybe a double linked list.
To make this more visible for you, I created some complete example code for a singly linked list for you.
Here I added also simple iterator functionality, which allows to use the class in a convenient way, e.g. with range based for loops or std::algorithms.
You may take this code to get some ideas for your own implementation.
#include <iostream>
#include <iterator>
#include <initializer_list>
#include <algorithm>
// Very simple implementation of a forward list
class SinglyLinkedList {
// The node
struct Node {
int data{}; // Data. Would normally be a templated argument
Node* next{}; // And the pointer to the next node
Node(int i, Node* n=nullptr) : data(i), next(n) {}; // Simple constructor to set a value and next pointer
};
Node* head{}; // This is the start of the list
// It would be advisable to have a tail pointer. We use the more inefficient approach here
Node* getLast() { Node* n{ head }; while (n and n->next) n = n->next; return n; }
public:
// Constructor / Destructor --------------------------------------------------------------------------------------------------------
~SinglyLinkedList() { clear(); }
// Default constuctor
SinglyLinkedList() {} // Default
// From an initialization list
SinglyLinkedList(const std::initializer_list<int>& il) { clear(); for (const int i : il) push_back(i); } // From initializer list
// Copy constructor
SinglyLinkedList(const SinglyLinkedList& other) { clear(); for (const int i : other) push_back(i); }
// Move constructor. Will steal the elements from the other
SinglyLinkedList(SinglyLinkedList&& other) noexcept { head = other.head; other.head = nullptr; }
// Assignment operator
SinglyLinkedList& operator = (const SinglyLinkedList& other) { clear(); for (const int i : other) push_back(i); }
// Move assignment operator
SinglyLinkedList& operator = (SinglyLinkedList&& other) { head = other.head; other.head = nullptr; }
// Housekeeping --------------------------------------------------------------------------------------------------------------
void clear() { Node* tmp{ head }; while (tmp) { Node* toDelete{ tmp }; tmp = tmp->next; delete toDelete; } head = nullptr; }
int empty() { return head == nullptr; }
int size() { int k{}; Node* n{ head }; while (n) { ++k; n = n->next; } return k; }
// Modify content --------------------------------------------------------------------------------------------------------------
void push_front(int i) { Node* n = new Node(i); n->next = head; head = n; };
void push_back(int i) { Node* n = new Node(i); Node* l = getLast();if (l) l->next = n; else head = n; }
void pop_front() { if (head) { Node* tmp = head->next; delete head; head = tmp; } }
void pop_back() { // This is a little bit more difficult in a singly linked list
if (head) {
Node* n{ head }, *previous{};
while (n and n->next) {
previous = n;
n = n->next;
}
delete n;
if (previous)
previous->next = nullptr;
else
head->next = nullptr;
}
}
// Access elements --------------------------------------------------------------------------------
int front() { return head ? head->data : 0; };
int back() { Node* n = getLast(); return n ? n->data: 0; }
// Add iterator properties to class ---------------------------------------------------------------
struct iterator { // Local class for iterator
Node* iter{}; // Iterator is basically a pointer to the node
// Define alias names necessary for the iterator functionality
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = int;
using pointer = int*;
using reference = int&;
// Constructor
iterator() {}
iterator(Node* n) : iter(n) {}
// Dereferencing
reference operator *() const { return iter->data; }
pointer operator ->() const { return &iter->data; }
// Aithmetic operations
iterator& operator ++() { if (iter) iter = iter->next; return *this; }
iterator operator ++(int) { iterator temp{ *this }; ++* this; return temp; }
iterator operator +(const difference_type& n) const { iterator temp{ *this }; difference_type k{ n }; while (k--)++temp; return temp; }
iterator& operator +=(const difference_type& n) { difference_type k{ n }; while (k--)++* this; return *this; };
// Comparison
bool operator != (const iterator& other) const { return iter != other.iter; }
bool operator == (const iterator& other) const { return iter == other.iter; }
bool operator < (const iterator& other) const { return iter < other.iter; }
bool operator > (const iterator& other) const { return iter > other.iter; }
bool operator <= (const iterator& other) const { return iter <= other.iter; }
bool operator >= (const iterator& other) const { return iter >= other.iter; }
// Difference. Also complicated, because no random access
difference_type operator-(const iterator& other) const {
difference_type result{};
Node* n{ iter };
while (n and n != other.iter) {
++result;
n = n->next;
}
return result;
}
};
// Begin and end function to initialize an iterator
iterator begin() const { return iterator(head); }
iterator end() const { return iterator(); }
// Functions typcical for forward lists ----------------------------------------------------------------------
// Easy, becuase we can operate form the current iterator and do not need the "previous" element
iterator insertAfter(iterator& pos, const int i) {
iterator result{};
if (pos.iter and pos.iter->next) {
Node* n = new Node(i, pos.iter->next);
pos.iter->next = n;
result = n;
}
return result;
}
iterator eraseAfter(iterator& pos) {
iterator result{};
if (pos.iter and pos.iter->next) {
Node* tmp = pos.iter->next->next;
delete pos.iter->next;
pos.iter->next = tmp;
result = pos.iter->next;
}
return result;
}
};
// Test/Driver Code
int main() {
// Example for initilizer list
SinglyLinkedList sllbase{5,6,7,8,9,10,11,12,13,14,15};
// Show move constructor
SinglyLinkedList sll(std::move(sllbase));
// Add some values in the front
sll.push_front(4);
sll.push_front(3);
sll.push_front(2);
sll.push_front(1);
// Delete 1st element (Number 1)
sll.pop_front();
// Delete last element
sll.pop_back();
// Use a std::algorithm on our custom linked list. Works because we have an interator
SinglyLinkedList::iterator iter = std::find(sll.begin(), sll.end(), 8);
// Now add an element after 8
iter = sll.insertAfter(iter,88);
// End delete the 9
iter = sll.eraseAfter(iter);
// Use range based for loop. Works because, we have iterators
for (int i : sll)
std::cout << i << ' ';
}
I'm new to C++ and having some difficultly with the use of shared ptrs. I've been able to construct a linked list. I want to traverse the linked list, and when the nodes (elements) have a valid to_add field, to add the element into the list, and continue.
class Element{
public:
char el = 'Z';
std::shared_ptr<Element> next;
char to_add = 'Z';
Element(char input){
el = input;
next = nullptr;
}
};
^ structure of node. I'm looking at the to_add field to see if there's an element to add in.
class Polymer{
public:
std::vector<Instruction> instruction;
std::shared_ptr<Element> extract_and_store_input(std::ifstream &file);
void prepare_insertion(std::shared_ptr<Element> head);
void insert_elements(std::shared_ptr<Element> head);
Polymer(std::ifstream &file){
std::shared_ptr<Element> head = extract_and_store_input(file);
prepare_insertion(head);
insert_elements(head);
}
};
^ calling code format
v problem is somewhere here
std::shared_ptr<Element> add_element(std::shared_ptr<Element> head_cpy){
auto tmp = head_cpy->next;
head_cpy->next = std::make_shared<Element>(head_cpy->to_add);
head_cpy->next = tmp;
return tmp;
}
void Polymer::insert_elements(std::shared_ptr<Element> head) {
auto trav = head;
auto tmp= head;
// for (int i = 0; i < num_steps; i ++)
while (trav->next != nullptr) {
std::cout<<trav->el<<std::endl;
if (trav->to_add != 'Z'){
std::cout<<"adding"<<trav->to_add<<std::endl;
trav=add_element(trav);
trav=trav->next; // progress forward twice
}
trav=trav->next;
}
// while (tmp->el != 'Z'){
// std::cout<<tmp->el<<std::endl;
// tmp=tmp->next;
// }
}
I think that the issue may be that the pointer doing the traversal (trav) is updating the list itself, rather than progressing through the list? I would really appreciate any insights!
If anyone recognises the q, it's from AoC day 14 :) I'm sure there are better ways to do it, but I'd like to understand the problem here first!
I am trying to dig into data structures in C++. Therefore I am learning how to write a list. Everything seemed to be working just fine until it came to overloading sum operator +. For two given lists it sums two of the highest values of the lists.
Here is .h file:
typedef struct rob{
int value;
struct rob* next;
}element;
class list{
public:
friend list& operator+(list&,list&);
friend void merge(list& x,list& y);
void show();
bool search(int x);
void append(int x);
bool sortAppend(int x);
list& operator--(int);
bool empty() { return (inf.head==nullptr);}
void clear() { inf.head = nullptr; }
list() { inf.head = inf.tail = nullptr; }
~list() { while(!empty()) { (*this)--;}}
private:
typedef struct{
element* head;
element* tail;
}info;
info inf;
};
I know that in an .h file the typedef may seem a bit C-like, but the header design is copied from the book that I am learning from. I am trying to crack the methods by my own though using authors ideas.
And relevant function definitions:
#include "list.h"
bool list::sortAppend(int x){
element* newElem = new element;
newElem->value = x;
if (empty()){
inf.head=inf.tail=newElem;
newElem->next=nullptr;
return true;
}
else if ( (newElem->value) < (inf.head->value) ){
newElem->next=inf.head;
inf.head=newElem;
return true;
}
else if ( (newElem->value) > (inf.tail->value) ) {
newElem->next=nullptr;
inf.tail->next=newElem;
return true;
}
element* tempHead = inf.head;
while(tempHead!=inf.tail){
if ( (newElem->value) < (tempHead->next)->value) {
newElem->next = (tempHead->next);
tempHead->next = newElem;
return true;
}
else{
tempHead = tempHead->next;
}
}
return false;
}
list& operator+(list& X, list& Y){
list* tempListArr[2] = {&X, &Y};
list* tempList = new list;
for(const list* i: tempListArr)
{
element* tempHead = (i->inf).head;
while(tempHead!= nullptr){
tempList->sortAppend(tempHead->value);
tempHead = tempHead->next;
}
tempList->show();
std::cout << "--\n";
}
return *tempList;
}
For given list containing values:
#include <iostream>
#include "list.cpp"
int main(){
list myList;
myList.sortAppend(5);
myList.sortAppend(2);
myList.sortAppend(4);
list myList2;
myList2.sortAppend(21);
list myList3;
myList3 = myList + myList2;
return 0;
}
Could anyone point me where I made a mistake? I am stuck for a few hours now and I don't know what goes wrong.
Many thanks in advance!
FOLLOW UP:
The sortAppend method surely works. It does create a sorted list as desired.
There must have been something wrong with the + operator definition itself though I have tried, instead of range loop, using for loop for one iteration and still I got a list of two values only.
You are simply not setting inf.tail to the new tail in
else if ((newElem->value) > (inf.tail->value)) {
newElem->next = nullptr;
inf.tail->next = newElem;
inf.tail = newElem; // <-- missing!
return true;
}
You should - at least - change the signature of operator+ to return a list instead of a list reference and return a local object instead of an unowned heap object (which is a memory leak). If you do so you will have to write a copy constructor and copy assignment operator too.
Given your code,
list myListWierd;
myListWierd.sortAppend(2);
myListWierd.sortAppend(4);
myListWierd.sortAppend(5);
myListWierd.show();
shows
2
5
so the sortAppend does not work.
The trouble is around updating either the tail, since operator + relies on using the tail.
I could sort the code out for you and make it work; indeed Andreas' answer does this. But for now, notice you have assumed a function works, but I found a case it doesn't work for by looking at the moving parts - a list we created, that we then try to re-create in a different order. As a general rule, try all the parts in a function that goes wrong, one at a time, maybe as a unit test.
Rather than fixing this, for now, let's make a couple of suggestions.
First, the destructor does nothing, other than walk pointers (using empty which uses head and not tail - so head needs setting as said before)
~list() { while (!empty()) { (*this)--; } }
If you don't want leaks you need to give this more thought.
Next,
list& operator+(list&, list&)
creates a pointer and returns its contents. This is a BAD IDEA. NEVER DO THIS.
For now, change the signature to
list operator+(list&, list&);
and just return a list:
list operator+(list& X, list& Y) {
list* tempListArr[2] = { &X, &Y };
list tempList;//copy it over to the calling vode otherwise DANGER
for (const list* i : tempListArr)
{
element* tempHead = (i->inf).head;
while (tempHead != nullptr) {
tempList.sortAppend(tempHead->value);
std::cout << "Adding " << tempHead->value << '\n';
tempHead = tempHead->next;
}
tempList.show();
std::cout << "--\n";
}
return tempList;
}
I am trying to make a linked list but am running into problems because I am deleting my nodes twice. The problem only arises when a node is passed into a function (if it is passed by reference everything is fine) which leads me to believe that the object being passed into the function is being copied in such a way that the pointers are pointing to nodes from the original list not the new list. I tried to get around this by overloading the = operator but this didn't work either. An explanation of what I'm doing wrong would be great.
Thanks for the help
#include <iostream>
struct node{
node(int n){
if (n == 1){
data = 1;
next = NULL;
}
if (n == 2){
data = 2;
next = new node(1);
next -> next = NULL;
}
}
~node(){
std::cout << data << std::endl;
if (next != NULL) delete next;
}
void operator=(node a){
next = NULL;
}
int data;
node* next;
};
void func2(node v){
}
int main(){
node v(2);
if (v.next -> next == NULL) std::cout << "true\n";
func2(v);
return 0;
}
Your suspicions are correct, but therein lies the problem; when you pass the node into func2, you're only copying the first node, not the entire list. The copy constructor will copy the first node, and the pointer in the first node (which points to the original second node), so when v goes out of scope in func2 it gets deleted once, then gets deleted again when it goes out of scope of main. You'll need to write the copy constructor to do a "deep copy," traversing the entire list and copying every node into a new address.
Remember also that the copy constructor should return *this in most cases, this is in the C++ FAQ and in the book "Effective C++" by Scott Meyers. Thus the signature should be:
node& operator=(const node& node);
If you're going to overload the assignment operator, you should probably also define a copy constructor. Good job explaining the problem, by the way.
Edit: The code would look like this. I apologize that I haven't tested this; I'm on my tablet and editing this is painful...
#include <iostream>
struct node{
node(const node& toCopy) : data(toCopy.data)
{
if(toCopy.next != null) {
next = new node(toCopy);
}
}
node(int n){
if (n == 1){
data = 1;
next = NULL;
}
if (n == 2){
data = 2;
next = new node(1);
next -> next = NULL;
}
}
node& operator=(const node& toCopy) {
if(&toCopy != this) {
data = toCopy.data;
if(next != NULL) {
next = new node(toCopy);
}
}
return *this;
}
~node(){
std::cout << data << std::endl;
if (next != NULL) delete next;
}
int data;
node* next;
};
void func2(node v){
}
int main(){
node v(2);
if (v.next -> next == NULL) std::cout << "true\n";
func2(v);
return 0;
}
I'm trying to implement a linked list class in C++ and I got problem. I have the += operator who adds new node.
the linked list class interface:
template <typename Type>
class LinkedList {
public:
LinkedList<Type>* head;
// linked list stracture
Type data;
LinkedList<Type>* next;
// others ....
size_t length;
public:
LinkedList();
~LinkedList();
void initializeHead(LinkedList<Type>* headPtr);
size_t size() const;
LinkedList& operator+=(const Type& add);
void operator-=(const Type& remove);
LinkedList<Type>& operator[] (const size_t index) const;
bool operator== (const LinkedList<Type> &versus) const;
friend ostream& operator<< (ostream& out,LinkedList& obj);
};
and here i have the += overload implement:
template <typename Type> LinkedList<Type>& LinkedList<Type>::operator +=(const Type& add) {
// head ptr - :)
LinkedList<Type>* p = head->next;
// go to the end
while(p) p = p->next;
// now on end - create new..!!!
try {
p = new LinkedList<Type>;
} catch (bad_alloc& e) {
cout << "There\'s an allocation error....";
} catch (...) {
cout << "An unknown error.." << endl;
}// fill and done
p->data = add;
p->next = NULL;
// increment length .........
++head->length;
// done ............
return *p;
}
Additionally , I have "array" access overload method:
template <typename Type> LinkedList<Type>& LinkedList<Type>::operator [](const size_t index) const {
if(index < 0 || index >= length) // invaild argument
throw exception();
// continue
LinkedList<Type>* p = head;
for(size_t i = 0; i < index; ++i) p = p->next; // we are at what we want
return *p;
}
All works correctly - I checked on the dibugger,
the problem is - += doesn't save the new node in "head->next", for some reason, after finish += method, head->next equal to null.
Do someone know why the new allocation don't link to head->next?
Thanks a lot!!
after while(p) p = p->next; p is NULL
and next you do p = new LinkedList<Type>; but you don't link the p into the head.
Instead of:
// go to the end
while(p) p = p->next;
You need:
head->next = p;
As the other answers say, you go beyond the list when you try to add. Try something like this:
template <typename Type> LinkedList<Type>& LinkedList<Type>::operator +=(const Type& add)
{
LinkedList<Type> *last;
// Find the last node in the list
for (last = head; last != 0 && last->next != 0; last = last->next)
{
}
// `last` now points to the last node in the list, or is zero
// If zero (i.e. NULL) then list is empty
if (last == 0)
{
head = new LinkedList<Type>;
head->next = 0;
head->data = add;
head->length = 0;
}
else
{
last->next = new LinkedList<Type>;
last->next->next = 0;
last->next->data = add;
}
// We can safely use `head` as we are sure it won't be zero
head->length++;
// Return the added node
return (last != 0 ? *last->next : *head);
}
You can also use temporary variable to store last node and then the last node will point to new node.
This is sample code. You need to take care of some situations like adding first node etc.
LinkedList<Type>* temp = NULL;
while(p)
{
temp = p;
p = p->next;
}
try
{
p = new LinkedList<Type>;
temp->next = p;
}