Ascending order in linked list in c - c

I am trying to do ascending order in linked list through change of links and addresses rather than value
struct node
{
char name[30];
int percent;
struct node *link;
};
int main
{
clrscr();
randomize();
struct node *st;
st=NULL;
for(int i=0;i<7;i++)
append(&st,random(101)); //Assigning random values to structure node->percent
display(st);
AscMarks(&st); //Changing the order of links and addresses to arrange them in ascending order
printf("\nAscending order list...\n");
display(st);
getch();
return 0;
}
/*Adds a node at the end of a linked list */
void append(struct node **q,int per)
{
struct node *temp,*r;
temp=*q;
/* If the list is empty , create first node */
if(temp==NULL)
{
temp=(node*)malloc(sizeof(struct node));
temp->percent=per;
getName(temp->name);
temp->link=NULL;
*q=temp;
}
else
{
while(temp->link!=NULL)
temp=temp->link;
r=(struct node*)malloc(sizeof(struct node));
r->percent=per;
getName(r->name);
r->link=NULL;
temp->link=r;
}
}
/*Displays the contents of the linked list */
void display(struct node *q)
{
while(q!=NULL)
{
printf("%d\t%s\n",q->percent,q->name);
q=q->link;
}
}
void getName(char *c)
{
for(int i=0;i<30;i++)
{
if(i==10||i==20)
*(c+i)=' ';
else
*(c+i)=(char)((random(26)+97));
}
*(c+i+1)='\0';
}
/*To change the links and addresses in order to arrange the percent in ascending order */
void AscMarks(struct node **q)
{
struct node *temp,*temp1,*r;
temp=*q;
// r=q;
for(int i=0;i<7;i++,temp=temp->link)
{ temp1=temp->link;
for(int j=i+1;j<7;j++,temp1=temp1->link)
{
if(temp->percent>temp1->percent)
{
r=*q;
while(r->link!=temp1)
{
r=r->link;
}
r->link=temp1->link;
temp1->link=temp;
temp=temp1;
}
}
if(i==0)
*q=temp;
}
temp->link=NULL;
/*
while(r!=NULL)
{
printf("\n%d",r->percent);
r=r->link;
} */
}
Ascending order (AscMarks) is not giving results as expected and I am unable to see what's my fault in the code Please help

You are not establishing link between the smallest address to the second smallest address and so on ... i have got that through node variable "*s"
by s->link=temp& giving the address of last sorted value (temp) to s..through s=temp.. And in "j" loop after each time , temp->percent> temp1->percent .. you have done temp1-link=temp, it makes the address of temp1, the address of starting temp... means in short ... the number of tries of "j" will be too less to compare all the addresses ... as most of it will repeat ...
so for it you should do j=i;
void AscMarks(struct node **q)
{
struct node *temp,*temp1,*r,*s;
temp=*q;
// r=q;
for(int i=0;i<7;i++,temp=temp->link)
{ temp1=temp->link;
for(int j=i+1;j<7;j++,temp1=temp1->link)
{
if(temp->percent>temp1->percent)
{
r=*q;
while(r->link!=temp1)
{
r=r->link;
}
r->link=temp1->link;
j=i;//resetting the value of j
temp1->link=temp;
temp=temp1;
if(i!=0)
s-link=temp; //establishing link between
//this sorted address(in this loop) to the
//last sorted address
}
}
if(i==0)
*q=temp;
s=temp;//giving it the address of structure which have the last
//sorted value
}
temp->link=NULL; //No need to do this
/*
while(r!=NULL)
{
printf("\n%d",r->percent);
r=r->link;
} */
}

Related

C language:Binary search tree with strings

I have to create a program for a binary search tree for strings, which calculates how many times each word repeats, and it seems like I can't get the program to do as intended, because when printing it out, what should be printed first, are the words/characters smaller than the origin node, followed by the words/characters bigger than the origin node. But what my program does, it just prints it out in the order that I introduced the words/characters, I am still thinking about, how to realise the part of the program that will calculate the number of appearances of each word.
#include<stdio.h>
#include<stdlib.h>
#define MAX 15
typedef struct BST
{
char data[MAX];
struct BST *left;
struct BST *right;
} node;
node *create();
void insert(node *,node *);
void preorder(node *);
int main()
{
char ch;
node *root=NULL,*temp;
do
{
temp=create();
if(root==NULL)
{
root=temp;
}
else
{
insert(root,temp);
}
printf("\nDo you want to enter more(y/n)?");
ch=getch();
}
while(ch=='y'||ch=='Y');
printf("\nPreorder Traversal: ");
preorder(root);
return 0;
}
node *create()
{
node *temp;
printf("\nEnter data:");
temp=(node*)malloc(sizeof(node));
fgets(&temp->data,MAX,stdin);
temp->left=temp->right=NULL;
return temp;
}
void insert(node *root,node *temp)
{
if(temp->data<root->data)
{
if(root->left!=NULL)
insert(root->left,temp);
else
root->left=temp;
}
if(temp->data>root->data)
{
if(root->right!=NULL)
insert(root->right,temp);
else
root->right=temp;
}
}
void preorder(node *root)
{
if(root!=NULL)
{
printf("%s ",root->data);
preorder(root->left);
preorder(root->right);
}
}
Here's what I came up with, with the help of somebody in the comments, and it works as intended
void insert(node *root,node *temp)
{
int cmp_rezult=strcmp(temp->data,root->data);
printf("\nCompare:%d ", cmp_rezult);
if(cmp_rezult<0)
{
if(root->left!=NULL)
insert(root->left,temp);
else
root->left=temp;
}
if(cmp_rezult>0)
{
if(root->right!=NULL)
insert(root->right,temp);
else
root->right=temp;
}
}
In insert you do:
temp->data<root->data
but that's not how you compare strings in C.
To compare strings use strcmp
Further it seems that insert miss a code block for handling "equal".
So something like:
int cmp_result = strcmp(temp, data<root->data);
if (cmp_result < 0)
{
// Handle less than
}
else if (cmp_result > 0)
{
// Handle greater than
}
else // i.e. cmp_result == 0
{
// Handle equal
}

