Inserting into a binary search tree in C - c

I'm currently learning C and also some datastructures such as binary search trees etc. I have trouble understanding HOW exactly changing pointer values within a function works in some cases and in others doesn't... I'll attach some of my code I wrote. It's an insert function which inserts values in the correct places in the BST (it works as it should). I tried working with pointers to pointers to be able to change values withing a function. Even though it works, im still really confused why it actually does.
I don't quite understand why my insert function actually changes the BST even though I only work with local variables (tmp, parent_ptr) in my insert function and I don't really dereference any pointers apart from " tmp = *p2r " in the insert function.
Thanks for helping out.
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
struct TreeNode** createTree(){
struct TreeNode** p2r;
p2r = malloc(sizeof(struct TreeNode*));
*p2r = NULL;
return p2r;
}
void insert(struct TreeNode** p2r, int val){
// create TreeNode which we will insert
struct TreeNode* new_node = malloc(sizeof(struct TreeNode));
new_node -> val = val;
new_node -> left = NULL;
new_node -> right = NULL;
//define onestep delayed pointer
struct TreeNode* parent_ptr = NULL;
struct TreeNode* tmp = NULL;
tmp = *p2r;
// find right place to insert node
while (tmp != NULL){
parent_ptr = tmp;
if (tmp -> val < val) tmp = tmp->right;
else tmp = tmp->left;
}
if (parent_ptr == NULL){
*p2r = new_node;
}
else if (parent_ptr->val < val){ //then insert on the right
parent_ptr -> right = new_node;
}else{
parent_ptr -> left = new_node;
}
}
int main(){
struct TreeNode **p2r = createTree();
insert(p2r, 4);
insert(p2r, 2);
insert(p2r, 3);
return 0;
}

