One function for insertion anywhere? Before or after head?
This follows the same indexing suggested by coder 777 above.
Note that
index-> 0 inserts before head
index-> 1 inserts before the second node (after head)
index-> 2 inserts before the third node (after second node)
etc.
|
For insertion after the tail:
index-> N insert after tail in list with N nodes.
To help with getting the number of nodes correct, I'll include a helper function
int nodeCount(node*);
Here is some complete test code. Note: a destroy list function has also been added:
Also, because the newest insert function insert_node_all can modify the head pointer (when insertion of new head is made) we must pass pNode by reference. Please see comments within function for further reason
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
#include <iostream>
using std::cout;
struct node
{
int x;
node* link;
node( int X=0, node* Link=nullptr): x(X), link(Link) {}
};
// first version: add node at beginning of list = push_front
node* add_node( node* pHead, int X )
{
return new node(X, pHead);
}
// 2nd version: insert after existing node
void add_node( node* pNode, int X, int cnt )// cnt = 0 to N-1
{
if( pNode && cnt > 0 )
add_node( pNode->link, X, cnt-1 );
else if( pNode )// insert after this node
pNode->link = new node(X, pNode->link);// pass by value OK
}
// version 3: insert before or after any node
void add_node_all( node*& pNode, int X, int cnt )// cnt = 0 to N
{
if( cnt == 0 )// push _front
pNode = new node(X, pNode);// pass by ref needed for this
else if( pNode && cnt > 1 )
add_node_all( pNode->link, X, cnt-1 );
else if( pNode )// insert after this node
pNode->link = new node(X, pNode->link);// pass by value OK for this
}
void remove_node( node*& pHead, int cnt )
{
if( !pHead ) return;
if( cnt == 0 )
{
node* temp = pHead;
pHead = pHead->link;// reason for pass by ref
delete temp;
return;
}
remove_node( pHead->link, cnt-1 );// recursion!
}
void display_list( node* pHead )
{
if( !pHead ){ cout << "empty list\n"; return; }
while( pHead )
{
cout << pHead->x << ' ';
pHead = pHead->link;
}
cout << '\n';
}
void destroy_list( node*& pHead )// passed by ref so pHead = nullptr sticks at the end
{
int cnt = 0;
while( pHead )
{
node* temp = pHead;
pHead = pHead->link;
delete temp;
++cnt;
}
cout << cnt << " nodes destroyed\n";
}
int nodeCount( node* pNode )// recursive
{
if( !pNode ) return 0;
return 1 + nodeCount( pNode->link );
}
int main()
{
// pointer for a list
node* pHead = nullptr;// or NULL pre C++11
// add nodes
add_node_all( pHead, 10, 1 );// attempt insertion after non-existent head
display_list( pHead );// empty
add_node_all( pHead, 10, 0 );// new head
display_list( pHead );// 10
add_node_all( pHead, 5, 0 );// new head
display_list( pHead );// 5 10
add_node_all( pHead, 8, 1 );// after head
display_list( pHead );// 5 8 10
add_node_all( pHead, 15, nodeCount(pHead) );// after tail
display_list( pHead );// 5 8 10 15
add_node_all( pHead, 12, 3 );// after 10
display_list( pHead );// 5 8 10 12 15
// remove nodes
remove_node( pHead, 1 );// the 8
display_list( pHead );// 5 10 12 15
remove_node( pHead, 3 );// the 15
display_list( pHead );// 5 10 12
remove_node( pHead, 0 );// the 5
display_list( pHead );// 10 12
// cleanup!
destroy_list( pHead );// 2 nodes destroyed
return 0;
}
|
@coder777
I substituted your insert_before function for insert_node_all in above code and it works the same, except that it will add an initial head node when that 1st line
insert_before( pHead, 10, 1 );// attempt insertion after non-existent head
The function does insert a new head so we get 2 10's in the list.
My function ignores the request, but I'm not sure which behavior is best in that case anyway.
@jhykima. The matter of passing pointers by value vs. by reference depends on whether the pointer will be reassigned a value directly or not. This rule applies regardless of the variable type. If you want a function to modify an int parameter it must be passed by reference.
Any parameter passed by value is useful only for reading from. It cannot be written to. If a value is written it's to the copy produced for use in the function, not to the quantity passed.
Testing if pass by reference is necessary can be done by just removing the & symbol in the parameter list.
If the function still works then pass by reference wasn't necessary.
EDIT: A quick experiment using the shell runner here Click the wheel at the top right corner of the code, modify code as desired then click run.
Removing the & in line 27
1 2
|
// version 3: insert before or after any node
void add_node_all( node* pNode, int X, int cnt )// cnt = 0 to N. pNode pass by value now
|
results in this output
empty list
empty list
empty list
empty list
empty list
empty list
empty list
empty list
empty list
0 nodes destroyed
|
This is because no head was added (pHead stays = nullptr) since the function can't assign a new value to pNode.
Removal of the & in remove_node results in this mess:
empty list
10
5 10
5 8 10
5 8 10 15
5 8 10 12 15
5 0 10 12 15
5 0 10 72392256 15
72392320 0 10 72392256 15
|
I think it may have crashed. There's no output from the destroy_list() call.
Desired output, for reference:
empty list
10
5 10
5 8 10
5 8 10 15
5 8 10 12 15
5 10 12 15
5 10 12
10 12
2 nodes destroyed
|
EDIT: I think coder777 has the function name right. The function does insert before the indexed node.