reverse linked list recursively - different function signature - c

There are many posts with probably with same question but the problem says it has to be done by
node* reverseList (node * lh)
{
if(lh==NULL)............ ;
else if (lh->next==NULL)...........;
else ...........;
}
the three blanks must be filled
the first two are simply
return NULL
and
return lh
repectively
one way could be just to go down and reverse the pointers but in that case how can i keep the tail intact even after backtracking? is it possible at all?

The trick to solving recursive problems is to pretend that you are done already. To solve this homework by yourself, you need to answer three questions:
How do you reverse an empty list? (i.e. a list with lh set to NULL)?
How do you reverse a list with only one item?
If someone could reverse all items on the list except the initial one for you, where do you add the first item from the initial list to the pre-reversed "tail" portion of the list?
You answered the first two already: NULL and lh are the right answers. Now think of the third one:
else {
node *reversedTail = reverseList(lh->next);
...
}
At this point, reversedTail contains pre-reversed tail of your list. All you need to do is set lh->next to NULL, add it to the back of the list that you are holding, and return reversedTail. The final code looks like this:
else {
node *reversedTail = reverseList(lh->next);
node *p = reversedTail;
while (p->next) p = p->next;
p->next = lh;
lh->next = NULL;
return reversedTail;
}

I think this answers it:
node *reverseList(node *lh)
{
if (!lh) return NULL;
else if (!lh->next) return lh;
else {
node *new_head = reverseList(lh->next);
lh->next->next = lh;
lh->next = NULL;
return new_head;
}
}
It returns the head of the reversed list, i.e. the tail of the original list.
head = reverse_list(head);

Below is an API which does the reversal of a Single linked list, this one of the best algo that i have seen:
void iterative_reverse()
{
mynode *p, *q, *r;
if(head == (mynode *)0)
{ return;
}
p = head;
q = p->next;
p->next = (mynode *)0;
while (q != (mynode *)0)
{
r = q->next;
q->next = p;
p = q;
q = r;
}
head = p;
}

Related

Issues with linked list and pointers (C)

