偶然想到约瑟夫环的问题,就试着编写代码实现一下。
首先介绍一下约瑟夫环的问题。
这个就是约瑟夫环问题的实际场景,有一种是要通过输入n,m,k三个正整数,来求出列的序列。这个问题采用的是典型的循环链表的数据结构,就是将一个链表的尾元素指针指向队首元素。pL->pTail->next=pL->head
解决问题的核心步骤:(程序的基本算法)
⒈建立一个具有n个链结点,无头结点的循环链表;
⒉确定第1个报数人的位置;
⒊不断地从链表中删除链结点,直到链表为空。
约瑟夫环链表方法的C语言实现:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node* next;
}node;
typedef struct LinkList
{
struct Node* pHead;
struct Node* pTail;
}Linklist;
//初始化一个循环链表
struct LinkList* init_linklist()
{
struct LinkList* p = (struct LinkList*)malloc(sizeof(struct LinkList));
p->pTail = p->pHead =NULL;
return p;
}
void insert_linklist(struct LinkList** pL,int data )
{
struct LinkList* pl = *pL;
struct Node* pN;
pN = (struct Node*)malloc(sizeof(struct Node));
if(!pN)
{
printf("申请空间失败!\n");
return;
}
if(pl->pHead ==NULL&& pl->pTail ==NULL)
{
pl->pHead = pN;
pl->pTail =pN;
pl->pHead->next = pl->pTail;
pl->pHead->data =data;
}
else
{
pN->data =data;
pN->next =pl->pHead;
pl->pTail->next = pN;
pl->pTail = pN;
}
}
void delete_node(struct LinkList** pL,struct Node** pN)
{
struct LinkList* pl = *pL;
struct Node* pn;
pn =pl->pHead;
if(pl->pHead!=pl->pTail)
{
while(pn->next!=(*pN))
pn = pn->next;
printf("pN->data = %d\n",(*pN)->data );//输出删除的结点数据
pn->next = (*pN)->next;
if(*pN ==pl->pTail) //如果是循环的尾
pl->pTail = pn;
else if(*pN == pl->pHead)//如果是循环的头
pl->pHead = pn->next;
free(*pN);
*pN =pn->next;//指向下一个结点;
}
else
{
printf("pN->data = %d\n",(*pN)->data);
free(*pN);
pl->pHead =NULL;
pl->pTail =NULL;
*pN =NULL;
}
}
void show_linklist(struct LinkList** pL)
{
struct LinkList* pl = *pL;
struct Node* pn;
pn = pl->pHead;
if(pn!=NULL)
{
printf("所有的数据如下:");
printf("\n%d\t",pn->data );
pn = pn->next;
while(pn!=pl->pHead)//输出剩余的数据
{
printf("%d\t",pn->data );
pn= pn->next;
}
printf("\n");
}
else
{
printf("\n约瑟夫环中没有数据了\n");
return;
}
}
int main()
{
struct LinkList* pl =init_linklist();//初始化循环链表
int n,k,m;//nums表示数据个数,k表示从当前位置开始
struct Node* pn;
printf("请依次输入n、m和k的值,n代表元素的个数,m表示从第几个元素开始报数,k代表每次前进的步数! \n");
scanf("%d%d%d",&n,&m,&k);
for(int i =1;i <= n; i ++ )
insert_linklist(&pl,i);//插入数据
//显示循环链表中的数据
show_linklist(&pl);
pn = pl->pHead;
//从第m个开始报数
for(i = 1; i< m;i++)
pn= pn->next;
while(pn!=NULL)
{
for(i =1;i< k; i++)
pn = pn->next;
delete_node(&pl,&pn);
}
show_linklist(&pl);
free(pl);//释放申请的内存空间
return 0;
}
vc++6.0上面编译运行,输入一个实例,结果如下: