Linked List K Alternate Reverse Program - c

Can Anyone Explain me why the function *kAltReverse return node type prev and how it will work when you call node->next in print function to get the next element from the struct node & print and how it points to next data?
I don't understand how the data is printed using just prev in *kAltReverse function?
Help is very very highly appreciated!!!
Question Source: GeeksforGeeks
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node* next; };
struct node *kAltReverse(struct node *head, int k) {
struct node* current = head;
struct node* next;
struct node* prev = NULL;
int count = 0;
while (current != NULL && count < k)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
count++;
}
if(head != NULL)
head->next = current;
count = 0;
while(count < k-1 && current != NULL )
{
current = current->next;
count++;
}
if(current != NULL)
current->next = kAltReverse(current->next, k);
return prev;
}
void push(struct node** head_ref, int new_data) {
struct node* new_node =
(struct node*) malloc(sizeof(struct node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printList(struct node *node) {
int count = 0;
while(node != NULL)
{
printf("%d ", node->data);
node = node->next;
count++;
}
}
int main(void) {
struct node* head = NULL;
for(int i = 20; i > 0; i--)
push(&head, i);
printf("\n Given linked list \n");
printList(head);
head = kAltReverse(head, 3);
printf("\n Modified Linked list \n");
printList(head);
getchar();
return(0);
}

Looks like there is a problem with int count = 0;.
It should be static int count = 0;, otherwise it would not behave as expected.
This reverses 1st 'k' elements of the linked list using recursion. Its like in 1st iteration of the loop, the 1st element will be placed at Kth position and 2nd element at 1st position, and in next iteration, with k reduced by 1, it will placed the 2nd value(the current 1st value after iteration) to the (k-1)th position (last position for current iteration). This goes on till count reaches to 'k'.

Related

C programming - Reverse a linked link by iterative method

I am trying to reverse a linked by iterative method. Magically, after watching tutorial and trying to recode myself, the program works successfully. However, when I review the code, I hit a question: in line 23, why we must use temp1->next instead of temp1? When traversing to the end of the linked list, which case we use the condition (the node != NULL)? In which case we use (the link of the node ! = NULL)? I fully appreciate it if anyone can enlighten me.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* Insert(struct Node* head, int data)
{
struct Node* temp = (struct Node*) malloc(sizeof(struct Node));
temp->data = data;
temp->next = NULL;
//If the list is empty
if (head == NULL)
{
head = temp;
}
else //The list is not empty
{
struct Node* temp1 = head;
while (temp1->next != NULL)
{
temp1 = temp1->next;
}
temp1->next = temp;
}
return head;
}
void Print(struct Node* head)
{
struct Node* temp = head;
while (temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
struct Node* Reverse(struct Node* head)
{
struct Node* *prev, *current, *next;
current = head;
prev = NULL;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
head = prev;
return head;
}
int main()
{
struct Node* head = NULL;
printf("Enter the length of the linked list you want to create: ");
int length;
scanf("%d", &length);
printf("Enter the value you want to input: ");
int i;
for (i = 0; i < length; i++)
{
int x;
scanf("%d", &x);
head = Insert(head, x);
}
printf("Given linked list\n");
Print(head);
head = Reverse(head);
printf("\nReversed linked list \n");
Print(head);
return 0;
}
In that case, inside the while condition, on line 23, you can notice that the program is using temp1 = temp1->next, if you change the condition to temp1 != NULL when it reaches the last element of linked list it'll collect trash from memory or even result in an error, because NULL don't have a next position.
So, you use temp1 != NULL if you are accessing the data inside the list and temp1->next != NULL if you are manipulating the next positions of the linked list.
Because temp1->next at the end of the linked list is NULL, however, the last node has data, if you use temp1 == NULL you would say that the last node is NULL, which is not the case. So you want to end the loop when the "pointer to the next node" is NULL, not when the next node is NULL.

Cannot sort a linked list of dynamically assigned nodes

My program takes in any number of words from the user, and stops only when the user types three asterisks (***). These words will be stored in a linked list and sorted, but the elements in the list are not sorted when I try to print the list. Why is this happening?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_STRING_LEN 32 // Limit on length of each string
/* Link list node */
struct Node
{
int data;
struct Node* next;
};
// Function to insert a given node in a sorted linked list
void sortedInsert(struct Node**, struct Node*);
// function to sort a singly linked list using insertion sort
void insertionSort(struct Node **head_ref)
{
// Initialize sorted linked list
struct Node *sorted = NULL;
// Traverse the given linked list and insert every
// node to sorted
struct Node *current = *head_ref;
while (current != NULL)
{
// Store next for next iteration
struct Node *next = current->next;
// insert current in sorted linked list
sortedInsert(&sorted, current);
// Update current
current = next;
}
// Update head_ref to point to sorted linked list
*head_ref = sorted;
}
/* function to insert a new_node in a list. Note that this
function expects a pointer to head_ref as this can modify the
head of the input linked list (similar to push())*/
void sortedInsert(struct Node** head_ref, struct Node* new_node)
{
struct Node* current;
/* Special case for the head end */
if (*head_ref == NULL || (*head_ref)->data >= new_node->data)
{
new_node->next = *head_ref;
*head_ref = new_node;
}
else
{
/* Locate the node before the point of insertion */
current = *head_ref;
while (current->next!=NULL &&
current->next->data < new_node->data)
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
}
/* BELOW FUNCTIONS ARE JUST UTILITY TO TEST sortedInsert */
/* Function to print linked list */
void printList(struct Node *head)
{
struct Node *temp = head;
while(temp != NULL)
{
printf("%s \n ", temp->data);
temp = temp->next;
}
}
/* A utility function to insert a node at the beginning of linked list */
void push(struct Node** head_ref, int new_data)
{
/* allocate node */
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
// Main function
int main()
{
struct Node *a = NULL;
int index=1;
int i;
char * strings[MAX_STRINGS]; // Array of pointers
do
{
strings[index] = malloc(MAX_STRING_LEN * sizeof(char));
printf("Please input a word : ", index);
fgets(strings[index],MAX_STRING_LEN,stdin);
strtok(strings[index], "\n")=='\0';
}
while(strcmp(strings[index++], "***")!=0);
printf("\nThe input set, in alphabetical order:\n");
for (i = 1; i < index-1; i++)
{
push(&a, strings[i]);
}
insertionSort(&a);
printList(a);
free(strings[i]);
return 0;
}
Input:
pear
apple
***
Given output:
pear
apple
Expected output:
apple
pear
Hii I spent some time thinking what you wanted to do. And saw many problems with your code. I think you want something like this.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_STRING_LEN 32 // Limit on length of each string
#define MAX_STRINGS 100 // Limit the number of strings
struct Node {
char *data;
struct Node *next;
};
void sortedInsert(struct Node **head_ref, struct Node* new_node) {
struct Node *counter = *head_ref;
struct Node *previous = NULL;
while (counter != NULL && strcmp(counter->data,new_node->data) < 0){
previous = counter;
counter = counter->next;
}
if (previous != NULL) {
previous->next = new_node;
new_node->next = counter;
} else {
new_node->next = *head_ref;
*head_ref = new_node;
}
}
void push(struct Node **head_ref, char *new_data) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = NULL;
if (!head_ref) {
*head_ref = new_node;
return;
}
sortedInsert(head_ref,new_node);
}
void printList(struct Node *head) {
struct Node *temp = head;
while(temp != NULL) {
printf("%s\n", temp->data);
temp = temp->next;
}
}
void freeLinkedList(struct Node *head) {
struct Node *next;
while(head) {
next = head;
head = head->next;
free(next);
}
}
// Main function
int main() {
struct Node *a = NULL;
int index = 0;
int i;
char * strings[MAX_STRINGS]; // Array of pointers
do {
strings[index] = malloc(MAX_STRING_LEN * sizeof(char));
printf("Please input a word %d: ", index);
scanf("%s",strings[index]);
fflush(stdin);
} while(strcmp(strings[index++], "***") != 0 && index < MAX_STRINGS);
printf("\nThe input set, in alphabetical order:\n");
for (i = 0; i < index-1; i++) push(&a, strings[i]);
printList(a);
return 0;
}
I have tested it and it works fine.
If you have any doubts I would like to clear them.
If you want to know what's buggy in your code please feel free to ask.

Linked list insertion behaviour

I found some odd behaviour in my C code last night.
I have a few base functions for creating and manipulating C Linked Lists.
The behaviour of my insert at nth position is odd though.
The first version works fine, but the second version does not insert at all into the list. Am I missing something?
//This works fine
void insert_nth(struct node** head, int data, int n_pos){
if (n_pos == 0){
insert_top(head, data);
return;
}
struct node* current = *head;
for(int i = 0; i < n_pos - 1 ; i++){
if(current == NULL) return;
else current = current->next;
}
if(current == NULL) return;
insert_top(&(current->next), data);
}
//This doesn't insert at all
void insert_nth(struct node** head, int data, int n_pos){
if (n_pos == 0){
insert_top(head, data);
return;
}
struct node* current = *head;
for(int i = 0; i < n_pos ; i++){
if(current == NULL) return;
else current = current->next;
}
if(current == NULL) return;
insert_top(&(current), data);
}
Here are the rest of the functions I'm using for reference.
int main(){
struct node* head = NULL;
build_rand_list(&head);
list_print(&head);
return 0;
}
void list_print(struct node** head){
printf("List size is %d: List: ", list_length(head));
for(struct node* current = *head; current!= NULL; current = current->next)
printf("%d ", current->data);
printf("\n");
}
void build_rand_list(struct node** head){
//Assume head is NULL
assert(*head == NULL);
srand(time(NULL));
for (int i = 0; i < 10; i++){
int random_num = rand() % 11;
insert_end(head, random_num);
}
}
void insert_top(struct node** head, int data){
struct node *new_node = (struct node *)malloc(sizeof(struct node));
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
&(current) is the address of a local variable.
&(current->next) is the address of a pointer inside a node in the list.
Modifying the local variable current, which is what insert_top ultimately does, has no effect on the list's nodes.
For example if you pass the node with the value 2 to the insert_top function the result will be something like this
It seems like you don't handle the pointers correctly. For example there is no node that points to the new node you created.
A better implementation would be
void insert_nth(struct node *head, int data, int npos) {
struct node *current = head;
for (int i = 0; i < npos - 1; i++) {
current = current->next;
if (current == null) {
printf("%s\n", "Insert failed");
return;
}
}
struct node *new_node = (struct node *)malloc(sizeof(struct node *));
new_node->data = data;
new_node->next = current->next;
current->next = new_node;
return;
}
Where the head parameter is the actual head of the list.
The result will then me more satisfying. Hope this helps.

Reversing The Last 5 Nodes In A Linked List

I want to reverse the last 5 nodes in a linked list as follows:
Input: 2->4->6->8->10->12->14->16->NULL
Output: 2->4->6->16->14->12->10->8->NULL
I have written the following code to perform the above task but my reverse() function is not working.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
int n;
void insert(struct node **headref, int data) {
struct node *new_node;
new_node = malloc(sizeof(struct node));
new_node->data = data;
new_node->next = *headref;
*headref = new_node;
}
struct node* create() {
struct node dummy;
struct node *new_node = &dummy;
dummy.next = NULL;
int i,num;
printf("Enter The Number Of Data: ");
scanf("%d", &n);
for(i = 1; i <= n; i++) {
printf("Enter Data %d: ", i);
scanf("%d", &num);
insert(&(new_node->next), num);
new_node = new_node->next;
}
return dummy.next;
}
void display(struct node *head) {
struct node *current;
for(current = head; current != NULL; current = current->next) {
printf("%d ", current->data);
}
printf("\n");
}
void reverse(struct node *head) {
struct node *current, *next, *prev, *temp;
current = head;
next = current->next;
prev = NULL;
int i;
for(i = 0; i < n-5; i++) {
temp = current;
current = next;
next = next->next;
}
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
next = next->next;
}
temp->next = prev;
}
int main() {
struct node *start = create();
display(start);
reverse(start);
display(start);
}
Is there any error in my logic in the reverse() function? I tried the dry run on paper and it should have worked but it isn't working. Please point out the mistake that I made or even better suggest some alternative code to solve this problem.
The problem is in the line:
next = next->next;
in this part of the code:
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
next = next->next;
}
In the last element, when current becomes the last node current->next is NULL and you try to get next->next->next which gives segmentation fault.
You need to change the above line simply by adding an if statement:
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
if (next!=NULL) next = next->next;
}
I tried with your given input and it works!!

sorting a singly linked list with quicksort after user input and then inserting a new node and resorting list

I have my code for the most part but having a rough go of it trying to get my quick sort function to work and sort through the actual link list created. Don't know if I am calling the function improperly or if I have the struct correct.
The program will compile and run up until it gets to the calling function for the quicksort. Then it just freezes and does nothing. Any help would be great. Thank you a head of time.
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *link_list;
};
struct node *insertion(struct node *pointer, int i){
struct node *temp_val;
if(pointer == NULL){
pointer = (struct node *)malloc(sizeof(struct node));
if(pointer == NULL){
printf("Error Exiting\n");
exit(0);
}
pointer->data = i;
pointer->link_list = pointer;
}else{
temp_val = pointer;
while(temp_val->link_list != pointer){
temp_val = temp_val->link_list;
}
temp_val->link_list = (struct node *)malloc(sizeof(struct node));
if(temp_val->link_list == NULL){
printf("Error Exiting\n");
exit(0);
}
temp_val = temp_val->link_list;
temp_val->data = i;
temp_val->link_list = pointer;
}
return(pointer);
};
struct node *findPivot(struct node *head, struct node *term, struct node **newHead, struct node **newTerm){
struct node *pivot = term;
struct node *previous = NULL, *current = head, *tail = pivot;
//finding the pivot and dividing the list while also updating the head and term
// with newHead and newTerm
while(current != pivot){
if(current->data < pivot->data){
//assigning the newHead to the first value less then the pivot
if((*newHead) == NULL){
(*newHead) = current;
}
previous = current;
current = current->link_list;
}else{
// if the current node has a higher value then the pivot
// assinging it to newTerm
if(previous){
previous->link_list = current->link_list;
}
struct node *temp = current->link_list;
current->link_list = NULL;
tail->link_list = current;
tail = current;
current = temp;
}
}
//Checks the case if the pivot is the smallest value and moves to head
if((*newHead)== NULL){
(*newHead) = pivot;
}
(*newTerm) = tail; // makes sure the last element is newEnd
return pivot;
}
//finds the last node in the list and returns it
struct node *getTail(struct node *current){
while(current != NULL && current->link_list != NULL){
current = current->link_list;
}
return current;
}
// the actual recursive quicksort algorithm
struct node *quickSort(struct node *head, struct node *term){
if(!head || head == term) //base case for the recursion
return head;
struct node *newHead = NULL, *newTerm = NULL;
// the recursive case
struct node *pivot = findPivot(head, term, &newHead, &newTerm);
//no need for recursion if pivot is smallest value
if(newHead != pivot){
struct node *temp = newHead;
while(temp->link_list != pivot){
temp = temp->link_list;
}
temp->link_list = NULL;
newHead = quickSort(newHead, temp);
temp = getTail(newHead);
temp->link_list = pivot;
}
pivot->link_list = quickSort(pivot->link_list, newTerm);
return newHead;
}
void quickSortFunction(struct node **pointer){
*pointer = quickSort(*pointer, getTail(*pointer));
return;
}
void printList_Unsorted(struct node *pointer){
struct node *temp;
temp = pointer;
printf("\nThe Data values in the list are:\n");
if(pointer != NULL){
do{
printf("%d\t", temp->data);
temp = temp->link_list;
}while(temp != pointer);
}else{
printf("the list is empty\n");
}
}
void printList_Sorted(struct node *node){
while(node!= NULL){
printf("%d ", node->data);
node = node->link_list;
}
printf("\n");
}
int main(int argc, char *argv[]) {
int num_nodes, node_val;
struct node *list = NULL;
printf("Enter the number of nodes to be created: ");
scanf("%d", &num_nodes);
while(num_nodes --> 0){
printf("\n\nEnter the data values to be placed in a node: ");
scanf("%d", &node_val);
list = insertion(list, node_val);
}
printf("\n\nThe Created list is as follow:\n");
printList_Unsorted(list);
printf("\n");
quickSortFunction(&list);
printList_Sorted(list);
//getchar();
//getchar();
return 0;
}
Please look at this working example.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link_list;
};
void insertion(struct node **pointer, int i) {
struct node *temp_val = malloc(sizeof *temp_val);
temp_val->data = i;
temp_val->link_list = (*pointer);
(*pointer) = temp_val;
}
/* A utility function to print linked list */
void printList(struct node *node) {
while (node != NULL) {
printf("%d ", node->data);
node = node->link_list;
}
printf("\n");
}
// Returns the last node of the list
struct node *getTail(struct node *current) {
while (current != NULL && current->link_list != NULL)
current = current->link_list;
return current;
}
struct node *findPivot(struct node *head, struct node *term,
struct node **newHead, struct node **newTerm) {
struct node *pivot = term;
struct node *previous = NULL, *current = head, *tail = pivot;
while (current != pivot) {
if (current->data < pivot->data) {
if ((*newHead) == NULL)
(*newHead) = current;
previous = current;
current = current->link_list;
}
else
{
if (previous)
previous->link_list = current->link_list;
struct node *tmp = current->link_list;
current->link_list = NULL;
tail->link_list = current;
tail = current;
current = tmp;
}
}
// If the pivot data is the smallest element in the current list,
// pivot becomes the head
if ((*newHead) == NULL)
(*newHead) = pivot;
// Update newTerm to the current last node
(*newTerm) = tail;
// Return the pivot node
return pivot;
}
// the actual recursive quicksort algorithe
struct node *quickSort(struct node *head, struct node *end) {
// base case
if (!head || head == end)
return head;
struct node *newHead = NULL, *newEnd = NULL;
struct node *pivot = findPivot(head, end, &newHead, &newEnd);
if (newHead != pivot) {
struct node *tmp = newHead;
while (tmp->link_list != pivot)
tmp = tmp->link_list;
tmp->link_list = NULL;
newHead = quickSort(newHead, tmp);
tmp = getTail(newHead);
tmp->link_list = pivot;
}
pivot->link_list = quickSort(pivot->link_list, newEnd);
return newHead;
}
void quickSortFunction(struct node **headRef) {
(*headRef) = quickSort(*headRef, getTail(*headRef));
return;
}
int main() {
struct node *list = NULL;
int num_nodes, node_val;
printf("Enter the number of nodes to be created: ");
scanf("%d", &num_nodes);
while(num_nodes --> 0){
printf("\n\nEnter the data values to be placed in a node: ");
scanf("%d", &node_val);
insertion(&list, node_val);
}
printf("\n\nThe Created list is as follows:\n");
printList(list);
printf("\n");
quickSortFunction(&list);
printList(list);
return 0;
}
Test
/home/dac/.CLion2016.2/system/cmake/generated/gnu-fadf49ce/fadf49ce/Debug/gnu
Enter the number of nodes to be created: 3
Enter the data values to be placed in a node: 2
Enter the data values to be placed in a node: 4
Enter the data values to be placed in a node: 3
The Created list is as follows:
3 4 2
2 3 4
Process finished with exit code 0
The problem with your code was that it entered an infinite loop because the parameter was not a pointer to the node, but a pointer to the struct. You also don't need to return the list because you are passing it by reference.

Resources