I am writing a C program to sort a linked list according to the largest values. I met an issue whereby the program just hangs when the program reached "prevPtr->next = headPtr".
I want the prevPtr->next to equate to headPtr, if the sum of prevPtr is larger than the sum of headPtr, however the program just hangs there.
compareNodes() function is used to compare the nodes to see if newNode has the same name as any other structs in the linked list, then it will add in the sum.
sortSimilarNodes() function is used to sort the nodes according to the sum of each struct.
The struct is here below:
struct purchase {
char name[30];
double sum;
struct purchase * next;
} ;
LOG * compareNodes(LOG * headPtr, char * name, char * price){
.
.
.
while (curPtr != NULL) {
if (strcmp(newNode->name, curPtr->name)==0) {
curPtr->sum += newNode->sum;
free(newNode);
similar = 1;
break;
}
//advance to next target
prevPtr = curPtr;
curPtr = curPtr->next;
}
/*if (curPtr == NULL){
if(strcmp(newNode->name, prevPtr->name)==0){
prevPtr->sum += newNode->sum;
free(newNode);
similar = 1;
}
}*/
if (similar == 1){
headPtr = sortSimilarNodes(curPtr, headPtr);
}
else{
headPtr = sortNodes(newNode, headPtr);
}
return headPtr;
}
LOG * sortSimilarNodes(LOG * newPtr, LOG * headPtr){
LOG * curPtr;
LOG * prevPtr;
if(headPtr->sum < newPtr->sum){
newPtr->next = headPtr;
return newPtr;
}
prevPtr = headPtr;
curPtr = headPtr->next;
while (curPtr == NULL){
}
while (curPtr != NULL){
if(strcmp(curPtr->name, newPtr->name)==0){
break;
}
prevPtr = curPtr;
curPtr = curPtr->next;
}
return headPtr;
}
This is the output of the program.
Thank you!
It's hard to tell from your code, because you haven't posted all of it, but you seem to have some misconceptions about linked lists. In particular:
There is no need for new nodes unless you really add new nodes to the list. That also means that you don't call malloc except when adding nodes. (There's no malloc in your code, but a suspicious free in your comparison function. Comparing does not involve creating or destroying anything; it just means to look what is already there.)
A corollary to the first point is that there should be no nodes in an empty list, not even dummy nodes. An empty list is a list whose head is NULL. Make sure that you initialise all head pointers before creating a new list:
LOG *head = NULL; // empty list
When you sort the list, the order of the list has changed and the old head is invalid. You cater for that by returning the new head:
head = sort(head);
But that seems redundant and it also seems to imply that the two pointers can be different. That's not the case, because the old pointer will point somehwre in the sorted list, not necessarily at its head. It's probably better to pass the head pointer's address in order to avoid confusion:
sort(&head);
Sorting linked lists can be tricky. One straightforward way is selection sort: Find the node with the highest value, remove it from the original list and add it at the front of a new list. Repeat until there are no more nodes in the original list.
Adding a new node n at the front of a list given by head is easy:
n->next = head;
head= n;
Adding a new node at the end of a list that is given by head is a bit more involved:
LOG **p = &head;
while (*p) p = &(*p)->next;
*p = n;
n->next = NULL;
Here, p is the address of the pointer that points to the current node, *p. After walking the list, that address is either the address of the head node (when the list is empty) or the address of the next pointer of the precedig node.
You could achieve something similar by keeping a prev pointer, but the pointer-to-pointer solution means that you don't have to treat the cases where there is no previous node specially at the cost of some extra & and * operators.
With that, your sorting routine becomes:
void sortByName(LOG **head)
{
LOG *sorted = NULL;
while (*head) {
LOG **p = head; // auxiliary pointer to walk the list
LOG **max = head; // pointer to current maximum
LOG *n; // maximum node
while (*p) {
if (strcmp((*p)->name, (*max)->name) > 0) max = p;
p = &(*p)->next;
}
n = *max;
*max = (*max)->next;
n->next = sorted;
sorted = n;
}
*head = sorted;
}
If you want to sort by sum, change the comparison to:
if ((*p)->sum > (*max)->sum) max = p;
Call the function like this:
LOG *head = NULL;
insert(&head, "apple", 2.3);
insert(&head, "pear", 1.7);
insert(&head, "strawberry", 2.2);
insert(&head, "orange", 3.2);
insert(&head, "plum", 2.1);
sortByName(&head);
print(head);
destroy(&head);
with the insert, destroy and print functions for completeness:
void insert(LOG **head, const char *name, double sum)
{
LOG *n = malloc(sizeof(*n));
if (n) {
snprintf(n->name, sizeof(n->name), "%s", name);
n->sum = sum;
n->next = *head;
*head = n;
}
}
void destroy(LOG **head)
{
LOG *n = *head;
while (n) {
LOG *p = n;
n = n->next;
free(p);
}
*head = NULL;
}
void print(LOG *l)
{
while (l) {
printf("%s: %g\n", l->name, l->sum);
l = l->next;
}
puts("");
}

C programing: How to pop last element on linked list?