How to find the maximum element from the linked list?

This is what I have tried so far.
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
void create(struct node **q)
{
struct node *r,*t;
int cnt,i,dat;
printf("How many nodes?");
scanf("%d",&cnt);
for(i=0;i<cnt;i++)
{
printf("Enter the data %d ",i);
scanf("%d",&dat);
r=(struct node *) malloc (sizeof(struct node));
r->data=dat;
r->next=NULL;
if(*q==NULL)
{
*q=r;
}
else
{
t=*q;
while(t->next!=NULL)
{
t=t->next;
}
t->next=r;
}
}
}
void display(struct node **q)
{
struct node *r;
r=*q;
while(r!=NULL)
{
printf("%d->",r->data);
r=r->next;
}
printf("\n");
}
void max(struct node **q)
{
struct node *r;
int max=0;
r=*q;
while((r->next)!=NULL)
{
max=r->data;
r=r->next;
if((r->data)>max)
{
max=r->data;
}
}
printf("The max is %d",max);
printf("\n");
}
int main()
{
struct node *head;
create(&head);
display(&head);
max(&head);
}
If I use the numbers 1, 2, and 3 as input my program currently incorrectly detects 2 as the maximum element. How can I fix it so that it will correctly determine 3 to be the maximum element?
rutuparna#pucsd-rutuparna:~/C/Datastructures assignment$ gcc linkedmax.c
rutuparna#pucsd-rutuparna:~/C/Datastructures assignment$ ./a.out
How many nodes?3
Enter the data 0 3
Enter the data 1 2
Enter the data 2 1
3->2->1->
The max is 2
There are a few issues with the loop
while((r->next)!=NULL) {
max=r->data;
r=r->next;
if((r->data)>max) {
max=r->data;
}
}
The line max=r->data unconditionally updates max. Combining this with the fact that the test (r->next)!=NULL causes your loop to exit one item early, the loop currently always returns the value of the second last item.
The code should be changed to something like
while(r!=NULL) {
if(r->data>max) {
max=r->data;
}
r=r->next;
}

What is wrong with this insertion sort using linked list code in c?

I am getting error while executing this. Compiler does not give any error but when executed it give random output.
What am i doing is taking input from user & storing them to linked list & then implementing insertion sort.
( I am able to call the subroutine insertion sort, so I guess the problem lies within subroutine only)
#include<stdio.h>
#include<stdlib.h>
struct node
{
int info;
struct node *next;
};
typedef struct node *NODEPTR;
NODEPTR getnode();
NODEPTR insertionSortLinkedList(NODEPTR head);
int main()
{
int i,n,temp;
NODEPTR head,lptr,prevlptr;
printf("No of input integers to be sorted\n");
scanf("%d",&n);
if (n<2){printf("n should be atleast 2 \n");return 0;}
printf("\nType space-separated array of %d integers\n",n);
scanf("%d",&temp);
head=getnode();
head->info=temp;
head->next=NULL;
prevlptr=head;
for (i=0;i<n-1;i++)
{
scanf("%d",&temp);
lptr=getnode();
lptr->info=temp;
prevlptr->next=lptr;
lptr->next=NULL;
prevlptr=lptr;
}
head=insertionSortLinkedList(head);
lptr=head;
while(lptr!=NULL)
{
printf("%d ",lptr->info);
prevlptr=lptr;
lptr=lptr->next;
free(prevlptr);
}
return 0;
}
NODEPTR getnode()
{
NODEPTR p;
p=(struct node*)malloc(sizeof(struct node));
return p;
}
NODEPTR insertionSort(NODEPTR head)
{
NODEPTR listptr,tempptr,prevptr,prevtempptr;
prevptr=head;
listptr=prevptr->next;
while(listptr!=NULL)
{
while (listptr->info < prevptr->info)
{
prevptr->next=listptr->next;
tempptr=head;
prevtempptr=head;
while(tempptr->info <= listptr->info)
{
prevtempptr=tempptr;
tempptr=tempptr->next;
}
if(tempptr->info == prevtempptr->info)
{
listptr->next=head;
head=listptr;
}
else
{e
listptr->next=prevtempptr->next;
prevtempptr->next=listptr;
}
listptr=prevptr->next;
if (listptr==NULL)
break;
}
prevptr=prevptr->next;
if (prevptr=NULL)
break;
listptr=prevptr->next;
}
return(head);
}
What is wrong with my code and how do I fix it?
The 6th line form last
if (prevptr=NULL)
it should be
if (prevptr==NULL)
Single "=" does the assignment instead of comparison.

