c语言围圈报数链表,使用循环链表实现约瑟夫环(围圈报数问题)(示例代码)

刚开始学C,碰到经典的围圈报数问题,现先将实现代码附下:

#include

#include

struct LNODE{            //链表定义

int data;

struct LNODE *next;

};

typedef struct LNODE Lnode;

typedef struct LNODE *LinkList;

struct LNODE *create(int s[])      //创建单项循环链表

{

struct LNODE *head=NULL,*p=NULL,*last=NULL;

int i=0;

head=(struct LNODE *)malloc(sizeof(struct LNODE));

if(!head)

printf("memory allocation error!");

if(s[0]!=0)

{

head->data=s[0];

head->next=head;

last=head;

i++;

while(s[i]!=0)      //判断是否为0,为0则结束

{

p=(struct LNODE*)malloc(sizeof(struct LNODE));

last->next=p;

p->data=s[i];

p->next=head;

last=p;

i++;

}

}

return head;

}

void printlist(struct LNODE *head)    //打印循环链表

{

struct LNODE *q;

int i;

printf("the linked list is :\n");

if(!head)

printf("NULL");

else

{

q=head;

do

{

printf("%d\t",q->data);

q=q->next;

}while(q!=head);

}

printf("\n");

}

int main()

{

int  circlelist[100],n,i,k=1;

printf("please input the number:");

scanf("%d",&n);      //输入人数

getchar();

for(i=0;i

circlelist[i]=i+1;      //给每个人编号

circlelist[i]=0;        //最后值赋0

for(i=0;i<=n;i++)

printf("%d\t",circlelist[i]);    //打印编号

LinkList p=NULL,q=NULL;

p=create(circlelist);

printlist(p);          //打印编号链表

while(p->data!=p->next->data)    //自身与自身相等时退出循环

{

if(k!=3)                //设置报到数3的人退出

{

k++;

q=p;

p=p->next;

}

else

{

k=1;

printf("%d\t",p->data);      //打印先后推出的人员编号

q->next=p->next;        //删除报3的人员结点

p=q->next;

}

}

printf("\n%d\n",p->data);

}

刚开始指针定义时都没有赋值为NULL,调试没错误,可是却无法执行。

书中说,建议定义时如果暂时不使用指针,先赋值为NULL,我觉得最好这样做,而且,在使用指针时,都应该判断一下是否为空。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我了解了您的问题约瑟夫环问题可以使用循环链表来解决。具体做法如下: 1. 首先,定义一个链表结构体,其中包含一个成员用于存储该结点的值,以及两个指针,分别指向下一个结点和前一个结点。 2. 创建一个循环链表,并按照顺序插入 n 个结点。 3. 定义一个指针,指向循环链表的头结点,然后开始从第 k 个结点开始依次遍历链表,每遍历一次,将指针向后移动 k 个位置,直到只剩下一个结点为止。 4. 在循环过程中将每个被遍历到的结点从链表中删除。 5. 最后剩下的那个结点就是幸存者。 以下是使用 C 语言实现代码: ``` #include<stdio.h> #include<stdlib.h> // 定义链表结构体 typedef struct node { int value; // 存储该结点的值 struct node* prev; // 指向前一个结点的指针 struct node* next; // 指向下一个结点的指针 } Node; int main() { int n, k; printf("请输入总人数n和数到k出圈的人数:\n"); scanf("%d%d", &n, &k); // 创建循环链表并插入n个结点 Node *head = (Node *)malloc(sizeof(Node)); head->value = 1; head->prev = NULL; head->next = NULL; Node *p = head; for(int i=2; i<=n; i++) { Node *temp = (Node *)malloc(sizeof(Node)); temp->value = i; temp->prev = p; p->next = temp; p = p->next; } p->next = head; head->prev = p; // 指向第k个结点 p = head; for(int i=1; i<k; i++) { p = p->next; } while(head->next != head) { // 指向第k个结点 for(int i=1; i<k; i++) { p = p->next; } // 删除该结点 p->prev->next = p->next; p->next->prev = p->prev; Node *temp = p; p = p->next; free(temp); } printf("幸存者是第%d号人\n", head->value); free(head); return 0; } ``` 希望我的回答能对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值