I'd like to add an element to a list of element. My list is a struct containing a double, an integer and a pointer to the next element. Could someone tell me how to do the Add function please
#include <stdio.h>
#include <stdlib.h>
typedef struct Liste Liste;
struct Liste{
double c;
int n;
Liste* next; // pointe sur l'élément suivant
};
void Add(Liste array, Liste item) {
Liste* last = array.next;
while (last != NULL) {
last = last->next;
}
array.next = &item;
printf("%p\n", array.next);
}
int main(){
Liste array = {12.4, 4, NULL};
printf("%f\n", array.c);
Liste item = {15.4, 7, NULL};
Add(array, item);
printf("%p\n", array.next);
return 0;
}
Pass-by-value
In Add, C makes a copy of all the function parameters; their scope is the function itself. When one returns, the function parameters are popped from the stack and there is no way to get them back, as you have seen. The way to mutate structures is to pass a pointer to the structure, then modify that pointer using the structure pointer dereference operator, (arrow ->.)
Design
The reason one would use a linked-list is it is very cheap to reorder it, but the head of your linked-list is fixed, so you can't change it. You might change this by delineating the container, the list itself, from the contents. This is similar to using a double-pointer, but I think less confusing.
struct Noeud {
double c;
int n;
struct Noeud* next; // pointe sur l'élément suivant
};
struct Liste {
struct Noeud *tete; // singly-linked-list est defini par un pointer seul
};
Then you can add, (I've included assert.h.)
/* `O(n)` */
static void AddQueue(struct Liste *liste, struct Noeud *item) {
assert(liste && item && item->next == NULL);
struct Noeud* last = liste->tete;
if(last == NULL) { // case spécieux
liste->tete = item;
} else {
while (last->next != NULL) {
last = last->next;
}
last->next = item;
}
}
However, it's much simpler and asymptotically faster to add at the beginning of the list.
Pointerstructures like a linked list are powerful tools with a wide rage of application.
But first you have to understand pointers.
A pointer is a datastructure which contains the address of a datastructure.
Whenever you call a function the arguments of it are copied (pushed) to the stack.
If the arguments require a lot of storage space you use a pointer instead.
the code below uses pointers to create a linked list
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"
typedef struct List List;
struct List{
double c;
int n;
List *next;
};
void AddItemEnd( List *RootItem, List *Item )
{
List *Last = RootItem;
while( Last->next != NULL )
{
Last = Last->next;
}
Last->next = Item;
}
void AddItemAtPos( List *RootItem, List *Item, unsigned int Pos )
{
if( Pos == 0 )
{
Item->next = RootItem;
}
else
{
List *TempItem = RootItem;
for( unsigned int i = 1; i < Pos && TempItem->next != NULL; ++i )
{
TempItem = TempItem->next;
}
Item->next = TempItem->next;
TempItem->next = Item;
}
}
void RemoveItemAtPos( List *RootItem, unsigned int Pos )
{
if( Pos == 0 )
{
free( (void*) RootItem );
}
else
{
List *TempItem = RootItem;
for( unsigned int i = 1; i < Pos && TempItem->next != NULL; ++i )
{
TempItem = TempItem->next;
}
if( TempItem->next == NULL )
{
return;
}else if( TempItem->next->next != NULL )
{
List *ItemToDelete = TempItem->next;
TempItem->next = TempItem->next->next;
free( (void*) ItemToDelete );
}else
{
free( (void*) TempItem->next );
TempItem->next =NULL;
}
}
}
int main(void) {
List *RootItem = malloc( sizeof( List ));
RootItem->c = 12.4;
RootItem->n = 4;
RootItem->next = NULL;
List *Item1 = malloc( sizeof(List ));
Item1->c = 15.4;
Item1->n = 7;
Item1->next = NULL ;
AddItemEnd( RootItem, Item1 );
List *IterationItem;
printf( "List created with AddItemEnd()\n\n" );
for( IterationItem = RootItem; IterationItem != NULL; IterationItem = IterationItem->next )
{
printf( "c: %lf\nn: %d\n\n", IterationItem->c, IterationItem->n );
}
List *item2 = malloc( sizeof( List ));
item2->c = 23.4;
item2->n = 1846;
item2->next = NULL ;
AddItemAtPos( RootItem, item2, 1 );
printf( "\n\nList extended with AddItemAtPos()\n\n");
for( IterationItem = RootItem; IterationItem != NULL; IterationItem = IterationItem->next )
{
printf( "c: %lf\nn: %d\n\n", IterationItem->c, IterationItem->n );
}
RemoveItemAtPos(RootItem, 1 );
printf( "\n\nList after RemoveItemAtPos()\n\n");
for( IterationItem = RootItem; IterationItem != NULL; IterationItem = IterationItem->next )
{
printf( "c: %lf\nn: %d\n\n", IterationItem->c, IterationItem->n );
}
free( (void*) RootItem );
free( (void*) item2 );
return 0;
}
The key elements when dealing with lists is pointers
and using memory allocation.
If we disregard your add function and just do a simple
example you will probably get the geist of it.
First allocate you starting list like this
Liste* array = malloc(sizeof(Liste));
Now you have one uninitialized block of memory
that array points to. You then need to initialize
it.
array->c = 12.4;
array->n = 4;
array->next = NULL;
in order to add a new entry to your list you
need to again allocate memory for the next node and
initialize it plus set the previous node next pointer
to point to it i.e. array->next.
Liste* item = malloc(sizeof(Liste));
item->c = 15.4;
item->n = 7;
item->next = NULL;
array->next = item;
now you have a list of two elements where array points
to the first
printing your short list
Liste* p = array;
while (p != NULL)
{
printf("%lf %d %p\n", p->c, p->n, p->next);
p = p->next;
}
So your Add functions does not allocate memory and copies
the parameters so that is not going to work.
Your Add function should have a pointer either to either the first or last item in your list e.g.
void Add(Liste* start, double c, int n)
Then you do as I showed you above and create a new node and assign the values
If you want to be able to pass an empty list to Add then you need to do differently, since start is copied it cannot be changed, you need to pass the address of the pointer
void Add(List** start, double c, int n)
{
Liste* node = malloc(sizeof(Liste));
...
(* put node in the list *)
if (*start == NULL)
{
*start = node; // first
}
else
{
(* find last node, see print loop *)
(* once you have last item, set it to point to node)
}
...
}
int main()
{
Liste* start = NULL;
Add(&start, 12.4, 4);
Add(&start, 15.4, 7);
...
Related
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node *tree_ptr;
typedef struct table * Table;
struct node
{
char* element;
tree_ptr left, right;
};
typedef struct table
{
tree_ptr head;
int tree_h;
}table;
char* key = NULL;
Table insert(char* insert_key,Table t)
{
int height = 0;
//tree_ptr ptr = t->head;
tree_ptr *ptr = &(t->head);
key = strdup(insert_key);
tree_ptr new_node = malloc(sizeof(struct node));
new_node->element = key;
new_node->left = NULL;
new_node->right = NULL;
if ( t->head==NULL ){
*ptr = new_node;
t->tree_h = 0;
printf("head:%s\n",t->head->element);
return t;
}
while(1){
if ( strcmp(insert_key, (*ptr)->element)<0 ){
if ( (*ptr)->left ==NULL ){
(*ptr)->left = new_node;
height++;
if ( height > t->tree_h)
t->tree_h = height;
break;
}
else{
(*ptr) = (*ptr)->left;
height++;
}
}
else if ( strcmp(insert_key, (*ptr)->element)>0 ){
if ( (*ptr)->right ==NULL ){
(*ptr)->right = new_node;
height++;
if ( height > t->tree_h)
t->tree_h = height;
break;
}
else{
(*ptr) = (*ptr)->right;
height++;
}
}
else break;
}
return t;
}
int main() {
Table t = malloc(sizeof(table));
t->head = NULL;
t = insert("one", t);
t = insert("two", t);
t = insert("three", t);
printf("%s\n",t->head->element);
return 0;
}
The above is a simplified program, some definition code is given, so I could not change the basic structure, like table, Table, node, tree_ptr, while others could be changed.
What I am trying to implement is a spellchecking, the table stored the head of the tree and some other properties of the tree(which is omitted here), the tree is implemented as an ordered binary tree.
I find that, insert() works well up to two times, after the (*ptr) = (*ptr)->right; the t->head is changed as well. So after using it two times, I lost the head of the tree.
How to modify my insert()?
To insert a node into a tree you first have to search for an empty leaf. Apart from this you do not modify t, so there is no need of writing it back by return value:
void insert( char* insert_key, Table t )
{
// serach empty leaf, where to insert the new node
tree_ptr *ptr = &(t->head); // start at head
while ( *ptr != NULL ) // end if empty leaf is found
{
int cmpRes = strcmp( insert_key, (*ptr)->element );
if ( cmpRes == 0 )
return; // insert_key already is member of tree
if ( cmpRes < 0 )
ptr = &((*ptr)->left); // step down to left child
else
ptr = &((*ptr)->right); // step down to right child
}
// create new node
tree_ptr new_node = malloc( sizeof(struct node) );
new_node->element = strdup( insert_key );
new_node->left = NULL;
new_node->right = NULL;
// place new node at empty leaf
*ptr = new_node;
}
With this recursive function you can print your tree:
void printTree( tree_ptr ptr )
{
if ( ptr == NULL )
return;
printTree( ptr->left );
printf( "%s\n", ptr->element );
printTree( ptr->right );
}
printTree( t->head );
And with this one you can free all nodes of your tree:
void deleteTree( tree_ptr ptr )
{
if ( ptr == NULL )
return;
deleteTree( ptr->left );
deleteTree( ptr->right );
free( ptr );
}
deleteTree( t->head );
t->head = NULL;
The problem is ptr is pointing to the address of the pointer to a struct node, instead of directly pointing to a struct node:
tree_ptr *ptr = &(t->head);
Then when iterating in the while loop, you aren't changing the pointer ptr, but the pointer it is pointing to, which is t->head:
(*ptr) = (*ptr)->left;
This overwrites the pointer, t->head on every iteration, effectively erasing the nodes that pointer pointed to, and leaking memory.
Instead use a normal pointer to the struct node:
struct node* iter = t->head;
...
if ( strcmp(insert_key, iter->element)<0 ){
...
}
else{
iter = iter->left;
....
And I would highly suggest removing those typedefs that hide the pointer, because they make the code hard to read and obfuscate the types, which is not desirable in this context:
typedef struct node *tree_ptr;
typedef struct table * Table;
Also note that if the loop finds a duplicate, the allocated node is not freed, leaking the memory.
Here's the code , i run it with one example it works , but when it comes
to comparing i do not understand what's wrong ? , thanks in advance for
any help .I need to print dictionary texts properly (inserting , printing) , can not still come up with a solution , i mean using dictionary data structure like .
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
typedef struct Node_s {
char *element;
struct Node_s *left, *right;
} Node;
typedef struct {
Node *head;
} Table;
//Table *initialize();
//Node *createNode(const char *element);
Table *initialize() {
Table *tb = malloc(sizeof(Table)*1000);
tb->head = NULL;
return tb;
}
Node *createNode( char * element ) {
Node *temp = malloc(sizeof(temp));
temp->element = element ;
temp->left = temp->right = NULL;
return temp;
}
void insert(Table *temp, char *element) {
Node *nd = createNode(element);
Table * place = NULL;
Node *new = NULL;
int cmp = 0;
if(temp->head == NULL) {
temp->head= nd;
printf("empty ! \n");
return;
}
else {
Table *current = temp;
while (current!=NULL) {
cmp = strcmp(current->head->element,element);
if(cmp < 0) {
current->head= current->head->left;
}
else if(cmp > 0) {
current->head = current->head->right;
}
} //while
place = current;
new = nd;
if(cmp > 0 ) {
place->head->right = new ;
}
else if(cmp <0 ) {
place->head->left = new;
}
}
}
void print_table(Table *temp) {
if(temp!=NULL || !temp->head) return;
print_table(temp->head->left);
printf("%s \n",temp->head->element);
print_table(temp->head->right);
}
int main () {
Node * nd = NULL;
//nd->element = "key";
// nd = createNode("key");
Table *tb = initialize();
//tb->head = createNode("key");
//tb->head = createNode("key");
insert(tb, "table element1");
insert(tb, "table element2");
insert(tb, "table element2");
//nd = createNode("key1");
// print_table(t);
//printf("%s \n",nd->element);
print_table(tb);
// printf("%s \n",tb->head->element);
free(nd);
return 0;
}
There are a lot of potential bugs here, but your primary issue is in the following line of createNode:
Node *temp = malloc(sizeof(temp));
Here you're doing a sizeof(temp) and temp is a pointer. This means that you are only allocating enough memory for a pointer (usually 8 bytes). You are hence writing outside of allocating memory when using the left/right members of the heap allocated structure. The fix:
Node *temp = malloc(sizeof(Node));
// EXTRA: I also recommend that you verify that the allocation was successful
if (temp) {
temp->element = element ;
temp->left = temp->right = NULL;
}
return temp;
In printTable, you should also verify that temp itself isn't NULL as you are passing the function parameters that might be NULL:
if(!temp || !temp->head) return;
Also, remove the free(nd); at the end of main, as calling free() on unallocated heap memory corrupts the heap and typically leads to a segfault.
Your printing method crashes when reaching the last node on the left because it will call print_table(NULL) since there's nothing more on the left. After that when it executes the line
if(!temp->head) return;
You get a memory access violation because temp is NULL, you should also check if temp itself is NULL.
if( !temp || !temp->head ) return;
That should fix your problem.
One issue right away is on your second call to insert:
while (current != NULL) {
cmp = strcmp(current->head->element, element); // this line
You didn't check if current->head is NULL itself. According to what you've implemented, you use head as a sentinel, thus it can be NULL. However, your search loop totally forgot about this condition and assumes that head is never NULL.
Your loop doesn't seem fundamentally correct. You traverse the left, so what is supposed to happen if the left branch "runs out" (as it does now when you call insert the second time)?
In addition, your insert function has a memory leak. You potentially allocate 2 new nodes here:
Node *nd = createNode(element);
and here:
new = createNode(element);
Only one is stored while the other is leaked.
Another issue is that your tree does nothing in the while loop if the two items are equal. Two equal items results in an infinite loop:
while (current!=NULL)
{
cmp = strcmp(current->head->element,element);
if(cmp < 0)
current->head= current->head->left;
else if(cmp > 0)
current->head = current->head->right;
else
printf("these are equal ! \n"); // but we don't do anything with current!
}
If the goal is to not have duplicates, then you should exit this function if a duplicate is found. If the goal is to store duplicates, only test for < 0, anything else, goes on the right branch.
This might be what you are looking for.
It handles a doubly linked list
error checking is added
removed undesirable/unnecessary typedef's from struct definitions
corrected the logic to link in new nodes
avoided recursion in the printing of the linked list
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
struct Node
{
char *element;
struct Node *left;
struct Node *right;
};
// define the head pointer for the linked list
struct Node *head = NULL;
// struct Node *createNode(const char *element);
struct Node *createNode( char * element )
{
struct Node *pNewNode = NULL;
if( NULL == (pNewNode = malloc(sizeof(struct Node)) ) )
{ // then, malloc failed
perror( "malloc for new node failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
pNewNode->element = element ; // copies a char pointer
pNewNode->left = NULL;
pNewNode->right = NULL;
return pNewNode;
} // end function: createNode
void insert(char *element)
{
int cmp = 0;
// get ptr to first node in list
struct Node *pCurrentNode = head;
// create the node to be inserted into linked list
struct Node *pNewNode = createNode(element);
if (pCurrentNode == NULL)
{ // then list empty
head = pNewNode;
printf("added first node\n");
return;
}
// implied else, not first node
while (pCurrentNode->right)
{
cmp = strcmp(pCurrentNode->element,element);
if(cmp < 0)
{
// insert new node before current node
pNewNode->right = pCurrentNode;
pNewNode->left = pCurrentNode->left;
pCurrentNode->left = pNewNode;
(pNewNode->left)->right = pNewNode;
}
else if(cmp > 0)
{
// step to next node
pCurrentNode = pCurrentNode->right;
} // end if
// note: if data same, don't insert new node
} //while
if( pCurrentNode->right == NULL )
{ // then, reached end of list
// append new node to end of list
pNewNode->left = pCurrentNode;
pNewNode->right = NULL;
pCurrentNode->right = pNewNode;
} // end if
} // end function: insert
void print_table()
{
struct Node *pCurrentNode = head;
if( pCurrentNode == NULL ) return;
// implied else, list not empty
while( pCurrentNode )
{
printf("%s \n",pCurrentNode->element);
pCurrentNode = pCurrentNode->right;
} // end while
} // end function: print_table
void cleanup()
{
struct Node *pCurrentNode = head;
while( pCurrentNode )
{
pCurrentNode = pCurrentNode->right;
free( pCurrentNode->left );
}
} // end function: cleanup
int main ()
{
// exercise the insert function
insert("table element1"); // append first element
insert("table element2"); // append second element
insert("table element4"); // append third element
insert("table element3"); // insert forth element
insert("table element3"); // duplicate within list
insert("table element4"); // duplicate at end of list
print_table();
cleanup();
return 0;
} // end function: main
I tried a different implementation, it compiles and works, it does not allow duplicates.
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#define ELEMENT_SIZE 1024
typedef struct Node_s
{
char element[ELEMENT_SIZE];
struct Node_s *left, *right;
} Node;
Node * createNode(char *element)
{
Node *node = malloc(sizeof(Node));
node->left = NULL;
node->right = NULL;
memcpy(node->element, element, ELEMENT_SIZE);
return node;
}
void free_node(Node *node)
{
if(!node)
return;
free_node(node->left);
free_node(node->right);
free(node);
}
Node * insert(Node **head_ptr, char *element)
{
Node *head = *head_ptr;
if(head == NULL){
Node *node = createNode(element);
head = node;
*head_ptr = node;
return node;
}else{
int comp = strcmp(head->element, element);
if(comp < 0){
// go left
if(head->left == NULL){
// set element to be temp left
Node *node = createNode(element);
head->left = node;
return node;
}else{
return insert(&head->left, element);
}
}else if(comp > 0){
// go right
if(head->right == NULL){
// set element to be temp left
Node *node = createNode(element);
head->right = node;
return node;
}else{
return insert(&head->right, element);
}
}else{
// element exists
printf("Element \"%s\" already exists\n", element);
return NULL;
}
}
}
void print_table(Node *temp)
{
if(!temp)
return;
printf("%s \n",temp->element);
print_table(temp->left);
print_table(temp->right);
}
int main ()
{
Node *nd = NULL;
printf("Address of nd is %p\n", &nd);
Node *n1 = insert(&nd, "table element 1");
n1 = insert(&nd, "table element 2");
n1 = insert(&nd, "table element 3");
n1 = insert(&nd, "element 1");
n1 = insert(&nd, "element 2");
n1 = insert(&nd, "element 3");
n1 = insert(&nd, "alternative 1");
n1 = insert(&nd, "alternative 2");
n1 = insert(&nd, "alternative 3");
n1 = insert(&nd, "alternative 1");
n1 = insert(&nd, "alternative 2");
n1 = insert(&nd, "alternative 3");
print_table(nd);
free_node(nd);
return 0;
}
I am trying to delete all the nodes on a linked list but I am getting a segmentation fault.
I had code that was working initially but I was only deleting the first node in the list, I want to delete all the nodes and delete all the pointers redundant pointers.
Also if some of you guys could check the function I am using to create the linked list and give me some feedback on whether you think it is ok or where some improvements could be made, I would appreciate it.
Thanks.
Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MEMORY_SIZE (15)
typedef struct link {
double coeff;
int pow;
struct link * next;
} poly;
poly *polyArray[MEMORY_SIZE];// array of 15 polynomials to play with
// /** The function prototypes */
void createPoly(poly **);
void deletePoly(poly *);
/**
* The main function
*/
int main(void) {
printf("\n\n\t***************************************************");
/* printf("\n\tDemonstrating Polynomial Creation");
printf("\n\t***************************************************");*/
printf("\n\t1st polynomial\t");
createPoly(&polyArray[0]);
showPoly(polyArray[0]);
srand(time(NULL));
// printf("\n\n\tCreating and storing the 2nd polynomial\n");
// createPoly(&polyArray[1]);
// showPoly(polyArray[1]);
showPoly(polyArray[0]);
printf("\n\t***************************************************");
printf("\n\tProgram has Ended, Deleting all polynomials");
printf("\n\t***************************************************");
int count;
for(count = 0; count < MEMORY_SIZE; count++)
{
deletePoly(polyArray[count]);
}
printf("\n\n");
showPoly(polyArray[0]);
return 0;
}//end main function
//////////////////////////////////////////////////////////////////////////////////////
void createPoly(poly **node) {
poly *tempnode; //To hold the temporary last address
tempnode = (poly*)malloc( sizeof(poly) ); //create the first node
*node = tempnode; //Store the head address to the reference variable
int flag = 1 + rand()%3;; // A flag to control the number of terms
int counter;
for( counter = 0; counter <= flag; counter++ )
{
tempnode->pow = ( flag-counter );
tempnode->coeff = ( (double)(rand()%20) )/( (double)(1 + rand()%20) );
if( (counter < flag) && (counter >= 0) )
{
tempnode->next = (poly*)malloc( sizeof(poly) ); //Grow the list
}
else if ( counter == flag )
{
tempnode->next = NULL;
}
tempnode = tempnode->next;
}
}
void deletePoly(poly *node) {
poly *temp;
if( node->next == NULL )
{
free( node );
node = NULL;
}
else
{
while( node->next != NULL )
{
temp = node->next;
free( node );
node = temp;
}//end while
node = NULL;
}//end 'if/else'
}//end function 'deletePoly'
As I understand it, the main function is creating only the first polynomial (poly[0]), but you are trying to delete them all (the loop in the main function goes up to MEMORY_SIZE).
You should also initialize all your pointers to NULL before beginning the program (this is an important feature in C programs) and change the deletePoly this way:
void deletePoly(poly *node) {
poly *temp;
while( node != NULL ) {
temp = node->next;
free( node );
node = temp;
}//end while
node = NULL;
}//end function 'deletePoly'
I would like some professional advice for making a char *x array of strings (of const char names with different sizes) Would someone help with mallocing a list to fit the size of a structure name ( qSep->front->name))
Attempt 1: Well my base case works, so I started making multiple print statements. The first one doesn't get put in. My gdb causes error at printf("Found in List %s has name\n", x[0]);
Code and then data structures below.
size_t separation( const User *user1, const User *user2 ) {
int len= 0;
char *x;
//use contains
queueSep *qSep =(struct queueSep*) malloc(sizeof(struct queueSep));
int count = 0;
//pre-condition: the user is not the same as user2
if ( user1->name == user2->name ) { //str compare
return 0;
}
qSep->front = convert(user1, NULL, count);
printf("Conversion complete for %s \n",qSep->front->name);
len++;
x = malloc(len*sizeof((const char*)qSep->front->name));
x[len-1] = qSep->front->name;
printf("Found in List %s has name\n", x[0]);
while( qSep->front != NULL) {
//check if front of the queue is the finish USER
if ( (const char*)qSep->front->name == user2->name ) {
return qSep->front->separationCount;
} else { //add all the neighbours on the queue with separation size incremented
struct node *currAmigo = qSep->front->sepAmigos->amigos_Queue->front;
if ( currAmigo == NULL ) {
//is that a bad thing?
}
while ( currAmigo != NULL ) {
for(int i = 0; i < len; ++i) {
printf("List amigo for %s has name %s\n", currAmigo->data->name, x[i]);
/*
//if(strcmp(x[i], currAmigo->data->name))
{
goto end_nested_loop;
}
*/
}
//make a qSep node
struct sepNode *node = convert(currAmigo->data, NULL, count+1);
len++;
x = realloc(x, len*sizeof(int));
x[len-1] = currAmigo->data->name;
//insert the sepNode into the end of the queue
que_insSepqueue(qSep, node);
//go to Next Amigo in top of Queue
currAmigo=currAmigo->next;
}
end_nested_loop:
count++;
//remove the node
que_deqSep( qSep );
}
}
return -1;
}
Converted Struct
typedef struct sepNode {
const char *name;
struct Friends_struct *sepAmigos;
size_t *separationCount;
struct sepNode *sepNodeNext;
}sepNode;
typedef struct queueSep{
struct sepNode *front; //front of queue
}queueSep;
//How to make a list
typedef struct User_struct {
const char *name;
Friends amigos;
} User;
EXTRA ( to convert a node to say separation length)
sepNode *convert( const User *user1, const User *user2, int count) {
sepNode *sepNode1=
sepNode1 = (struct sepNode*) malloc(sizeof(struct sepNode));
sepNode1->name = user1->name;
sepNode1->sepAmigos = user1->amigos;
sepNode1->separationCount = count;
sepNode1->sepNodeNext = NULL;
return sepNode1;
}
Using a pointer list
char *x;
You have indexes that need to be malloc instead of
x = malloc(len*sizeof((const char*)qSep->front->name));
x[len-1] = qSep->front->name;
Malloc the size of the first index with
x[len-1] = malloc(sizeof(char)*sizeof(qSep->front->name)); //redundant sizeof(char) =1
//just to illustrate
x[len-1] = qSep->front->name;
Also, if anyone knows if I can just free(x); in one line, that would be helpful in a comment.
Write a function that rearranges a linked list to put the nodes in even positions after the nodes in odd positions in the list, preserving the relative order of both the evens and the odds.
I found this problem in the book Algorithm in c writtern by Sedgewick. I have tried but failed. I trid to put all nodes in even positions on another linked list. It's grateful for you to help me. A good idea is enough. Thanks :).
This is my Code in C.
/*
* File: rearranges.c <Exercise 3.36>
* Note: Write a function that rearranges a linked list to put the nodes in even
* positions after the nodes in odd positions in the list, preserving the
* relative order of both the evens and the odds.
* NOTICE: I think it's necessary to use linked list with a dummy head.
* Time: 2013-10-26 10:58
*/
#include <stdio.h>
#include <stdlib.h>
#define LEN 11
typedef struct node *link;
struct node {
int item;
link next;
};
/* Traverse a linked list with a dummy head. */
void traverse(link t) {
link x = t->next;
while (x != NULL) {
printf("%d ", x->item);
x = x->next;
}
putchar('\n');
}
/* Detach even positon nodes from a linked list. */
link detach(link t) {
link u = malloc(sizeof(*u));
link x = t, y = u;
/* x is odd position node. We should ensure that there's still one even
* position node after x. */
while (x != NULL && x->next != NULL) {
y->next = x->next;
x->next = x->next->next;
x = x->next;
y = y->next;
y->next = NULL;
}
return u;
}
/* Combine two linked list */
link combine(link u, link t) {
link x = u;
link y = t->next;
while (y != NULL) {
link n = y->next;
y->next = x->next;
x->next = y;
x = x->next->next;
y = n;
}
return u;
}
/* The function exchanges the position of the nodes in the list. */
link rearranges(link t) {
link u = detach(t);
link v = combine(u, t);
return v;
}
int main(int argc, char *argv[]) {
int i;
link t = malloc(sizeof(*t));
link x = t;
for (i = 0; i < LEN; i++) {
x->next = malloc(sizeof(*x));
x = x->next;
x->item = i;
x->next = NULL;
}
traverse(t);
traverse(rearranges(t));
return 0;
}
curr=head;
end=lastOfList;//last node if size of list is odd or last-1 node
for(int i=1;i<=listSize()/2;i++)
{
end->next=curr->next;
end=end->next;
end->next=null;
if(curr->next!=null)
if((curr->next)->next!=null)
curr->next=(curr->next)->next;
curr=curr->next;
}
You can implement a recursive solution where each call returns an updated node that will serve as the new next reference for the upper caller. We just have to go down the list until we find the last element, and then move every even node to the end of the list, and update the reference to the last element. Here's my solution (please try to do it yourself before looking at my and other solutions):
struct node {
int val;
struct node *next;
};
struct node *reorder_aux(struct node *l, int count, struct node **last);
struct node *reorder(struct node *l) {
struct node *x;
if (l == NULL)
return NULL;
return reorder_aux(l, 1, &x);
}
struct node *reorder_aux(struct node *l, int count, struct node **last) {
struct node *n;
if (l->next == NULL) {
*last = l;
return l;
}
n = reorder_aux(l->next, count+1, last);
if (count & 1) {
l->next = n;
return l;
}
else {
(*last)->next = l;
l->next = NULL;
*last = l;
return n;
}
}
At each step, if the current node l is an even node (as determined by count), then we append this node to the end, and tell the upper caller that its next pointer shall be updated to our next (because our next will be an odd node). In case we're an odd node, we just have to update our next pointer to whatever the recursive call returned (which will be a pointer to an odd node), and return the current node, since we will not move ourselves to the end of the list.
It's a nice exercise!
#include <stdio.h>
struct list {
struct list *next;
int ch;
};
void swap_odd_even (struct list **pp)
{
struct list *one, *two ;
for( ; (one = *pp) ; pp = &one->next) {
two = one->next;
if (!two) break;
*pp = two;
one->next = two->next;
two->next = one;
}
}
struct list arr[] =
{ {arr+1, 'A'} , {arr+2, 'B'} , {arr+3, 'C'} , {arr+4, 'D'}
, {arr+5, 'E'} , {arr+6, 'F'} , {arr+7, 'G'} , {arr+8, 'H'}
, {arr+9, 'I'} , {arr+10, 'J'} , {arr+11, 'K'} , {arr+12, 'L'}
, {arr+13, 'M'} , {arr+14, 'N'}, {arr+15, 'O'} , {arr+16, 'P'}
, {arr+17, 'Q'} , {arr+18, 'R'} , {arr+19, 'S'} , {arr+20, 'T'}
, {arr+21, 'U'} , {arr+22, 'V'}, {arr+23, 'W'} , {arr+24, 'X'}
, {arr+25, 'Y'} , {NULL, 'Z'} };
int main (void) {
struct list *root , *ptr;
root = arr;
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
printf( "Swap\n" );
swap_odd_even ( &root);
for (ptr=root ; ptr; ptr = ptr->next ) {
printf( "-> %c" , ptr->ch );
}
printf( "\n" );
return 0;
}
In the following, every time swap_nodes is called another odd sinks to the last sunk odd. The evens are grouped together on each iteration and they bubble up to the end of the list. Here is an example:
/*
[0]-1-2-3-4-5
1-[0-2]-3-4-5
1-3-[0-2-4]-5
1-3-5-[0-2-4]
*/
#include <stdio.h>
#include <stdlib.h>
#define LIST_LENGTH 10
struct node{
int id;
struct node *next;
};
void print_list(struct node *current)
{
while(NULL != current){
printf("node id = %d\n",current->id);
current = current->next;
}
printf("Done\n");
}
struct node *swap_nodes(struct node *head_even, struct node *tail_even, struct node *next_odd)
{
tail_even->next = next_odd->next;
next_odd->next = head_even;
return next_odd;
}
struct node *reorder_list(struct node *head)
{
struct node *head_even;
struct node *tail_even;
struct node *next_odd;
struct node *last_odd;
if(NULL == head->next){
return head;
}
head_even = head;
tail_even = head;
next_odd = head->next;
last_odd = head->next;
head = swap_nodes(head_even, tail_even, next_odd);
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
while (NULL != tail_even->next) {
next_odd = tail_even->next;
last_odd->next = swap_nodes(head_even, tail_even, next_odd);
last_odd = last_odd->next;
if(NULL != tail_even->next){
tail_even = tail_even->next;
}
}
return head;
}
int main(void)
{
int i;
struct node *head = (struct node *) malloc(LIST_LENGTH*sizeof(struct node));
struct node *mem = head;
if(NULL == head){
return -1;
}
struct node *current = head;
for(i=0;i<LIST_LENGTH-1;i++){
current->next = current + 1;
current->id = i;
current = current->next;
}
current->next = NULL;
current->id = i;
head = reorder_list(head);
print_list(head);
free(mem);
return 0;
}