How to use the variable globally in the function - c

I am writing a C code to insert an element to a sorted linked list. In this code I am using the variable "place" for deciding the position to insert the new element. But here it is getting error that "place" variable is to declared first. But I need the place globally for using in other functions. So what can I do to make it work? Also there is some problem with the function calling in the last part of main function. Please help me to correct it. Please let me know if there are any other errors. Thank You
#include<stdio.h>
#include<stdlib.h>
struct Node{
int data;
struct Node *next;
};
int calcSize(struct Node* node){
int size=0;
while(node!=NULL){
node = node->next;
size++;
}
return size;
}
void insertPosition(int pos, int data, struct Node** head)
{
int size = calcSize(*head);
if(pos < 1 || size < pos)
{
printf("Can't insert, %d is not a valid position\n",pos);
}
else
{
struct Node* temp = *head;
struct Node* newNode = (struct Node*)
malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
while(--pos)
{
temp=temp->next;
}
newNode->next= temp->next;
temp->next = newNode;
}
}
void insertStart(struct Node** head, int data){
struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
void insertLast(struct Node** head, int data){
struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
if(*head==NULL){
*head = newNode;
return;
}
struct Node* temp = *head;
while(temp->next!=NULL)
temp = temp->next;
temp->next = newNode;
}
void display(struct Node* node){
while(node!=NULL){
printf("%d ",node->data);
node = node->next;
}
printf("\n");
}
void check(struct Node* node,int ele){
while(node!=NULL){
int i=0;
if(ele>node->data)
{ place=i; break;}
node= node->next;
}
}
int main()
{ int ele; int place=0;
struct Node* head = NULL;
struct Node* node2 = NULL;
struct Node* node3 = NULL;
struct Node* node4 = NULL;
struct Node* node5 = NULL;
head = (struct Node*)malloc(sizeof(struct Node));
node2 = (struct Node*)malloc(sizeof(struct Node));
node3 = (struct Node*)malloc(sizeof(struct Node));
node4 = (struct Node*)malloc(sizeof(struct Node));
node5 = (struct Node*)malloc(sizeof(struct Node));
head->data = 5; head->next = node2;
node2->data = 10; node2->next = node3;
node3->data = 18; node3->next = node4;
node4->data = 26; node4->next = node5;
node5->data = 32; node5->next = NULL;
printf("Current Items in Linked List\n");
display(head);
printf("Enter the element to insert into LL\n");
scanf("%d",&ele);
printf("Inserting into Linked List....");
if(place=1)
{ void insertStart(&head, ele); }
else if(place=5)
{ void insertLast(&head, ele); }
else
{ void insertPosition(place, ele, &head); }
return 0;
}

Related

How to make to linked list in C?

Using two linked lists or something similar, I want to add "ABCD", then I want to get "ABDC".
I'm not sure if my code is right, I'm a noob in C.
The code should have pointer and malloc. I made it like this:
struct Node
{
char data;
struct Node* next;
};
struct Node* newNode(char data)
{
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
node->data = data;
node->next = NULL;
return node;
}
struct Node* constructList()
{
struct Node* first = newNode(1);
struct Node* second = newNode(2);
struct Node* third = newNode(3);
struct Node* forth = newNode(4);
struct Node* head = first;
first->next = second;
second->next = third;
third->next=forth;
return head;
}
void printList(struct Node* head)
{
struct Node* ptr = head;
while (ptr)
{
printf("%d -> ", ptr->data);
ptr = ptr->next;
}
printf("NULL");
}
Your code is fine as shown, though it lacks error handling (and why are you using char to store integers?).
Do make sure you free() the nodes when you are done using them, eg:
void freeList(struct Node* head)
{
struct Node* ptr = head;
struct Node* next;
while (ptr)
{
next = ptr->next;
free(ptr);
ptr = next;
}
}
I would suggest changing constructList() to use a loop, eg:
struct Node* constructList()
{
struct Node *head = NULL;
struct Node **ptr = &head;
for (int value = 1; value <= 4; ++value)
{
*ptr = newNode(value);
if (*ptr == NULL)
{
freeList(head);
return NULL;
}
ptr = &((*ptr)->next);
}
return head;
}
You could then generalize constructList() to take an array of integers, or a string, as input and loop through that input adding a new node for each value. For example, try this:
struct Node
{
char data;
struct Node* next;
};
struct Node* newNode(char data)
{
struct Node* node = (struct Node*) malloc(sizeof(struct Node));
if (node)
{
node->data = data;
node->next = NULL;
}
return node;
}
void freeList(struct Node* head)
{
struct Node* ptr = head;
struct Node* next;
while (ptr)
{
next = ptr->next;
free(ptr);
ptr = next;
}
}
struct Node* constructList(const char *str)
{
struct Node *head = NULL;
struct Node **ptr = &head;
char ch;
if (str)
{
while ((ch = *str++) != '\0')
{
*ptr = newNode(ch);
if (*ptr == NULL)
{
freeList(head);
return NULL;
}
ptr = &((*ptr)->next);
}
}
return head;
}
void printList(struct Node* head)
{
struct Node* ptr = head;
while (ptr)
{
printf("%c -> ", ptr->data);
ptr = ptr->next;
}
printf("NULL");
}
struct Node *list = constructList("ABCD");
printList(list);
freeList(list);

What is the problem with this piece of code?

I am writing for deleting the last node of a doubly linked list. But, every time this function is giving me segmentation fault when I have 2 or more than 2 elements in the list.
void deleteEnd()
{
struct node *ptr;
if(head==NULL)
printf("\nList is empty.First add some numbers");
else if(head->next==NULL)
{
head = NULL;
free(head);
}
else
{
ptr = head;
while(ptr->next != NULL)
{
ptr = ptr -> next;
}
ptr -> prev -> next = NULL;
free(ptr);
}
}
Normally, when you are deleting a node from a linked list it is a good practice to pass a reference to the first node of the list as an argument of the function. In your case you are not showing us where the head is coming from, and I think that it could be quite a useful info, and I bet that the error hides there.
That is how the implementation could look like:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// insert end node: this is for testing purposes
struct node *insertEnd(struct node *head, int value) {
struct node *ptr, *new_node;
ptr = head;
new_node = (struct node *) malloc(sizeof(struct node));
new_node->data = value;
new_node->next = NULL;
// The list is empty
if (head == NULL) {
head = new_node;
return head;
}
// Non empty list
while (ptr->next != NULL) {
ptr = ptr->next;
}
ptr->next = new_node;
return head;
}
// delete end node
struct node *deleteEnd(struct node *head) {
struct node *ptr, *preptr;
ptr = head;
preptr = NULL;
// The list is empty
if (head == NULL) {
printf("The list is empty. Nothing to delete.\n");
return head;
}
while(ptr->next != NULL) {
preptr = ptr;
ptr= ptr->next;
}
free(ptr);
if (preptr == NULL) {
head = NULL;
}
else {
preptr->next = NULL;
}
return head;
}
int main(void) {
struct node *llist;
llist = NULL;
llist = insertEnd(llist, 10);
llist = insertEnd(llist, 20);
llist = insertEnd(llist, 30);
llist = deleteEnd(llist);
llist = deleteEnd(llist);
llist = deleteEnd(llist);
return 0;
}
It is always a great idea to maintain a global variable head and update it after every push/pop. See this:
struct node
{
int data;
struct node *next;
};
struct node *start = NULL;
struct node *deleteEnd(struct node *start)
{
struct node *ptr = start;
if(ptr==NULL)
{
printf("\nList is empty!!!");
return start;
}
else if(ptr->next == NULL)
{
free(ptr);
start = NULL;
return start;
}
else
{
while((ptr->next)->next!=NULL) //by doing this you dont have to maintain a prev pointer
{
ptr=ptr->next;
}
struct node *temp = ptr->next;
free(temp);
ptr->next = NULL;
return start;
}
}
Hope this helps!!!

Why can't I set list pointer to minimal value (sorting words) in the list?

After inserting new element to the circular doubly linked list, when I set list pointer to minimal value, I can't see the value which was inserted to the list first (by creating the list), I can see only strange characters.
if I don't set the pointer to minimal value everything is working correctly, but I care to have the pointer set to minimal value.
struct Person {
char surname[N];
};
struct c_dll {
struct Person *data;
struct c_dll *next, *prev;
};
struct c_dll *create_list(char *surname) {
struct Person *new_person = (struct Person *)malloc(sizeof(struct Person));
strcpy(new_person->surname, surname);
struct c_dll *new_node = (struct c_dll *)malloc(sizeof(struct c_dll));
if (new_node != NULL) {
new_node->data = new_person;
new_node->next = new_node->prev = new_node;
}
return new_node;
};
struct c_dll *find_min(struct c_dll *node) {
char min_surname[20];
struct c_dll *result, *start;
strcpy(min_surname, node->data->surname);
start = result = node;
do {
if (strcmp(min_surname, node->data->surname) > 0) {
strcpy(min_surname, node->data->surname);
result = node;
}
node = node->next;
} while (start != node);
return result;
}
struct c_dll *find_next_node(struct c_dll *node, char *surname) {
node = find_min(node);
struct c_dll *start = node;
do {
if (strcmp(node->data->surname, surname) > 0)
break;
node = node->next;
} while (start != node);
return node;
}
void add_element(struct c_dll **list_ptr, char *surname) {
struct Person *new_person = (struct Person *)malloc(sizeof(struct Person));
strcpy(new_person->surname, surname);
struct c_dll *new_node = (struct c_dll *)malloc(sizeof(struct c_dll));
if (new_node != NULL) {
struct c_dll *node;
new_node->data = new_person;
node = find_next_node(&(*list_ptr), surname);
new_node->next = node;
new_node->prev = node->prev;
node->prev->next = new_node;
node->prev = new_node;
}
(*list_ptr) = find_min(&(*list_ptr));
}
The bug is in add_element: you pass &(*list_ptr) to find_min and find_next_node, which is incorrect and even a type mismatch that the compiler should diagnose.
You should just pass *list_ptr instead.
Here is a modified version:
int add_element(struct c_dll **list_ptr, const char *surname) {
struct Person *new_person = malloc(sizeof(*new_person));
if (new_person == NULL)
return -1;
strcpy(new_person->surname, surname);
struct c_dll *new_node = malloc(sizeof(*new_node));
if (new_node == NULL) {
free(new_person);
return -1;
} else {
struct c_dll *node;
new_node->data = new_person;
node = find_next_node(*list_ptr, surname);
new_node->next = node;
new_node->prev = node->prev;
node->prev->next = new_node;
node->prev = new_node;
*list_ptr = find_min(*list_ptr);
return 0;
}
}

insert end linked list

I am having problem in inserting data at the end of the linked list. I have tried everything but no help. It is only showing first and the last no but the numbers in between.
Following is my code.
struct node
{
int data;
struct node *next;
} *start;
add()
{
int a,b,c=0;
scanf("%d",&a);
struct node *new,*new1;
new=(struct node *)malloc(sizeof(struct node));
new1=(struct node *)malloc(sizeof(struct node));
while(a!=0)
{
c=a%10;
a=a/10;
if(start==NULL)
{
new->data=c;
start=new;
printf("%d\n",start->data);
}
else
{
new1->data=c;
new->next=new1;
new=new->next;
}
}
new->next=NULL;
}
you are re-writing 2nd node every-time. move to the last of linked list and then add
add()
{
int a,b,c=0;
scanf("%d",&a);
struct node *new,*new1;
while(a!=0)
{
c=a%10;
a=a/10;
new=(struct node *)malloc(sizeof(struct node));
if(start==NULL)
{
new->data=c;
new->next = NULL;
start=new;
printf("%d\n",new->data);
}
else
{
new1=(struct node *)malloc(sizeof(struct node));
new1 = start;
while(new1->next != NULL) {
new1 = new1->next;
}
new->data=c;
new->next = NULL;
printf("%d\n",new->data);
}
}
}
void print(struct node *p){
while(p){
printf("%d\n", p->data);
p = p->next;
}
}
void add(void){
int a;
scanf("%d", &a);
struct node *new, *curr;
for( ;a!=0; a /= 10){
new = (struct node *)malloc(sizeof(struct node));
new->data = a % 10;
new->next = NULL;
if(start==NULL)
start = curr = new;
else
curr = curr->next = new;
}
print(start);
}
Solved it. The problem was that I was using the same new1 again and again. When the satisfying case appears it should be always allocated memory. The modified code is as below:-
int a,b,c=0;
scanf("%d",&a);
while(a!=0)
{
struct node *new,*new1;
c=a%10;
a=a/10;
if(start==NULL)
{
new=(struct node *)malloc(sizeof(struct node));
new->data=c;
start=new;
printf("%d\n",start->data);
}
else
{
new1=(struct node *)malloc(sizeof(struct node));
new1->data=c;
new->next=new1;
printf("%d\n",new->next->data);
new=new->next;
new->next=NULL;
}
}

convert an ordered linked list to binary search tree

Here's my code. Please let me know the bug.The question is to convert a given ordered linked list into a binary search tree.
Thanks.
struct treenode* makeBSTnode(struct node* head)
{
struct treenode *root=(struct treenode*)malloc(sizeof(struct treenode));
root->data = head->data;
root->leftchild = NULL;
root->rightchild = NULL;
return root;
}
struct treenode* makeBST(struct node **head,int iterations)
{
if(iterations==0)
{
/*this is the code for the base condition*/
struct treenode *root=(struct treenode*)malloc(sizeof(struct treenode));
root = makeBSTnode(*head);
return root;
}
else
{
/*this is for the case when the node is not single but should be broken down into parts*/
struct node *leftchildnode=NULL,*rightchildnode=NULL,*rootnode=NULL,*temp;
temp = (struct node*)malloc(sizeof(struct node));
struct treenode *root = (struct treenode*)malloc(sizeof(struct treenode));
int limit = (int)ceil((float)(3*iterations)/2);
for(int i=1;i<=limit;i++)
{
if(i==(int)ceil((float)iterations/2))
{
leftchildnode = (struct node*)malloc(sizeof(struct node));
leftchildnode = *head;
}
else if(i==iterations)
{
rootnode = (struct node*)malloc(sizeof(struct node));
rootnode = *head;
}
else if(i==(int)ceil((float)(3*iterations)/2))
{
rightchildnode = (struct node*)malloc(sizeof(struct node));
rightchildnode = *head;
}
if(*head)
(*head) = (*head)->next;
else
break;
}
root = makeBSTnode(rootnode);
root->leftchild = makeBST(&temp,(int)ceil((float)iterations/2));
root->rightchild = makeBST(&rootnode,(int)ceil((float)(3*iterations/2)));
return root;
}
}
I called this makeBST function in main as:
root = makeBST(&head,(int)ceil((float)length/2));

Resources