Can anyone tell me what is wrong with my code?
I want to create non- return function void to insert a node at the end of linked list.
void insert_tail_Recursively(struct node **phead, int key) {
if (*phead == NULL) {
Node*temp = malloc(sizeof(Node));
temp->data = key;
temp->pLeft = temp->pRight = NULL;
*phead = temp;
} else {
Node*temp = malloc(sizeof(Node));
temp->data = key;
temp->pLeft = temp->pRight = NULL;
/* data more than root node data insert at right */
if ((temp->data > (*phead)->data) && ((*phead)->pRight != NULL))
insert_tail_Recursively((*phead)->pRight, key);
else if ((temp->data > (*phead)->data) && ((*phead)->pRight == NULL)) {
(*phead)->pRight = temp;
}
/* data less than root node data insert at left */
else if ((temp->data < (*phead)->data) && ((*phead)->pLeft != NULL))
insert_tail_Recursively((*phead)->pLeft, key);
else if ((temp->data < (*phead)->data) && ((*phead)->pLeft == NULL)) {
(*phead)->pLeft = temp;
}
}
}
Your code is too complicated and as result has bugs. For example there are memory leaks.
It seems you mean the following.
void insert_tail_Recursively( struct node **phead, int key )
{
if ( *phead == NULL )
{
*phead = malloc( sizeof( struct node ) );
( *phead )->data = key;
( *phead )->pLeft = ( *phead )->pRight = NULL;
}
else
{
phead = key < ( *phead )->data ? &( *phead )->pLeft : &( *phead )->pRight;
insert_tail_Recursively( phead, key );
}
}
Related
the main purpose of my code is that to take a data from the user and then search the single linked list to find the target and then delete all the nodes that are equal to target.
this is also the base single linked list:
typedef struct Node
{
int data;
struct Node *next;
}no;
Input: 1, 2, 3, 2, 5 --> to delete= 2
so the new linked list is: 1, 3, 5
void* toDElduplicatedlinkedlist (no* firstNode, int target)
{
no* current = firstNode;
no* ptemp;
while ( NULL != current->next)
{
if (firstNode->data == target)
{
current = firstNode->next;
free(firstNode);
}
else if (current->next->data == target)
{
ptemp = current->next;
current->next= current->next->next;
free(ptemp);
}
current = current->next;
}
this is my to-delete function I wrote.
it works for the target items that are in the middle of the linked list but when the firstNode which is head of the list is the target it either doesn't deletes it or looses the head address and i tried to do many ways to save the head of the list so that it wont loose it.
it also doesn't work for the situation that the last node it the target.
I was struggling with this problem but i couldn't solve it so i would be happy and thankful if someone helps me with this.
For starters the function returns nothing though its return type is void *.
This while loop
while ( NULL != current->next)
can invoke undefined behavior if the function is called for an empty list.
Also the while loop is skipped when the list contains only one node.
Or for example if the first node contains a value that is equal to the parameter target then in the first iteration of the loop the pointed node will be freed. However in the next iteration of the loop you are again checking the deleted node
if (firstNode->data == target)
{
current = firstNode->next;
free(firstNode);
}
that one more invokes undefined behavior.
The function can be declared and defined the following way
void toDElduplicatedlinkedlist( no **firstNode, int target )
{
while ( *firstNode )
{
if ( ( *firstNode )->data == target )
{
no *tmp = *firstNode;
*firstNode = ( *firstNode )->next;
free( tmp );
}
else
{
firstNode = &( *firstNode )->next;
}
}
}
And if in the caller of the function you have
no *firstNode;
then the function is called like
toDElduplicatedlinkedlist( &firstNode, target );
That is the pointer to the first node of the list is passed by reference.
Another way to define the function is the following
no * toDElduplicatedlinkedlist( no *firstNode, int target )
{
while ( firstNode && firstNode->data == target )
{
no *tmp = firstNode;
firstNode = firstNode->next;
free( tmp );
}
if ( firstNode != NULL )
{
for ( no *current = firstNode; current->next != NULL; )
{
if ( current->next->data == target )
{
no *tmp = current->next;
current->next = current->next->next;
free( tmp );
}
else
{
current = current->next;
}
}
}
return firstNode;
}
In this case the function is called like
firstNode = toDElduplicatedlinkedlist( firstNode, target );
And at last the function can be also defined the following way
no * toDElduplicatedlinkedlist( no *firstNode, int target )
{
for ( no **current = &firstNode; *current; )
{
if ( ( *current )->data == target )
{
no *tmp = *current;
*current = ( *current )->next;
free( tmp );
}
else
{
current = &( *current )->next;
}
}
return firstNode;
}
and called the same way as shown above that is
firstNode = toDElduplicatedlinkedlist( firstNode, target );
One needs a pointer to a pointer to modify the head node given the function, and one should merely loop while current is not null.
void* toDEduplicatedlinkedlist(no** firstNode, int target)
{
no* current = *firstNode;
no* ptemp = *firstNode;
while (NULL != current)
{
no* temp = NULL;
if (current->data == target)
{
if (current == *firstNode) {
*firstNode = current->next;
}
else {
ptemp->next = current->next;
}
temp = current;
}
else {
ptemp = current;
}
current = current->next;
if(temp != NULL) free(temp);
}
return *firstNode;
}
i have this problem when im using this function, i want to delete all the node with the given string, but when i run this on my program it deletes all from the first find char ex[], im new to c please guide me
void delSearch(char ex[]){
int del;
struct file *temp = head;
while(temp!=NULL){
if(strcmp(temp->ex,ex)==0){
file *temp2 = temp->next;
file *temp3 = temp;
temp->next=temp2;
free(temp3);
temp3 = NULL;
}
else
{
temp = temp->next;
}
}
}
For starters the local variable del
int del;
is not used within the function.
The function does not change the global pointer head provided that it points to a node that stores the given string.
Also you need to update the data member next of the node that precedes to the node to be deleted.
The function can look the following way as it is shown below.
void delSearch( const char ex[] )
{
while ( head && strcmp( head->ex, ex ) == 0 )
{
struct file *tmp = head;
head = head->next;
free( tmp );
}
if ( head )
{
for ( struct file *current = head; current->next != NULL; )
{
if ( strcmp( current->next->ex, ex ) == 0 )
{
struct file *tmp = current->next;
current->next = current->next->next;
free( tmp );
}
else
{
current = current->next;
}
}
}
}
If you want to know how many nodes were deleted after calling the function then the function can be changed the following way.
size_t delSearch( const char ex[] )
{
size_t total = 0;
while ( head && strcmp( head->ex, ex ) == 0 )
{
struct file *tmp = head;
head = head->next;
free( tmp );
++total;
}
if ( head )
{
for ( struct file *current = head; current->next != NULL; )
{
if ( strcmp( current->next->ex, ex ) == 0 )
{
struct file *tmp = current->next;
current->next = current->next->next;
free( tmp );
++total;
}
else
{
current = current->next;
}
}
}
return total;
}
An alternative function definition can look the following way
size_t delSearch( const char ex[] )
{
size_t total = 0;
for ( struct file **current = &head; *current != NULL; )
{
if ( strcmp( ( *current )->ex, ex ) == 0 )
{
struct file *tmp = *current;
*current = ( *current )->next;
free( tmp );
++total;
}
else
{
current = &( *current )->next;
}
}
return total;
}
This is my function:
void IntListInsertInOrder (IntList L, int v)
{
struct IntListNode *n = newIntListNode (v);
if (L->first == NULL) { //case a, empty list
L->first = L->last = n;
L->size ++;
return;
}
else if (v <= L->first->data) { // case b, smallest value
n->next = L->first;
L->first = n;
}
else if (v >= L->last->data) { // case c, largest value
L->last->next = n;
L->last = n;
}
else if (v > L->first->data && v <= L->first->next->data) { // case d, second-smallest value
n->next = L->first->next;
L->first->next = n;
}
else { //case f, value in the middle
struct IntListNode *curr = L->first;
while (curr->next->data < v) {
curr = curr->next;
}
n->next = curr->next;
curr->next = n;
}
L->size ++;
return;
}
when i put random lists of 10 numbers into it, 3/10 sorted correctly. the errors seem to be in the last part but it looks exactly like solutions i found online.
OK I figured it out. I forgot to add&& curr-> != NULLin the condition of the last while loop. After I added that all the test cases passed.
Your function is too complicated, has many if conditions and as a result it is error-prone and unreadable.
You did not show the list definition but I can guess that you have a two-sided singly-linked list because nowhere in the code there is a reference to a data member named prev.
Here is a demonstrative program that shows how the function can be simply defined.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
typedef struct List
{
Node *head;
Node *tail;
size_t size;
} List;
int insert_in_order( List *list, int data )
{
Node *new_node = malloc( sizeof( Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
Node **current = &list->head;
while ( *current != NULL && !( data < ( *current )->data ) )
{
current = &( *current )->next;
}
new_node->next = *current;
if ( *current == NULL )
{
list->tail = new_node;
}
*current = new_node;
++list->size;
}
return success;
}
void clear( List *list )
{
while ( list->head != NULL )
{
Node *current = list->head;
list->head = list->head->next;
free( current );
}
}
void display( const List *list )
{
printf( "There are %zu nodes in the list\n", list->size );
printf( "They are: " );
for ( const Node *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int main(void)
{
List list = { .head = NULL, .tail = NULL, .size = 0 };
srand( ( unsigned int )time( NULL ) );
const size_t N = 10;
for ( size_t i = 0; i < N; i++ )
{
insert_in_order( &list, rand() % ( int )N );
}
display( &list );
clear( &list );
return 0;
}
The program output might look like
There are 10 nodes in the list
They are: 1 -> 2 -> 3 -> 3 -> 6 -> 6 -> 7 -> 8 -> 8 -> 9 -> null
Can you help me to understand why this function doesn't delete a specific element in the linked list? What am I doing wrong?
typedef struct str_node{
int data;
struct str_node *next;
}node;
...
node *head;
head = malloc(sizeof(node));
...
void delete_spec(node *a){
int num;
node *tmp;
tmp = a;
printf("Insert number to eliminate: ");
scanf("%d",&num);
while(tmp!=NULL){
if(tmp->data == num){
tmp = tmp->next->next;
}
tmp = tmp->next;
}
}
For starters it is unclear what the allocation is doing here
node *head;
head = malloc(sizeof(node));
The pointer head shall be initially set to NULL
node *head = NULL;
and new nodes shall be inserted in the list by the function that inserts new values in the list.
The function that deletes nodes from the list shall not issue any prompt. It is the caller of the function that will ask the user to specify the value that will be deleted from the list and then call the function passing the specified value. So the function should have two parameters: pointer to the pointer to the head node and the integer value that shall be deleted from the list.
The function can be defined the following way
void delete_spec( node **head, int data )
{
while ( *head != NULL )
{
if ( ( *head )->data == data )
{
node *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
else
{
head = &( *head )->next;
}
}
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node
{
int data;
struct str_node *next;
} node;
int push_front( node **head, int data )
{
node *new_node = malloc( sizeof( node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
return success;
}
void delete_spec( node **head, int data )
{
while ( *head != NULL )
{
if ( ( *head )->data == data )
{
node *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
else
{
head = &( *head )->next;
}
}
}
void display( node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int main(void)
{
node *head = NULL;
int a[] = { 1, 3, 5, 7, 1, 2, 3, 1 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
push_front( &head, a[i] );
}
display( head );
delete_spec( &head, 1 );
display( head );
return 0;
}
Its output is
1 -> 3 -> 2 -> 1 -> 7 -> 5 -> 3 -> 1 -> null
3 -> 2 -> 7 -> 5 -> 3 -> null
public class LL5 {
Node head;
int size;
LL5(){
this.size = 0;
}
class Node{
String data;
Node next;
Node(String data){
this.data = data;
this.next = null;
size++;
}
}
public void push(String data) {
Node newNode = new Node(data);
if(head == null) {
head = newNode;
return;
}
newNode.next = head;
head = newNode;
}
public void deleteelement(String data) {
Node cur = head;
Node x = cur.next;
Node y = x.next;
if(data == head.data) {
head = head.next;
}
else if(x.data == data) {
head.next = y;
}
else{
while(y.data != data) {
x = x.next;
y = y.next;
}
x.next = y.next;
}
}
public void printList() {
if(head == null) {
System.out.println("list is empty");
return;
}
Node cn = head;
while(cn != null) {
System.out.print(cn.data + " -> ");
cn = cn.next;
}
System.out.print("null");
}
public static void main(String[] args) {
LL5 obj = new LL5();
obj.push("1");
obj.push("2");
obj.push("3");
obj.push("4");
obj.push("5");
obj.push("6");
obj.push("7");
obj.push("8");
obj.push("9");
obj.push("10");
System.out.println("before delete");
obj.printList();
System.out.println();
System.out.println("After delete");
obj.deleteelement("10");
obj.printList();
}
}
delete_spec does not modify in anyway the input list. also: it does not free any memory.
in order to actually delete a node you must:
1. free its memory.
2. modify the list so the "next" pointers are updated. in order to update the list, you must provide the delete function the address of the head so it can modify also head.
something like this:
void delete_spec(node **a){
int num;
node *tmp;
if (a == NULL || *a == NULL) return;
tmp = *a;
printf("Insert number to eliminate: ");
scanf("%d",&num);
if (tmp->data == num)
{
*a = (*a)->next;
free(tmp);
return;
}
while(tmp->next!=NULL){
if(tmp->next->data == num){
node* tmp2 = tmp->next;
tmp->next = tmp->next->next;
free(tmp2);
}
tmp = tmp->next;
}
}
I had to write a recursive function that receives two sorted lists:
typedef struct listNode {
int* dataPtr;
struct listNode* next;
} ListNode;
typedef struct list
{
ListNode* head;
ListNode* tail;
} List;
and merge them into one sorted list.
I wrote these functions:
void mergeRec(ListNode* head1, ListNode* head2, ListNode* mergedList)
{
if (head1 == NULL && head2 == NULL)
return;
else if (head1 == NULL) {
mergedList->next = head2;
head2 = head2->next;
}
else if (head2 == NULL) {
mergedList->next = head1;
head1 = head1->next;
}
else if (*(head1->dataPtr) > *(head2->dataPtr)) {
mergedList->next = head1;
head1 = head1->next;
}
else
{
mergedList->next = head2;
head2 = head2->next;
}
mergeRec(head1, head2, mergedList->next);
}
List merge(List lst1, List lst2)
{
List mergedList;
makeEmptyList(&mergedList);
mergeRec(lst1.head, lst2.head, mergedList.head);
return mergedList;
}
Now, the problem I have with the recursive function is that at the first call when merged list is pointing to null, so obviously when I write something like mergeList->next I will get a running bug.
I tried to solve it by adding the following condition in the recursion:
if (mergedList == NULL)
{
if (*(head1->dataPtr) > *(head2->dataPtr))
{
mergedList = head1;
head1 = head1->next;
}
else
{
mergedList = head2;
head2 = head2->next;
}
}
but I got this error:
"Exception thrown at 0x00661EB9 in q2d.exe: 0xC0000005: Access violation writing location 0x01000F48."
I can't tell the problem, or how do I solve it.
I would very much appreciate your help.
Thanks!
For starters it is entirely unclear why in this structure there is a data member of type int *
typedef struct listNode {
int* dataPtr;
struct listNode* next;
}List;
instead of just of type int
typedef struct listNode {
int data;
struct listNode* next;
}List;
Nevertheless, the functions merge and mergeRec are invalid because they deal with copies of values of lists and of pointers list1.head, list2.head, and mergedList.head.
List merge(List lst1, List lst2)
mergeRec(lst1.head, lst2.head, mergedList.head);
Moreover the pointers list1.tail, list2.tail, and mergedList.tail are ignored.
I can suggest the following solution shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
typedef struct listNode
{
int *dataPtr;
struct listNode *next;
} ListNode;
typedef struct list
{
ListNode *head;
ListNode *tail;
} List;
void makeEmpty( List *list )
{
list->head = list->tail = NULL;
}
int push( List *list, int data )
{
ListNode *current = malloc( sizeof( ListNode ) );
int success = current != NULL;
if ( success )
{
current->dataPtr = malloc( sizeof( int ) );
success = current->dataPtr != NULL;
if ( success )
{
*current->dataPtr = data;
current->next = NULL;
if ( list->head == NULL )
{
list->head = list->tail = current;
}
else
{
list->tail = list->tail->next = current;
}
}
else
{
free( current );
current = NULL;
}
}
return success;
}
List merge( List *first, List *second )
{
List result;
makeEmpty( &result );
if ( ( second->head != NULL ) &&
( first->head == NULL || *second->head->dataPtr < *first->head->dataPtr ) )
{
result.head = result.tail = second->head;
second->head = second->head->next;
if ( second->head == NULL ) second->tail = NULL;
}
else if ( first->head != NULL )
{
result.head = result.tail = first->head;
first->head = first->head->next;
if ( first->head == NULL ) first->tail = NULL;
}
if ( !( first->head == NULL && second->head == NULL ) )
{
List tmp = merge( first, second );
result.head->next = tmp.head;
result.tail = tmp.tail;
}
return result;
}
void output( const List *list )
{
for ( const ListNode *current = list->head; current != NULL; current = current->next )
{
printf( "%d ", *current->dataPtr );
}
puts( "NULL" );
}
int main(void)
{
List even_numbers;
List odd_numbers;
makeEmpty( &even_numbers );
makeEmpty( &odd_numbers );
const int N = 10;
for ( int i = 0; i < N; i++ )
{
i % 2 == 0 ? push( &even_numbers, i )
: push( &odd_numbers, i );
}
printf( "even_numbers: " ); output( &even_numbers );
printf( "odd_numbers: " ); output( &odd_numbers );
List all_numbers = merge( &even_numbers, &odd_numbers );
printf( "all_numbers: " ); output( &all_numbers );
printf( "even_numbers: " ); output( &even_numbers );
printf( "odd_numbers: " ); output( &odd_numbers );
return 0;
}
The program output is
even_numbers: 0 2 4 6 8 NULL
odd_numbers: 1 3 5 7 9 NULL
all_numbers: 0 1 2 3 4 5 6 7 8 9 NULL
even_numbers: NULL
odd_numbers: NULL