For starters the function myLinkedListCreate does not make sense. Initially the pointer to the head node should be equal to NULL. That is to create a new empty list you can just write:
MyLinkedList *head = NULL;
Moreover the allocation of a node within the function:
MyLinkedList* myLinkedListCreate() { LinkList p = (LinkList)malloc(sizeof(MyLinkedList)); p->val = 0; p->next = NULL; return p; }
can fail. In this case these statements:
p->val = 0; p->next = NULL;
will invoke undefined behavior. And it is unclear why an empty list contains a node with the stored value 0. Otherwise you will always need to skip this node in the list in other functions that deal with the list. And you will need to free memory for an empty list that sounds very strange.
The design of the function myLinkedListGet is very bad. The value -1 returned by the function in case when there are less nodes in the list than the specified index can be a valid value stored in a node. In such a case you will not know whether it is a valid value or a signal that a node is not found.
The function should be declared and defined the following way:
int myLinkedListGet( const MyLinkedList *head, size_t index, int *value ) { while ( head != NULL && index != 0 ) { head = head->next; --index; } if ( head != NULL ) *value = head->val; return head != NULL; }
The function can be called like
MyLinkedList *head = NULL; //... int value = 0; size_t index = some_value; if ( myLinkedListGet( head, index, &value ) ) { // do something with the stored value in the variable value }
Pay attention to that the first parameter of the function (the pointer to the head node) is declared with the qualifier const because the list itself it not changed within the function.
The declaration of the function myLinkedListAddAtHead is incorrect. Firstly the pointer to the head node is passed to the function by value. It means that the function deals with a copy of the value of the pointer to the head node. Changing the copy within the function like:
obj = new;
does not change the original pointer to the head node passed to the function. It stays unchanged that results in a memory leak. And secondly the function does not report whether memory for the new node was allocated or not. And again if the new node was not created these statements:
new->val = val; new->next = obj;
will invoke undefined behavior.
You need to pass the pointer to the head node to the function by reference. In C passing by reference means passing an object (that in turn can be a pointer) indirectly through a pointer to it. Thus dereferencing the passed pointer within the function you can get a direct access to the original object.
The function can be declared and defined the following way:
int myLinkedListAddAtHead( MyLinkedList **head, int value ) { MyLinkedList *new_node = malloc( sizeof( MyLinkedList ) ); int success = new_node != NULL; if ( success ) { new_node->val = value; new_node->next = *head; *head = new_node; } return success; }
Alternatively you could for all functions that add new nodes to the list return a pointer to the head node that can be modified within functions (for example when the list is empty). But it is also not a good design because it is much better when functions return either success or failure of the operation of adding a new node to the list.
The same problems exist for the function myLinkedListAddAtTail. Pay attention to that if you are going to add new nodes to the tail of the list the list should be defined as a doubly-linked list.
The function myLinkedListAddAtIndex that has sinilar drawbacks as the functions described above that add new nodes to the list also can invoke undefined behavior in this for loop:
for(int i = 0; i != index - 1; i++){ p = p->next; }
because the specified index can be much greater than the number of nodes in the list. In this case a null pointer will be used in this statement
p = p->next;
The same problems exist in the function myLinkedListDeleteAtIndex.
Pay attention to that the function myLinkedListFree also does not change the original pointer to he head node that can confuse users of the list. It would be again better to pass the pointer to the head node to the function by reference. That is the function can look the following way:
void myLinkedListFree( MyLinkedList **head ) { while ( *head ) { MyLinkedList *tmp = *head; *head = ( *head )->next; free( tmp ); } }
And the function is called like:
MyLinkedList *head = NULL; //... myLinkedListFree( &head );
After calling this function the original pointer to the head node will be changed to NULL. That is the list indeed will be empty.
So in my opinion, for a beginner, the function declarations and their designs at leetCode are bad and incorrect relative to the C programming language.