Let's analyze the approach step by step.
At first we consider the following simple program.
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void create( struct TreeNode *head, int val )
{
head = malloc( sizeof( struct TreeNode ) );
head->val = val;
head->left = NULL;
head->right = NULL;
}
int main(void)
{
struct TreeNode *head = NULL;
printf( "Before calling the function create head == NULL is %s\n",
head == NULL ? "true" : "false" );
create( head, 10 );
printf( "After calling the function create head == NULL is %s\n",
head == NULL ? "true" : "false" );
return 0;
}
The program output is
Before calling the function create head == NULL is true
After calling the function create head == NULL is true
As you can see the pointer head in main was not changed. The reason is that the function deals with a copy of the value of the original pointer head. So changing the copy does not influence on the original pointer.
If you rename the function parameter to head_parm (to distinguish the original pointer named head and the function parameter) then you can imagine the function definition and its call the following way
create( head, 10 );
//...
void create( /*struct TreeNode *head_parm, int val */ )
{
struct TreNode *head_parm = head;
int val = 10;
head_parm = malloc( sizeof( struct TreeNode ) );
//...
That is within the function there is created a local variable head_parm that is initialized by the value of the argument head and this function local variable head_parm is changed within the function.
It means that function arguments are passed by value.
To change the original pointer head declared in main you need to pass it by reference.
In C the mechanism of passing by reference is implemented by passing an object indirectly through a pointer to it. Thus dereferencing the pointer in a function you will get a direct access to the original object.
So let's rewrite the above program the following way.
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void create( struct TreeNode **head, int val )
{
*head = malloc( sizeof( struct TreeNode ) );
( *head )->val = val;
( *head )->left = NULL;
( *head )->right = NULL;
}
int main(void)
{
struct TreeNode *head = NULL;
printf( "Before calling the function create head == NULL is %s\n",
head == NULL ? "true" : "false" );
create( &head, 10 );
printf( "After calling the function create head == NULL is %s\n",
head == NULL ? "true" : "false" );
return 0;
}
Now the program output is
Before calling the function create head == NULL is true
After calling the function create head == NULL is false
In your program in the question you did not declare the pointer to the head node like in the program above
struct TreeNode *head = NULL;
You allocated this pointer dynamically. In fact what you are doing in your program is the following
#include <stdio.h>
#include <stdlib.h>
struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void create( struct TreeNode **head, int val )
{
*head = malloc( sizeof( struct TreeNode ) );
( *head )->val = val;
( *head )->left = NULL;
( *head )->right = NULL;
}
int main(void)
{
struct TreeNode **p2r = malloc( sizeof( struct TreeNode * ) );
*p2r = NULL;
printf( "Before calling the function create *p2r == NULL is %s\n",
*p2r == NULL ? "true" : "false" );
create( p2r, 10 );
printf( "After calling the function create *p2r == NULL is %s\n",
*p2r == NULL ? "true" : "false" );
return 0;
}
The program output is
Before calling the function create *p2r == NULL is true
After calling the function create *p2r == NULL is false
That is compared with the previous program when you used the expression &head of the type struct TreeNode ** to call the function create you are now introduced an intermediate variable p2r which stores the value of the expression &head due to this code snippet
struct TreeNode **p2r = malloc( sizeof( struct TreeNode * ) );
*p2r = NULL;
That is early you called the function create like
create( &head, 10 );
Now in fact you are calling the function like
struct TreeNode **p2r = &head; // where head was allocated dynamically
create( p2r, 10 );
The same takes place in your program. That is within the function insert dereferencing the pointer p2r you have a direct access to the pointer to the head node
if (parent_ptr == NULL){
*p2r = new_node;
^^^^
}
As a result the function changes the pointer to the head node passed by reference through the pointer p2r.
The data members left and right of other nodes are also changed through references to them using the pointer parent_ptr
else if (parent_ptr->val < val){ //then insert on the right
parent_ptr -> right = new_node;
^^^^^^^^^^^^^^^^^^^
}else{
parent_ptr -> left = new_node;
^^^^^^^^^^^^^^^^^^
}

While the pointers themselves are indeed local variables, they point to a specific location in memory. When you dereference the pointer by using the -> symbol, you're basically accessing the memory where that exact variable to which the pointer is pointing to is stored. This is why your changes are reflected outside the function as well.
You basically told a local variable where your tree is stored, it helped with the insertion, and then it went out of scope. The tree itself is not a local variable so the changes are reflected on it.
I suggest reading up on how pointers work.

First of all, always remember one thing about the pointers, they store a memory address, rather than a value. For example:
int val = 5;
int copy = val;
int *original = &val;
printf("%d\n", val);
printf("%d\n", copy);
printf("%d\n", *original);
val = 8;
printf("%d\n", val);
printf("%d\n", copy);
printf("%d\n", *original);
On executing this piece of code, the output will be
5
5
5
8
5
8
Notice, how on changing the value of val, the value of copy remains the same, and the value pointed the by original changes. This happens because the pointer original points to the memory location val.
Now, coming to the insert function, although you are only working with local variables(tmp, parent_ptr), but remember they are pointer variables, they refer to a memory address. So whenever within the loop, you traverse to tmp -> right or tmp -> left, you are actually jumping in memory from one location to another, in the correct order, that's why it works. The following example will make it more clear.
56 (A)
/ \
/ \
45 (B) 60 (C)
Consider the above BST, with the memory address in brackets. Let's insert 40 into this BST. Initially, tmp will point to A, address of 56. Now 40 is less than 56, so tmp goes to left and now points to B, address of 45. Once, again it goes to left and now it is null. But by now, parent_ptr points to B. So the new node for 40 gets attached to left of B.
56 (A)
/ \
/ \
45 (B) 60 (C)
/
/
40 (D)

Related

Why does the value of a Pointer change after a print?

#include <stdlib.h>
#include <stdio.h>
#include "sorted_tree.h"
int insert_value(int value, struct TreeNode *n) {
if (value < n->value) {
if (n->left_child == NULL) {
struct TreeNode t = {0};
struct TreeNode *tpointer = &t;
tpointer->value = value;
tpointer->left_child = NULL;
tpointer->right_child = NULL;
n->left_child = tpointer;
printf("links eingefügt\n");
}
else {
insert_value(value, n->left_child);
}
return 0;
}
else if (value > n->value) {
if (n->right_child == NULL) {
struct TreeNode t = {0};
struct TreeNode *tpointer = &t;
tpointer->value = value;
tpointer->left_child = NULL;
tpointer->right_child = NULL;
n->right_child = tpointer;
printf("rechts eingefügt\n");
}
else {
insert_value(value, n->right_child);
}
return 0;
}
else {
return 1;
}
}
void print_inorder(struct TreeNode *n) {
if (n == NULL) {
printf("r");
return;
}
else {
print_inorder(n->left_child);
printf("%d ", n->value);
print_inorder(n->right_child);
}
}
int main() {
struct TreeNode t = {0};
struct TreeNode *tpointer = &t;
tpointer->value = 5;
tpointer->left_child = NULL;
tpointer->right_child = NULL;
insert_value(6, tpointer);
printf("%d", tpointer->right_child->value);
printf("%d", tpointer->right_child->value);
}
The first printf() in the main outputs "6" which is correct, but the second one outputs a hug random nummer as if the address has been changed. The 6 should be inserted into the right child node so I expected 66 as the output. Why those this happen and how can I fix it?
struct TreeNode t={0};
struct TreeNode *tpointer=&t;
tpointer->value=value;
Those blocks of code inside the if/else if of insert_value are not correct. This is because struct TreeNode t={0}; creates an automatic variable with lifetime only within the enclosing scope. In this case, the lifetime is only within the if/else if block. Keeping a reference to the variable and using it beyond that will result in Undefined Behaviour.
The solution is to create variables that have lifetimes beyond the function. The most common way to do that is to use dynamically allocated memory:
struct TreeNode *tpointer = malloc(sizeof(*tpointer));
Don't forget to free all dynamically allocated memory when it is no longer needed.
The approach when a first node of a tree is not allocated dynamically as in your program
struct TreeNode t={0};
struct TreeNode *tpointer=&t;
tpointer->value=5;
tpointer->left_child=NULL;
tpointer->right_child=NULL;
is not good. In fact you can not create or use an empty tree.
All nodes in a tree should be allocated dynamically when it is required.
So the pointer n within the function insert_value in general can be equal to NULL for an empty tree. You need to check it. Otherwise statements like this
if(value<n->value){
can invoke undefined behavior.
Also within the function you are setting a pointer to a local object of the type struct TreeNode as for example
struct TreeNode t={0};
struct TreeNode *tpointer=&t;
After exiting the function the local object t will not be alive. So an invalid pointer will be added to the tree.
You need to allocate a new node dynamically.
Also the function in fact returns an arbitrary number 0 or 1 because the function does not return the final value of subsequent recursive calls of the function.
Also it would be logically more consistent to return 1 in case when a new node is added and 0 otherwise.
I would declare and define the function the following way
int insert_value( struct TreeNode **n, int value )
{
if ( *n == NULL )
{
*n = malloc( sizeof( struct TreeNode ) );
( *n )->value = value;
( *n )->left_child = NULL;
( *n )->right_child = NULL;
return 1;
}
else if ( value < ( *n )->value )
{
return insert_value( &( *n )->left_child, value );
}
else if ( ( *n )->value < value )
{
return insert_value( &( *n )->right_child, value );
}
else
{
return 0;
}
}
And if in main you have a pointer to the root node declared like
struct TreeNode *root = NULL;
then the function is called like
insert_value( &root, value );

Deleting a list with pointer to pointer in C

The partial code, in C, is here:
typedef struct List {
double v;
struct List *next;
} List;
void deleteList (List **p) {
*p = (*p)->next;
}
I am confused about how the deleteList function is working. So the arguement is a pointer to a pointer to a List structure. So we have:
p : pointer_2 --> pointer_1 --> List
So I have some questions:
So what is *p in the function deleteList()? Is it pointer_1 or something else?
Does *p before = mean the same as *p after the = sign?
Is there a difference between *p and (*p) ?
Say we have:
... la --> lb --> lc --> ld ....
And say we want to delete lb. I get the idea, theoretically. You alter the la->next to point to lc. But I am confused about the pointer business.
What is the argument to deleteList()?
Is it, deleteList(la->next)? Or something else?
And then the really confusing part.
*p = ... is supposed to be la->next because this is the pointer we want to alter.
But then ...(*p)->next, wouldn't this just be the lb? But we want lc? So it seems like
*p have different meaning in the same line?!
Let;s at first write the function correctly.
void deleteList( List **head )
{
while ( *head != NULL )
{
List *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
}
A pointer to the head node is passed to the function by reference.
If you will define the function like
void deleteList( List *head )
{
while ( head != NULL )
{
List *tmp = head;
head = head->next;
free( tmp );
}
}
that is if the pointer will not be passed by reference then the function will deal with a copy of the pointer. Changing a copy does not influence on the original pointer.
Consider the following demonstrative program.
#include <stdio.h>
#include <stdlib.h>
void f( int *p )
{
p = NULL;
}
int main(void)
{
int x = 10;
int *px = &x;
printf( "Before the function call px = %p\n", ( void * )px );
f( px );
printf( "Adter the function call px = %p\n", ( void * )px );
return 0;
}
Its output might look like
Before the function call px = 0x7ffe26689a2c
Adter the function call px = 0x7ffe26689a2c
That is the original pointer px was not changed because the function dealt with a copy of the pointer.
To change the pointer you need to pass it to the function by reference
#include <stdio.h>
#include <stdlib.h>
void f( int **p )
{
*p = NULL;
}
int main(void)
{
int x = 10;
int *px = &x;
printf( "Before the function call px = %p\n", ( void * )px );
f( &px );
printf( "Adter the function call px = %p\n", ( void * )px );
return 0;
}
Now the program output might look like
Before the function call px = 0x7ffed60815fc
Adter the function call px = (nil)
Within the function you need to dereference the parameter to get the access to the passed by reference pointer.
*p = NULL;
^^^^
The same occurs in the function deleteNode. To check whether the passed pointer is equal to NULL there is used the following statement
while ( *head != NULL )
^^^
To access the data member next of the node pointed to by the origibal pointer you again have to dereference the parameter to get access to the original pointer
*head
So this expression yields the original pointer. So to access the data member next you have to write
( *head )->next
You are using the parentheses because the postfix operator -> has a higher priority but you need at first to get the original pointer.
That is if you had no a referenced pointer you would write
head->next
But when you have a referenced pointer that is when you have a pointer to an original pointer then to get the original pointer you have to derefernce the referenceing pointer like
( *head )->next
You could write the function without accepting the pointer to the head node by reference. But in this case you should to add in the caller one more statement that will set the pointer head to NULL.
For example
void deleteList( List *head )
{
while ( head != NULL )
{
List *tmp = head;
head = head->next;
free( tmp );
}
}
and in the caller you need to write
List *head - NULL;
// the code thatf fills the list
deleteList( head );
head = NULL;
Or the function could return a null pointer like
List * deleteList( List *head )
{
while ( head != NULL )
{
List *tmp = head;
head = head->next;
free( tmp );
}
return head;
}
and in the caller you could write
List *head - NULL;
// the code thatf fills the list
head = deleteList( head );
The advantage of defining the function that accepts the pointer to the head node by reference is that the user of the function does not need to remember to set the pointer to NULL by himself.
in deleteList function: before you pass to the next element you must free the element you point to.
void deleteList (List **p) {
while(*p != NULL){
List *nextNode = (*p)->next;
free(*P);
*p= nextNode;
}
}

Why can't I add a node to linked list in C?

I have a problem with linked lists in C. I made a function that created a new node of the list with some information (char *description) and added it to its end. The code is following:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node {
char *description;
struct node *next;
};
// The function to create a node and append it to the linked list of nodes
struct node* create_node(struct node *first, char *description) {
struct node *current = first;
// Iteration through the list until the end
while(current != NULL) {
node++;
current = current -> next;
}
// Now pointer current points at the end of the list, first -> next. How to assign the pointer new to first -> next through current?
struct node *new = malloc(sizeof(struct container));
new -> next = NULL;
new -> description = malloc(sizeof(description));
memcpy(new -> description, description, sizeof(description));
current = new;
return current;
}
int main() {
// Creating the first node
struct node *first = create_node(NULL, "First");
// Creating and appending the second node to the list
create_node(first, "Second");
printf("%d\n", first -> next == NULL); // Prints 1, the newly created node hasn't been appended
return 0;
}
I searched how to create the list of the kind and saw very similar ways of how to do it. I know that it's something basic and most likely there's a simple solution, but I can't find it.
Thanks everyone for respond.
For starters the function name create_node is confusing. It is much better to name the function at least like append_node.
The second function parameter should have the qualifier const because the passed string is not changed in the function.
In these statements
new -> description = malloc(sizeof(description));
memcpy(new -> description, description, sizeof(description));
you are allocating memory of the size equal either to 8 or to 4 bytes depending on the value of sizeof( char * ) and correspondingly coping this number of bytes.
You have at least to write
new -> description = malloc( strlen(description));
memcpy(new -> description, description, strlen(description));
But it would be better if you were copying the whole string.
The function has a bug. It does not append a node to the list because within the function there is changed the local pointer current that is not chained to the list.
Take into account that memory allocation can fail. You should process such a situation.
The function can be safer and simpler if to pass the pointer to the head node by reference.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node
{
char *description;
struct node *next;
};
// The function to create a node and append it to the linked list of nodes
int append_node( struct node **head, const char *description )
{
struct node *new_node = malloc( sizeof( struct node ) );
int success = new_node != NULL;
if ( success )
{
new_node->description = malloc( strlen( description ) + 1 );
success = new_node->description != NULL;
if ( success )
{
strcpy( new_node->description, description );
new_node->next = NULL;
while ( *head != NULL )
{
head = &( *head )->next;
}
*head = new_node;
}
else
{
free( new_node );
}
}
return success;
}
int main( void )
{
// Creating the first node
struct node *head = NULL;
if ( append_node( &head, "first" ) )
{
printf( "%s\n", head->description );
}
return 0;
}
The program output is
first
Hi I am new at this community. Lets try to help.
I thik you are pointing to the last node of the list and changing it to the new one at line
current = new;
But to link the new node you should save it in the field next of the node, try:
current->next=new;
I hope help you, bye :).

Using double pointers in functions [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
I am currently trying to learn how linked lists as a personal project. I understand the core concepts and I have been trying to implement it into c. My program looks like it should work, keep in mind I am still new to programming :D
I created a structer pointer called head. head will point to the first node in the linked_list and startPtr will contain the address of head. Each time the function add is called a new node will be created and allocated some space in memory then the previously created node will point to the new node.
I know where my program is crashing but I can see why? It compiles fine.
My code crashes on the line
(*prevNode)->link = newNode;
This is the way I see this code:
I pass the double pointer startPtr into the function add. I then created a new node using malloc. Next I deference startPtr ( which is called prevNode in the function ) which should contain the memory address of head....right? I then use the "->" expression to point the the structure pointer inside head called link.
The program just ends at this point and I have no idea why. I have looked at other linked list c codes but most of them don't use double pointers they just declare global structers and pointers. I am using GCC as my compiler.
Anyone know why this is happening?
#include <stdio.h>
#include <stdlib.h>
// STRUCTURES
struct node
{
int data;
struct node *link;
}*head;
void add( int, struct node ** );
int main()
{
struct node *head;
struct node **startPtr;
startPtr = head;
struct node *nodePtr;
int userInput;
int inputData;
do{
printf( "\n\n1: enter new node\n" );
printf( "2: Print Nodes\n" );
printf( "\n\nEnter: " );
scanf( "%d", &userInput );
if ( userInput == 1 )
{
printf( "\n\nEnter data:");
scanf("%d", &inputData );
add( inputData, startPtr );
}
}while( userInput == 1 );
// printing linked list
nodePtr = head->link;
while( nodePtr->link != NULL )
{
printf( "%d\n", nodePtr->data);
nodePtr = nodePtr->link;
}
printf( "%d\n", nodePtr->data);
return 0;
}// END main()
void add( int num, struct node **prevNode )
{
// assigning memory for a new node
struct node *newNode = malloc( sizeof( struct node ) );
(*prevNode)->link = newNode;
newNode->data = num;
newNode->link = NULL;
prevNode = &newNode;
}// END add()
Also I have one other question which I couldn't find and answer to online. when I create a pointer to a structer e.g. struct node *ptr;. does the structer pointer my default store the address of it's self. by its self I mean the structer, so if I print ptr will it output the address of the structer ptr?
A lot to unpack here... these are uninitialized and then you alias a pointer rather than point to an address so you really don't have a pointer to a pointer you have 2 of the same pointer
struct node *head;
struct node **startPtr;
startPtr = head;
struct node *nodePtr;
maybe something like this:
struct node *head = NULL;
struct node **startPtr = &head;
struct node *nodePtr = NULL;
would be a better start... then in C you can't deref a NULL pointer so you have to check first if there is a possibility of a null pointer... note this wont check for uninitialized garbage values, which local variable can be:
if(startPtr && *startPtr)
{
// now you know you can deref startPtr twice,
// once to a pointer to an object (which might be null)
// then after then && you can deref to an actual object
}
Apart from this typo
startPtr = head;
^^^^
where has to be
startPtr = &head;
^^^^^
there are several problems with the code.
The first one is that the header was not initialized initially. So dereferencing this pointer results in undefined behavior.
The second problem is that this loop
do{
printf( "\n\n1: enter new node\n" );
printf( "2: Print Nodes\n" );
printf( "\n\nEnter: " );
scanf( "%d", &userInput );
if ( userInput == 1 )
{
printf( "\n\nEnter data:");
scanf("%d", &inputData );
add( inputData, startPtr );
}
}while( userInput == 1 );
is built logically incorrectly. For example if the user enters some number that is not equal to 1 or 2 then the program will try to output the list after exiting the loop.
The third one is as initially the header can be equal to null. So this statement in the function
(*prevNode)->link = newNode;
again invokes undefined behavior and moreover if *prevNode is not equal to NULL then all early appended nodes will be lost because its reference link is overwritten.
The function can look the following way
int add( struct node **head, int data )
{
struct node *newNode = malloc( sizeof( struct node ) );
int success = newNode != NULL;
if ( success )
{
newNode->data = data;
newNode->link = *head;
*head = newNode;
}
return success;
}
struct node *head;
never initialized
startPtr = head;
initialized to uninitialized; your entire program is undefined beyond this point.

Singly Linked List insert function

I am trying to insert into linked list but I am not getting proper output when display() method is called. Everything is fine while inserting data into the linked list.
The printf statement in insert() method prints :
a int
b int
c int
But when display() method is called it prints :
c
c
c
Datatype member of the structure doesn't get printed at all. And, I think identifierName member gets overwrite every time. Following I snippet of my code :
struct symbol
{
char* identifierName;
char* datatype;
struct symbol* next;
};
void insert(struct symbol** headRef,char* identifier,char* type)
{
struct symbol* newnode = (struct symbol*) malloc(sizeof(struct symbol));
newnode->identifierName = identifier;
newnode->datatype = type;
newnode->next = (*headRef);
(*headRef) = newnode;
printf("%s %s\n",newnode->identifierName,newnode->datatype); //debugging
}
void display(struct symbol* node)
{
while(node!=NULL)
{
printf("%s %s\n",node->identifierName,node->datatype);
node = node->next;
}
}
It seems that you need to make copies of the strings passed as arguments of the function.
Change the function the follwoing way
#include <string.h>
//...
void insert(struct symbol** headRef,char* identifier,char* type)
{
struct symbol* newnode = (struct symbol*) malloc(sizeof(struct symbol));
if ( newnode )
{
newnode->identifierName = malloc( strlen( identifier ) + 1 );
strcpy( newnode->identifierName, identifier );
newnode->datatype = malloc( strlen( type ) + 1 );
strcpy( newnode->datatype, type );
newnode->next = *headRef;
*headRef = newnode;
printf("%s %s\n",newnode->identifierName,newnode->datatype); //debugging
}
}
Take into account that the function expects that paramameters identifier and type are pojnters to first characters of strings.
If for example parameter identifier is a pointer to a single character then instead of
newnode->identifierName = malloc( strlen( identifier ) + 1 );
strcpy( newnode->identifierName, identifier );
you have to write
newnode->identifierName = malloc( sizeof( char ) );
*newnode->identifierName = *identifier;
Also do not forget to free memory pointed to by these pointers when a node is deleted.
replace these two lines
newnode->next = (*headRef);
(*headRef) = newnode;
with
newnode->next = headRef->next;
headRef = newnode;

Resources