I have two sorted linked lists, list1 and list2. My goal is to merge list2 into list1.
The requirements are as follows:
- The resulting list should be list1 (no creating a new linked list and having the merged list to be in the new linked list)
- The return type must be void
- list2 must be empty after the merge
- Merged list must be sorted
- Cannot delete or remove any nodes. Move pointers only
- No recursions
- No sorting allowed in the algorithm
- No other helper functions
Sample output:
- list1: d -> e -> f -> t -> w -> x -> y -> NULL
- list2: a -> b -> e -> j -> l -> z -> NULL
Result:
- list1: a -> b -> d -> e -> e -> f -> j -> l -> t -> w -> x -> y -> z -> NULL
- list2: empty
My code's result is currently
- list1: d -> e -> f -> j -> l -> t -> w -> x -> y -> z -> NULL
- list2: a -> b -> d -> e -> e -> f -> j -> l -> t -> w -> x -> y -> z -> NULL
typedef struct listNode {
char data;
struct listNode* nextPtr;
} ListNode;
typedef ListNode* ListNodePtr;
void mergeSortedList(ListNodePtr list1, ListNodePtr list2) {
ListNodePtr curr = NULL;
ListNodePtr last = NULL;
if (list1->data < list2->data)
{
curr = list1;
last = list1;
list1 = list1->nextPtr;
}
else {
curr = list2;
last = list2;
list2 = list2->nextPtr;
}
last->nextPtr = NULL;
while (list1 != NULL && list2 != NULL) {
if (list1->data < list2->data) {
last->nextPtr = list1;
last = list1;
list1 = list1->nextPtr;
}
else {
last->nextPtr = list2;
last = list2;
list2 = list2->nextPtr;
}
last->nextPtr = NULL;
}
if (list1 != NULL) {
last->nextPtr = list1;
}
else {
last->nextPtr = list2;
}
}
CodePudding user response:
Eliminate
ListNodePtr
in favor ofListNode *
(see Is it a good idea to typedef pointers?).As @n.m. implied you need to pass in
ListNode **
in order to have an effect on caller.If either
list1
orlist2
are NULL original code segfaults.Swap the two lists if
*list1
doesn't point to the smallest first node. Then iterate through the two lists using the pointersl1
andl2
. The interesting case is moving nodes froml2
tol1
. This requires you to look ahead a node onl1
m so you can set the inbound pointer to the node being move. Alternatively keep a pointer around to the previous node onl1
than the one we currently looking. Finally, deal with any remaining nodes ofl2
.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct listNode {
char data;
struct listNode* nextPtr;
} ListNode;
ListNode *createList(const char *data) {
if(!data || !*data) return NULL;
size_t n = strlen(data);
ListNode *head = malloc(n * sizeof(*head));
if(!head) return NULL;
ListNode *p = head;
for(size_t i = 0; i < n; i , p = p->nextPtr) {
p->data = data[i];
p->nextPtr = p 1;
}
(p-1)->nextPtr = NULL;
return head;
}
void mergeSortedList(ListNode **list1, ListNode **list2) {
if(!*list1 || (*list2 && (*list1)->data > (*list2)->data)) {
ListNode *tmp = *list1;
*list1 = *list2;
*list2 = tmp;
}
if(!*list1) return;
ListNode *l1 = *list1;
ListNode *l2 = *list2;
while(l1->nextPtr && l2) {
if(l1->nextPtr->data <= l2->data)
l1 = l1->nextPtr;
else {
ListNode *tmp = l2->nextPtr;
l2->nextPtr = l1->nextPtr;
l1->nextPtr = l2;
l2 = tmp;
}
}
if(l2) l1->nextPtr = l2;
*list2 = NULL;
}
void printList(const char *name, ListNode *head) {
printf("%s: ", name);
for(; head; head = head->nextPtr) {
printf("%c -> ", head->data);
}
printf("NULL\n");
}
int main(void) {
ListNode *l1 = createList("deftwxy");
ListNode *l2 = createList("abejlz");
mergeSortedList(&l1, &l2);
printList("list1", l1);
printList("list2", l2);
}
and resulting output:
list1: a -> b -> d -> e -> e -> f -> j -> l -> t -> w -> x -> y -> z -> NULL
list2: NULL