What is wrong with my array of linked lists implementation as all elements get over-written?

I'm trying to implement a hash table as an array of linked lists. Currently I'm trying to have a simple hash table where the key is the index of the array and value is a singly linked list for implementing chaining.
This is the code that I've written so far:
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int value;
struct Node *next;
};
struct Node *hashtable[7];
int empty(int index)
{
if(hashtable[index]==NULL)
return 0;
return 1;
}
void addNode(int frame,struct Node **iter)
{
if(*iter==NULL)
*iter=malloc(sizeof(struct Node));
else
{
while((*iter)->next != NULL)
(*iter)=(*iter)->next;
(*iter)->next=malloc(sizeof(struct Node));
(*iter)=(*iter)->next;
}
(*iter)->value=frame;
(*iter)->next=NULL;
}
void print()
{
int i;
struct Node **iter;
for(i=0;i<7;i++)
{
iter=&hashtable[i];
while(*iter !=NULL)
{
printf("%d%s%d\n",(*iter)->value,"--",i);
(*iter)=(*iter)->next;
}
}
}
int main()
{
int i=0,count=7;
for(i=0;i<7;i++)
hashtable[i]=NULL;
i=empty(1);
printf("%d",i);
do
{
printf("Enter no:\n");
scanf("%d",&i);
struct Node** temp;
temp=&hashtable[i-1%7];
addNode(rand(),temp);
count--;
print();
} while(count > 0);
return 0;
}
When I'm calling print, I can only see one element added to one particular index, which is the last element that was added, what am I doing wrong here?
void add_node(int frame,struct Node **iter)
{
/* find (pointer to) NULL pointer at end of chain */
for ( ; *iter; iter = &(*iter)->next ) {;}
*iter = malloc(sizeof **iter );
(*iter)->value = frame;
(*iter)->next = NULL;
}

can my code for reversing link list be further enhanced

Here is my program which creates a link list and also reverses it.
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *list=NULL;
struct node *root=NULL;
static int count=0;
struct node *create_node(int);//function to create node
void travel_list(void);
void create_list(int);
void reverse_list(void);
int main()
{
int i, j, choice;
printf("Enter a number this will be root of tree\n");
scanf("%d", &i);
create_list(i);
printf("Enter 1 to enter more numbers \n 0 to quit\n");
scanf("%d", &choice);
while (choice!=0){
printf("Enter a no for link list\n");
scanf("%d",&i);
// printf("going to create list in while\n");
create_list(i);
travel_list();
printf("Enter 1 to enter more numbers \n 0 to quit\n");
scanf("%d", &choice);
}
printf("reversing list\n");
reverse_list();
travel_list();
}
// end of function main
void create_list (int data)
{
struct node *t1,*t2;
//printf("in function create_list\n");
t1=create_node(data);
t2=list;
if( count!=0)
{
while(t2->next!=NULL)
{
t2=t2->next;
}
t2->next=t1;
count++;
}
else
{
root=t1;
list=t1;
count++;
}
}
struct node *create_node(int data)
{
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->data=data;
temp->next=NULL;
// printf("create node temp->data=%d\n",temp->data);
// printf("the adress of node created %p\n",temp);
return temp;
}
void travel_list(void )
{
struct node *t1;
t1=list;
printf("in travel list\n");
while(t1!=NULL)
{
printf("%d-->",t1->data);
t1=t1->next;
}
printf("\n");
}
void reverse_list(void)
{
struct node *t1,*t2,*t3;
t1=list;
t2=list->next;
t3=list->next->next;
int reverse=0;
if(reverse==0)
{
t1->next=NULL;
t2->next=t1;
t1=t2;
t2=t3;
t3=t3->next;
reverse++;
}
while(t3!=NULL)
{
t2->next=t1;
t1=t2;
t2=t3;
list=t1;
travel_list();
t3=t3->next;
}
t2->next=t1;
list=t2;
}
Above is a fully working code.
I want to know if there can be further enhancement to the above code?
Make your indentation and whitespace usage consistent
Use meaningful identifiers rather than t1, t2 and t3
Make the data member a generic type, for example void * rather than int.
Don't use global variables, pass struct node * pointers to your functions.

Resources