I am beginner programer and one week ago i was introduced to linked list however I'm still struggling to wrap my head around this.
Currently trying to write a function that will help me remove last element from the linked list. I would appreciate some explanation what am i doing wrong here. Thank You for any suggestions.
I'm not allowed to touch or modify current structs
Here is my structs:
typedef struct node {
ElemType val;
struct node *next;
} NODE;
struct list_struct {
NODE *front;
NODE *back;
};
And heres my current code:
if list is empty, we do nothing and return arbitrary value
otherwise, the last element in the list is removed and its
value is returned.
ElemType lst_pop_back(LIST *l) {
NODE * p = l->front;
NODE * trail = l->front;
if( p == NULL) return 0;
if( lst_len(l) == 1){
free(p);
l->front = NULL;
l->back = NULL;
}
else{
p=p->next;
while( p != NULL){
if( p->next == NULL) free(p);
trail = trail->next;
p=p->next;
}
trail= trail->next;
trail->next= NULL;
}
return 0;
}
I'm using Xcode on MAC and the error that i get is: Thread 1: EXC_ACCESS(code=1, address=0x8)
The XCode error EXC_BAD_ACCESS(code=1, address=0x8) means that somebody tries to access unaccessable memory. XCode's boundary checks are said to be good, so let's trust them. It is a bit sad that the OP doesn't tell us the exact line-number but one can guess. I would concur with Katerina B. here and assume the same lines as the culprit.
In detail:
ElemType lst_pop_back(LIST * l)
{
// p and trail point to the first node
NODE *p = l->front;
NODE *trail = l->front;
if (p == NULL)
return 0;
if (lst_len(l) == 1) {
free(p);
l->front = NULL;
l->back = NULL;
} else {
p = p->next;
// Now: trail->next points to the old p
// and p to p->next, that is: trail points
// to the node before p
// while trail is not the last node
while (p != NULL) {
// if p is the last node
if (p->next == NULL){
// release memory of p, p points to nowhere from now on
free(p);
}
// Following comments assume that p got free()'d at this point
// because trail points to the node before p
// trail->next points to the node p pointed to
// before but p got just free()'d
trail = trail->next;
// p got free()'d so p->next is not defined
p = p->next;
}
// assuming p got free()'d than trail->next is one step
// further into unknown, pardon, undefined territory
trail = trail->next;
trail->next = NULL;
}
return 0;
}
I think the error you're getting happens when you try to access something that's already been deallocated. You're doing that here:
if( p->next == NULL) free(p);
trail = trail->next;
p=p->next;
Since the list structure contains a back pointer, I'd recommend using that to help you. Maybe let p move through the list until p->next points to the same thing as the list's back pointer, then make p->next null.
Also, should the function POP or REMOVE from the list? Your question says removing but the function is named lst_pop_back. If you're poping, you'll need to return the last value too.

Segmentation fault deleting nodes from singly linked list

this is the case i am working on
[11] -> [12] -> [13] -> NULL
I am trying to delete the elements from the liked list above(example) but I keep getting segfault and on running GDB doesnot help much. I am not looking for an answer but and explanation on where I am going wrong logically.
here is the code
int
List:: remove( int val )
{
ListNode *headNode = _head;
ListNode *tempNode = NULL;
if(headNode->_value == val){
tempNode = headNode->_next;
delete headNode;
_head = tempNode;
}
else
{
while(headNode->_value != val){
tempNode = headNode;
headNode = headNode->_next;
}
tempNode->_next = headNode->_next;
delete headNode;
}
}
You're not accounting for the following conditions:
The list may be empty; i.e. _head is NULL;
The value may not be in the list at all.
Your function is declared to return int, but makes no such return
Assuming the rest of your code is correct (and that is a big assumption), I'm all-but-certain this is what you're trying to do:
void List::remove( int val )
{
ListNode *headNode = _head;
ListNode *tempNode = NULL;
while (headNode && headNode->_value != val)
{
tempNode = headNode;
headNode = headNode->next;
}
if (headNode)
{
if (tempNode)
tempNode->next = headNode->next;
else
_head = headNode->next;
delete headNode;
}
}
Alternatively, if so inclined this can get (arguably) simpler utilizing a pointer-to-pointer to traverse the pointers in the list, not just their values. It is worth investigating how the following works, which still covers all the bases described previously, but does so using the actual pointers in the list nodes themselves, including _head, by-address rather than by-value, thereby eliminating the need for a walk-behind temporary pointer:
void List::remove( int val )
{
ListNode **pp = &_head;
while (*pp && (*pp)->_value != val)
pp = &(*pp)->next;
if (*pp)
{
ListNode *p = *pp;
*pp = p->next;
delete p;
}
}
In your remove method you are assuming there are always elements in your list. - What if it is empty?
What if the value isn't in the list? You need to handle this case as well.
You're headed in the right direction - there are just a few cases that you haven't considered that can lead you to seg fault.
Example of forward traversal with deletion (forward-only linked list):
// Start from the beginning (head), then while the current isn't null,
// move to the next node.
for (ListNode* current = head; current != null; current = current->next) {
// Check the next item if there is one, and remove it if it matches the value.
// We check the next one because you can't delete the current node in a
// forward only linked list (can in a doubly-linked list however)
if (current->_next != nullptr && current->_value == value) {
// Make this item point to the next next item
// (Since we're gonna delete the next item)
current->_next = current->_next->next;
// Delete the next item.
delete current->_next;
}
}

