We are given the main function and structures, asked to create two different linked lists. One being in ascending order and another in descending order and then joined together without changing their order. To give an example,if we have L1: 1->3->4->6 and L2: 9->8->5->2, The final list would be 1->9->3->8->4->5->6->2. This below is my work. I'm having some problems.
This is the main function:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "function.h"
struct nodeFB *startFB = NULL;
struct nodeGS *startGS = NULL;
struct newNodeFB *startNewFB = NULL;
int main()
{
int id, age;
scanf("%d", &id);
while(id!=-1)
{
scanf("%d", &age);
insertFB(&startFB, id, age);
scanf("%d", &id);
}
scanf("%d", &id);
while(id!=-1)
{
insertGS(&startGS, id);
scanf("%d", &id);
}
printFB(startFB);
printGS(startGS);
createFinalList(&startNewFB,startFB,startGS);
printAll(startNewFB);
return 0;
}
These are the given structures and the functions I've written:
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
struct nodeFB
{
int id;
int age;
struct nodeFB *next;
};
struct nodeGS
{
int id;
struct nodeGS *next;
};
struct newNodeFB
{
int id;
int age;
struct newNodeGS *next;
};
struct newNodeGS
{
int id;
struct newNodeFB *next;
};
struct nodeFB *startFB;
struct nodeGS *startGS;
//functions
struct nodeFB *insertFB( struct nodeFB **startFB, int id, int age)
{//address of the first node in the linked list of FB
struct nodeFB *newnode, *ptr;
newnode = (struct nodeFB*)malloc(sizeof(struct nodeFB));
newnode->id = id;
newnode->age = age;
if (startFB == NULL) {
newnode->next = NULL;
*startFB = newnode;
}
else {
ptr = *startFB;
while(ptr->next!=NULL) {
ptr=ptr->next;
ptr->next= newnode;
newnode->next = NULL;
}
}
return *startFB;
}
void swap(struct nodeFB *a, struct nodeFB *b) {//function to swap two nodes
int temp = a->id;
a->id = b->id;
b->id = temp;
}
void sortFB(struct nodeFB *startFB) { //function to bubble sort the given linked list
int i;
int swapped;
struct nodeFB *ptr1;
struct nodeFB *ptr2= NULL;
if (startFB==NULL) { //checking for empty list
return; }
do {
swapped = 0;
ptr1=startFB;
while (ptr1->next !=ptr2) {
if (ptr1->id > ptr1->next->id) {
swap (ptr1, ptr1->next);
swapped = 1;
}
ptr1= ptr2->next;
}
ptr2=ptr1;
}
while (swapped);
}
void printFB(struct nodeFB *startFB) { //function to display the sorted list
struct nodeFB *ptr;
ptr = startFB;
sortFB(ptr);
while(ptr != NULL) {
printf("%d %d/n", ptr->id, ptr->age);
ptr=ptr->next;
}
}
struct nodeGS *insertGS(struct nodeGS **startGS, int id ) {
struct nodeGS *newnode, *ptr;
newnode = (struct nodeGS*)malloc(sizeof(struct nodeGS));
newnode->id = id;
if (startGS == NULL) {
newnode->next = NULL;
*startGS = newnode;
}
else {
ptr = *startGS;
while(ptr->next!=NULL) {
ptr=ptr->next;
ptr->next= newnode;
newnode->next = NULL;
}
}
return *startGS;
}
void swapGS(struct nodeGS *c, struct nodeGS *d) {//function to swap two nodes
int temp = c->id;
c->id = d->id;
d->id = temp;
}
void sortGS(struct nodeGS *startGS) { //function to bubble sort the given linked list
int i;
int swapped;
struct nodeGS *ptr1;
struct nodeGS *ptr2= NULL;
if (startGS==NULL) { //checking for empty list
return; }
do {
swapped = 0;
ptr1=startGS;
while (ptr1->next !=ptr2) {
if (ptr1->id < ptr1->next->id) {
swapGS (ptr1, ptr1->next);
swapped = 1;
}
ptr1= ptr2->next;
}
ptr2=ptr1;
}
while (swapped);
}
void printGS(struct nodeGS *startGS) {
struct nodeGS *ptr;
ptr = startGS;
sortGS(startGS);
while(ptr != NULL) {
printf("%d/n", ptr->id);
ptr = ptr->next;
}
}
**struct newNodeFB *createFinalList(struct newNodeFB **startNewFB, struct nodeFB *startFB, struct nodeGS *startGS ) {
struct newNodeFB *temp1, *ptr1;
temp1=(struct newNodeFB*) malloc(sizeof(struct newNodeFB));
temp1->id= startFB->id;
temp1->age=startFB->age;
struct newNodeGS *temp2;
temp2->id= startGS->id;
struct newNodeFB *temp3 = NULL;
struct newNodeGS *temp4 = NULL;
while (temp1 != NULL && temp2 != NULL)
{
ptr1=temp1;
while (ptr1->next!=NULL) {
ptr1=ptr1->next;
ptr1->next= temp2;
temp2->next=NULL;
}
temp3=temp1->next;
temp4= temp2->next;
temp1->next=temp2;
temp2->next=temp3;
temp1=temp3;
temp2=temp4;
}
startGS = temp2;
return startNewFB;
}**
void printALL(struct newNodeFB *startNewFB){
struct newNodeFB *ptr;
ptr= startNewFB;
while(ptr != NULL) {
printf("%d %d/n%d", startNewFB->id, startNewFB->age, startNewFB->id);
ptr=ptr->next;
}
}
The simplest way to create a merged list where the nodes alternate, is to simply iterate over both lists simultaneously and add each node from the two lists into a brand new list.
Because you want to alternate between the two lists, you need to use a single loop to iterate the lists, adding one node from the first list to the new merge-list, then adding one node from the second list. Stop when both lists are finished.
In pseudoish code it could look something like this:
Node *node1 = list1->head; // Node from first list
Node *node2 = list2->head; // Node from second list
// Loop while there are nodes in at least one of the lists
while (node1 != NULL || node2 != NULL)
{
if (node1 != NULL)
{
list_add_tail(merge_list, node1->data);
node1 = node1->next;
}
if (node2 != NULL)
{
list_add_tail(merge_list, node2->data);
node2 = node2->next;
}
}
As seen it's basically the same as iterating over a single list, copying data to a new list.
Another consideration is if one is mixing struct nodeFB and struct nodeGS in one list, how could the programme tell if the node is an FB or GS? Unless the lists are of equal sizes, where they are alternating, one loses type information by mixing them together.
There are several ways to get around this. One could only allow one type of node in one list; one has to convert the types to mix the lists. One might as well convert on input and have one type of list. A more nuanced approach is to store a pointer telling what type it is with every node.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* Circular definitions mean one has to forward declare. */
struct node;
static void foo_print(const struct node *);
static void bar_print(const struct node *);
/* Virtual table stores the type of node. */
typedef void (*print_fn)(const struct node *);
static const struct vt { print_fn print; }
foo_vt = { &foo_print }, bar_vt = { &bar_print };
/* A list of nodes. */
struct node { struct node *next; const struct vt *vt; };
struct list { struct node *head; };
/* Subclasses of node. */
struct foo_node {
struct node base;
int id, age;
};
struct bar_node {
struct node base;
int id;
};
/* Implementations of the above. */
static void foo_print(const struct node *node) {
const struct foo_node *ptr = (const struct foo_node *)node;
printf("(foo)%d age %d", ptr->id, ptr->age);
}
static void bar_print(const struct node *node) {
const struct bar_node *ptr = (const struct bar_node *)node;
printf("(bar)%d", ptr->id);
}
static struct node *foo_input(void) {
int id, age;
struct foo_node *foo;
if((printf("Id: "), scanf(" %d", &id) != 1) || id == -1
|| (printf("Age: "), scanf(" %d", &age) != 1)
|| !(foo = malloc(sizeof *foo))) return 0;
foo->base.vt = &foo_vt;
foo->id = id;
foo->age = age;
fprintf(stderr, "User entered %d, %d.\n", foo->id, foo->age);
return &foo->base;
}
static struct node *bar_input(void) {
int id;
struct bar_node *bar;
if((printf("Id: "), scanf(" %d", &id) != 1) || id == -1
|| !(bar = malloc(sizeof *bar))) return 0;
bar->base.vt = &bar_vt;
bar->id = id;
fprintf(stderr, "User entered %d.\n", bar->id);
return &bar->base;
}
//address of the first node in the linked list
static void push(struct list *start, struct node *node) {
assert(start && node);
node->next = start->head, start->head = node;
}
static void printAll(const struct list *list) {
struct node *node;
for(node = list->head; node; node = node->next)
printf("%s", node == list->head ? "" : ", "), node->vt->print(node);
printf(".\n");
}
/** Interleaves the list `bars` with the list `foos`. `bars` will be the empty
list and `foos` will have all of the elements. */
static void createFinalList(struct list *foos, struct list *bars) {
/* Create this function. */
(void)foos, (void)bars;
}
int main(void) {
struct list foos = { 0 }, bars = { 0 };
struct node *node;
while(node = foo_input()) push(&foos, node);
while(node = bar_input()) push(&bars, node);
printf("foos: "), printAll(&foos);
printf("bars: "), printAll(&bars);
createFinalList(&foos, &bars);
printf("now,\n");
printf("foos: "), printAll(&foos);
printf("bars: "), printAll(&bars);
/* fixme: Memory leak, clean up. */
return 0;
}
If one really cannot modify the nodes, maybe encompass them in a union?
struct node {
const struct vt *vt;
union { struct nodeFB fb; struct nodeGS gs; };
};
Related
struct item {
char name[32];
struct item *next;
};
struct item *create_item(char *name) {
struct item *result = malloc(sizeof(struct item));
strcpy(result->name, name);
result->next = NULL;
return result;
}
int equals(char *a, char *b) {
return strcmp(a, b) == 0;
}
void append(struct item **list, struct item *i){
i = malloc(sizeof(struct item));
struct item *last = *list;
strcpy(i->name, i->name);
i->next = NULL;
if(*list == NULL){
*list = i;
}
while(last->next != NULL) {
last = last->next;
}
last->next = i;
}
int main(void) {
struct item *list = NULL;
append(&list, create_item("Dog"));
append(&list, create_item("Cat"));
append(&list, create_item("Bat"));
assert(equals(list->next->next->name, "Bat"));
}
I would like to append a new struct node at the end of a list, but I get an error (segmentation fault) when I try to run main.
Can someone please help me? :-)
I think the problem might be that I am initializing the list with NULL in main, but I don't know what I need to change so the append-function can handle it.
You have several errors:
demo.c: In function ‘append’:
demo.c:26:13: warning: passing argument 1 to ‘restrict’-qualified parameter aliases with argument 2 [-Wrestrict]
26 | strcpy(i->name, i->name);
You malloc an already malloced object here:
i = malloc(sizeof(struct item)); // choose a better name, 'i' sucks :)
And the main problem, you never connect the head (list) in the append function.
Your code working:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
struct item {
char name[32];
struct item *next;
};
struct item *create_item(const char *name) // const added
{
struct item *result = malloc(sizeof(struct item));
strcpy(result->name, name);
result->next = NULL;
return result;
}
int equals(char *a, char *b)
{
return strcmp(a, b) == 0;
}
void append(struct item **list, struct item *item)
{
if (*list == NULL)
{
*list = item;
return;
}
struct item *next = *list;
struct item *tail = NULL;
while (next != NULL)
{
tail = next;
next = next->next;
}
tail->next = item;
}
int main(void)
{
struct item *list = NULL;
append(&list, create_item("Dog"));
append(&list, create_item("Cat"));
append(&list, create_item("Bat"));
assert(equals(list->next->next->name, "Bat"));
}
Please, next time provide a compilable snippet.
I am trying to sort a doubly linked list in ascending order. I've gone trough the code again and again, and I can't find any logical flaws with it, so I assume the problem is elsewhere. When I try to print the sorted list, the console returns 0 without printing anything (the print function is not to blame, since it has already been tested)
Here is the code I am currrently running:
typedef struct dados_temp{
float temp;
float incerteza;
char pais[100];
char cidade[100];
float angle;
int hemisferio;
int dia;
int mes;
int ano;
} dados_temp;
typedef struct Node{
dados_temp payload;
struct Node *next;
struct Node *prev;
} Node;
//receives the original head pointer
//returns sorted list's head pointer
Node** SortDate(struct Node** head)
{
struct Node *i, *j;
for( i = head; i != NULL; i = i->next )//iterates over the entire list
{
//if the data value of the next node is bigger
if ( i->payload.ano > i->next->payload.ano )
{
//swaps the data value between i and i->next
//SwapNodes was tested and it is working
SwapNodes(i, i->next);
//the current value of i->next (former value of i)
//is compared to all the previous values
//and keeps swapping until a smaller value is found
for (j = i->next; j->payload.ano < j->prev->payload.ano;)
{
SwapNodes(j, j->prev);
}
}
}
return head;
}//sort
I know there probably are easier ways to sort doubly linked list, but I'm trying to figure out why this one doesn't work.
Thank you in advance!
EDIT:
showing all the involved functions:
#include <stdio.h>
#include <stdlib.h>
typedef struct dados_temp{
float temp;
float incerteza;
char pais[100];
char cidade[100];
float angle;
int hemisferio;
int dia;
int mes;
int ano;
} dados_temp;
typedef struct Node{
dados_temp payload;
struct Node *next;
struct Node *prev;
} Node;
Node * CreateCitiesList();
Node * CreateCountriesList();
Node * Intervalos(struct Node*, int[]);
void PrintBack(struct Node*);
struct Node* CreateNode (dados_temp x)
{
struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
NewNode->payload = x;
NewNode->next = NULL;
NewNode->prev = NULL;
return NewNode;
}
}
void Print (struct Node* head)
{
struct Node* temp = head;
while ( temp != NULL)
{
printf("%d-%d-%d \n", temp->payload.ano, temp->payload.mes,
temp>payload.dia);
fflush(stdout);
temp = temp->next;
}
printf("\n");
}
Node* SortDate (struct Node*);
void SwapNodes (struct Node*, struct Node*);
int main(int argc, char* argv[])
{
CreateCountriesList();
}
Node* CreateCountriesList()
{
char linha[150] = {NULL};
char cabecalho[100] = {NULL};
int i = 0;
dados_temp New_Entry;
dados_temp tail;
int *ptr_head_co;
struct Node* head_countries = NULL;
struct Node* Node = NULL;
FILE *inputf;
inputf = fopen("tempcountries_all.csv", "r");
if (inputf == NULL)
{
printf("Nao da pa abrir o fitchas boi");
exit(EXIT_FAILURE);
}
//gets rid of the first line
fgets(cabecalho, 100, inputf);
for (i = 0; i < 577462 ; i++)
{
fgets(linha, 150, inputf);
//scans the date(amongst other things) from file (yyyy-mm-dd)
sscanf(linha, "%d-%d-%d,%f,%f,%[^,]s", &New_Entry.ano,
&New_Entry.mes,&New_Entry.dia, &New_Entry.temp, &New_Entry.incerteza,
&New_Entry.pais);
if (head_countries == NULL)
{
head_countries = CreateNode(New_Entry);
Node = CreateNode(New_Entry);
}
else
{
head_countries = InsertHead(head_countries, New_Entry);
}
}
fclose(inputf);
head_countries = RemoveNodes(Node);
SortDate(head_countries);
Print(head_countries);
return head_countries;
}
Node* SortDate(struct Node* head)
{
struct Node *i, *j;
for( i = head; i != NULL; i = i->next )
{
if ( i->payload.ano > i->next->payload.ano )
{
SwapNodes(i, i->next);
for (j = i->next; j->payload.ano < j->prev->payload.ano;)
{
SwapNodes(j, j->prev);
}
}
}
}//sort
void SwapNodes(struct Node* node1, struct Node* node2)
{
dados_temp temp = node1->payload;
node1->payload = node2->payload;
node2->payload = temp;
}
Okay so I've been doing a program which would read elements of a txt file using scanf (cmd input redirection). A new node must be created for every entry in the file and add it at the end of the list. Here's my code so far:
struct Elem{
int Atnum;
char Na[31];
char Sym[4];
};
struct nodeTag {
struct Elem entry;
struct nodeTag *pNext; // pointer to the next node
};
typedef struct nodeTag Node;
The function that would initialize it is this:
Node *
InitializeList(Node *pFirst, int n)
{
int i;
Node *head, *temp = 0;
pFirst = 0;
for (i=0; i<n; i++){
head = (Node *)malloc(sizeof(Node));
scanf("%d", &head->entry.AtNum);
scanf("%s", head->entry.Na);
scanf("%s", head->entry.Sym);
if (pFirst != 0)
{
temp->pNext = head;
temp = head;
}
else
{
pFirst = temp = head;
}
fflush(stdin);
temp->pNext = 0;
}
return pFirst;
}
and lastly, print it
void
Print( Node *pFirst )
{
Node *temp;
temp = pFirst;
printf("\n status of the linked list is\n");
while (temp != 0)
{
printf("%d %s %s", temp->entry.AtNum, temp->entry.Na, temp->entry.Sym);
temp = temp -> pNext;
}
}
Now, I can't get the program to run properly. No run-time errors though but the output seems to be garbage. I've been working for hours for this and I cant' get my head around it. Thank you for your help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Elem
{
int AtNum;
char Na[31];
char Sym[4];
};
struct nodeTag
{
/* entry must be a pointer in order to not lose the values
and/or encounter memory conflicting errors
*/
struct Elem *entry;
struct nodeTag *pNext;
};
typedef struct nodeTag Node;
// insert node at the first location
Node *insertFirst(Node *head, struct Elem *data)
{
Node *node = (Node *) malloc(sizeof(Node));
// fill in data
node->entry = data;
/* point it to old first node
in simple words: "put this node before the head"
*/
node->pNext = head;
// point first to new first node
head = node;
return head;
}
Node *InitializeList(int n)
{
int i;
Node *head = NULL;
struct Elem *data;
for (i = 0; i < n; i++)
{
// allocate memory for the struct Elem of each node
data = (struct Elem*) malloc(sizeof(struct Elem));
scanf("%d", &data->AtNum);
scanf("%s", data->Na);
scanf("%s", data->Sym);
head = insertFirst(head, data);
}
return head;
}
//display the list
void printList(Node *head)
{
Node *ptr = head;
printf("\nStatus of the linked list is:\n");
//start from the beginning
while(ptr != NULL)
{
printf("%d %s %s", ptr->entry->AtNum, ptr->entry->Na, ptr->entry->Sym);
printf("\n");
ptr = ptr->pNext;
}
}
int main(int argc, char *argv[])
{
Node *head;
head = InitializeList(3);
printList(head);
return 0;
}
I hope I didn't come too late! If not, please check this answer as the solution, thanks! :-)
Is there any part i have missed in the code?
I am creating a non-empty linked
list and to display the contents of a linked list. Where am I getting it wrong?
#include <stdbool.h>
#include <stdlib.h>
struct node_int
{
void *data;
node next;
};
typedef struct node_int *node;
typedef struct list_int { node first; } *list;
void init_list(list *lp, void *o)
{
*lp = (list) malloc(sizeof(struct list_int));
(*lp)->first = NULL;
(*lp)->first->data = o;
(*lp)->first->next = NULL;
}
void print(list ell, void (*print_data)(void *d))
{
list c;
c = ell;
while (c!NULL)
{
print_data(c->data);
c = ell;
}
}
There are a few problems with your code.
First like to say that I find it bad style to typedef a pointer. If you do that, you should at least use a name which clearly tells that the type is a pointer. Names like list and node make others think of something which is not pointers.
Below is some code showing how it could look without typedef'ed pointers.
#include <stdio.h>
#include <stdlib.h>
struct node_int
{
void *data;
struct node_int* next;
};
typedef struct node_int node;
typedef struct list_int { node* first; } list;
void init_list(list** lp, void *o)
{
// Allocate the list
*lp = malloc(sizeof(list));
if (*lp == NULL) return;
// Allocate the first node
(*lp)->first = malloc(sizeof(node));
if ((*lp)->first == NULL)
{
free(*lp);
*lp = NULL;
return;
}
// Initialize first element
(*lp)->first->data = o;
(*lp)->first->next = NULL;
}
void print(list* ell, void (*print_data)(void *d))
{
if (ell == NULL) return;
node* p = ell->first;
while (p != NULL)
{
print_data(p->data);
p = p->next;
}
}
void myPrint(void* d)
{
int* p = (int*)d;
printf("%d\n", *p);
}
void free_list(list* ell)
{
// Add code here ...
}
int main(void)
{
int a = 1;
list* myList;
init_list(&myList, &a);
if (myList == NULL) return 0;
// Use the list.....
print(myList, myPrint);
free_list(myList);
return 0;
}
Suppose I got an external library bst that handles custom data types insertion in a bst
Here are the new_node,insert and search functions :
//new node
struct bst_node* new_node(void* data)
{
struct bst_node* result = malloc(sizeof(struct bst_node));
assert(result);
result->data = data;
result->left = result->right = NULL;
return result;
}
//insert node
void insert(struct bst_node** root, void* data) {
struct bst_node** node = search(root, data);
if (*node == NULL) {
*node = new_node(data);
}
}
//search node
struct bst_node** search(struct bst_node** root, void* data) {
struct bst_node** node = root;
while (*node != NULL) {
if (data, (*node)->data < 0)
node = &(*node)->left;
else if (compare_result > 0)
node = &(*node)->right;
else
break;
}
return node;
}
and the main.c ,suppose i read the models from a txt file :
#include <stdio.h>
#include <stdlib.h>
#include "bst.h"
#include <string.h>
#define MAX 50
typedef struct data_t{
int gg,mm,aaaa;
}data;
typedef struct accesories_t{
char name[MAX];
int price;
struct accesories_t *next;
}accesories;
typedef struct model_t{
//int index;
char name[MAX];
char file_a[MAX];
data date;
int price;
accesories *acs;
}model;
int main(int argc, char *argv[])
{
int menu=0;
char nf[MAX];
char name[MAX];
char fa[MAX];
int price,gg,mm,a;
strcpy(nf,argv[1]);
FILE *fp=fopen(nf,"+r");
model m;
struct bst_node* root = NULL;
while(fscanf(fp,"%s %d//%d//%d %d %s",name,gg,mm,a,price,fa)!=EOF){
strcpy(m.name,name);
strcpy(m.file_a,fa);
m.date.gg=gg;
m.date.mm=mm;
m.date.aaaa=a;
m.price=price;
m.index=index++;
insert(&root ,m);
}
system("PAUSE");
return 0;
}
So my question arises in the search function, how can i manage a comparator on custom data (let's say insert the models ordered by name (strcmp) ?
I'm very confused on how can i pass the names to the bst.c given that bst.c has no idea how my model struct is made.
Should I modify the bst library and maybe on bst struct add before data some sort of index and use that as comparator ?
OK I've managed to fix that by adding a string key inside the struct bst
What I'm trying to achieve now is to return the void* data type casted into struct model,
suppose _I got the tree with nodes containing the data, once I do a search I'd like to return for
example the data contained in a node and work on it, any clues ????
tried someting like without any success
suppose node is a returned node from a search function
model *m;
m=(model*)node->data;
how could I achieve this?
Example for using compare functions as callbacks. Definitions omitted for brevity.
int llist_cmp(struct llist *l, struct llist *r)
{
if (!l) return 1;
if (!r) return -1;
return strcmp(l->payload,r->payload);
}
struct llist * llist_split(struct llist **hnd, int (*cmp)(struct llist *l, struct llist *r) )
{
struct llist *this, *save, **tail;
for (save=NULL, tail = &save; this = *hnd; ) {
if (! this->next) break;
if ( cmp( this, this->next) <= 0) { hnd = &this->next; continue; }
*tail = this->next;
this->next = this->next->next;
tail = &(*tail)->next;
*tail = NULL;
}
return save;
}
struct llist * llist_merge(struct llist *one, struct llist *two, int (*cmp)(struct llist *l, struct llist *r) )
{
struct llist *result, **tail;
for (result=NULL, tail = &result; one && two; tail = &(*tail)->next ) {
if (cmp(one,two) <=0) { *tail = one; one=one->next; }
else { *tail = two; two=two->next; }
}
*tail = one ? one: two;
return result;
}
BTW: the above snippet handles linked lists, but the mechanism for passing function pointers is the same as with trees, of course. And after all it was homework ;-)