Reputation: 55
I am working on the program which solves Josephus problem on C. I have to use circular linked lists here. Currently I have this code to create list:
void create_list(int N, struct node* head){
int i, j, k;
for(i = 2; i <= N; i++){
struct node* tmp_node = (struct node*)malloc(sizeof(struct node));
tmp_node -> number = i;
tmp_node -> next = NULL;
tmp_node -> next = head -> next;
head -> next = tmp_node;
head = tmp_node;
}
}
Now I am working on finding last element to remin after Josephus permutations. I have this:
int find_last(int M, struct node* head){
int i, j = 1;
if(head -> next == NULL){
return head -> number;
}
else {
struct node* current = head;
while(current -> next != NULL){
while(current -> next -> number != j){
current = current -> next;
j++;
}
if (j % M == 0){
struct node* delete_node;
delete_node = current -> next;
current -> next = delete_node -> next;
free(delete_node);
j = 1;
}
}
return current -> number;
}
}
And this is my main:
int main(){
int M, N, i, j, res;
struct node* head = (struct node*)malloc(sizeof(struct node));
head -> number = 1;
head -> next = NULL;
read_numbers(&N, &M);
create_list(N, head);
res = find_last(M, head);
printf("%d\n", res);
return 0;
}
The problem occurs in int find_last function. Please, tell me the errors and what I can do to solve the problem, thanks for your time.
EDIT.
I have drawn the algorithm and updated my function but it still doesn't work. Here it is:
int find_last(int M, int N, struct node* head){
int i = 0, j = 1;
if(head -> next == NULL){
return head -> number;
}
else {
struct node* current = head;
while(i != N){
while(j % M != 0){
current = current -> next;
j++;
}
struct node* delete;
delete = current -> next;
delete -> next = current -> next;
free(delete);
i++;
}
return current -> number;
}
}
Upvotes: 0
Views: 119
Reputation: 8344
create_list()
does NOT create a circular LL. You'll have to examine the code to see your own mistake there. The shortest explanation would take longer to relate than merely fixing the code.
Shorter (working!) code to study:
typedef struct n { // typedef reduces verbiage
int no; // simple, short and sweet name for variables
struct n *next;
} node;
node *create( int N ) { // simple function name
node *pHead = NULL, *pTail = NULL; // track head & tail of LL
for( int i = 1; i <= N; i++ ) { // make N nodes
node *pn = malloc( sizeof *pn ); // no casting, and sizeof tied to variable, not type
// Omitting verification for brevity
pn->no = i; // assign the value
if( !pTail )
pHead = pTail = pn; // first node
else
pTail = pTail->next = pn; // linking onto end
}
return pTail->next = pHead; // May the circle be unbroken!!
}
int killOff( int M, node *pn ) { // NB: function name tells all
while( pn->next != pn ) { // until only "self" remains
for( int i = M; --i; ) pn = pn->next; // skip M nodes around circle
node *del = pn->next;
pn->next = del->next; // dead man walking in exile now
free( del ); // bye bye
}
return pn->no; // survivors ID
}
int main( void ) {
int M = 3, N = 17; // constants
node *head = create( N ); // simple, right?
printf( "Survivor: %d\n", killOff( M, head ) ); // simpler, too!
free( head ); // kill off the last of them
return 0; // and good night
}
You can get yourself tied up in knots with verbiage and without planning.
Caveat: M
down count may be off-by-one. Change --i
to i--
to suit your interpretation of how far to travel around the shrinking ring of nodes.
EDIT
After closer examination, I believe the following is a better version. (No changes to create()
shown above.)
int killOff( int M, node *pn ) {
// the previous "victim" is #0 at the start of each iteration
// So, the first iteration begins with 1; subsequent iterations with 0
for( int i = 1; pn->next != pn; i = 0 ) {
while( ++i < M ) pn = pn->next;
node *del = pn->next;
pn->next = pn->next->next;
free( del );
}
int survivorID = pn->no;
free( pn ); // Last "survivor" is free'd here, remembered only by "name."
return survivorID;
}
int main( void ) {
printf( "Survivor: %d\n", killOff( 3, create( 17 ) ) );
return 0;
}
Upvotes: 2