Deleting occurrences of substring in string in singly linked list C

I have a little problem out here.
I must to program a singly linked list stuff, and I hadn't got any problems since now. I stuck on the deletion by the occurrence of the substring given after the function call in authors name in linked list.
the program snippet:
void list_delete_element(kniha_t* inode)
{
kniha_t *actualnode = inode;
kniha_t *prevnode = NULL;
kniha_t *tempnode = NULL;
uchar_t needle[100];
uchar_t haystack[100];
ushort_t occur = 0;
scanf("%s", &needle);
lower_string(needle);
while(actualnode != NULL)
{
copy_string(haystack, actualnode->autori);
lower_string(haystack);
if(search_string(haystack, needle))
{
occur++;
if ( NULL != prevnode)
{
prevnode->next = actualnode->next;
}
else
{
inode = actualnode->next;
}
tempnode = actualnode;
actualnode = actualnode->next;
free(tempnode);
tempnode = NULL;
}
else
{
prevnode = actualnode;
actualnode = actualnode->next;
}
}
printf("Deleted sa %hu nodes\n", occur);
}
and the stuff I must load in it, ignoring the ---:
http://pastebin.com/NPvEr3y6
the problem is, that works ( :D )...until I sweep all the occurrences.
Example:
When I type in pra, it must delete all the nodes that contains "pra". It works like a charm...but when I type only "p", it tells me, that all the X occurrences were freed, but they stay in the buffer somewhere, because I can print the whole list out again!
I will be very thankful, who can give me some advice.
Your list_delete_element should take kniha_t** so that you can delete the head node and prune linked list. With current code, you delete the node, but other functions doesn't know that because inode is not changed.
You you can update your code as
void list_delete_element(kniha_t* *inode)
{
kniha_t *actualnode = *inode;
...
if ( NULL != prevnode)
{
prevnode->next = actualnode->next;
}
else
{
*inode = actualnode->next;
}
...
}
this statement:
tempnode = NULL;
does nothing, actually, since you never do anything with tempnode besides assignment and immediately freeing.

linked list reverse without temp

Is there any way to reverse linked list without using temp variable in C?
Thanks in advance.
the famous approach:
Element *reverse(Element *head)
{
Element *previous = NULL;
while (head != NULL) {
// Keep next node since we trash
// the next pointer.
Element *next = head->next;
// Switch the next pointer
// to point backwards.
head->next = previous;
// Move both pointers forward.
previous = head;
head = next;
}
return previous;
}
uses temp variable
Saurabh
Note that your temp usage is actually generating two swap() calls, and can be replaced with:
swap(head->next,previous);
swap(previous,head);
You can swap without temps using xor, it is called xor swap.
Use XOR-swaps on the pointers to fake an XOR-linked-list.
Implementation is left to the reader as an exercise.
Recursive approach :
Element *reverse(Element *head, Element **first)
{
if (head->next == NULL)
{
*first = head;
return head;
}
Element* NextElement= reverse (head->next, first);
NextElement->next = head;
head->next = null;
return head;
}
Call for recursive function:
Element *revLinkListHead;
reverse(head, &revLinkListHead);
If someone is still interested, here is the solution that uses no new variables at all, except for those passed in recursive call.
public static List invert(List l) {
invert(l.next, l, l);
l = l.next;
breakCycle(l, l);
return l;
}
private static void invert(List l, List toBeNext, List first) {
if(l.next == null) {
l.next = toBeNext;
first.next = l;
} else {
invert(l.next, l, first);
l.next = toBeNext;
}
}
private static void breakCycle(List l, List first) {
if(l.next == first) {
l.next = null;
} else {
breakCycle(l.next, first);
}
}
The idea is the following: first we run invert function recursively, and implement it so that when it reaches the last element it assigns it as a next element of current head (parameter first). After we executed it, we will have a reversed list but cycled, so the current head.next will point at the head of the reversed list. We reassign head to its next element (the actual head of the reversed list), and the last thing we have to do is to break the cycle. So we call breakCycle which does the job recursively!

Resources