您的位置:首页 > 其它

约瑟夫环问题的解决

2015-06-12 20:37 204 查看
约瑟夫环问题介绍:

已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为1的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
typedef int DataTp;

typedef struct node
{
DataTp elem;
struct node*pnext;

}NODE;

typedef NODE* LinkList;

NODE* CreatList(int n);
void MakeLoop(LinkList phead);
void DeleteNode(LinkList phead,LinkList paim);

int main (void)
{
int sum,num;  //总人数 , 退出人的编号
int i;

LinkList pstart;  //头节点
LinkList paim;    //待删除的目标节点的地址
LinkList pt;

puts("输入总人数");
scanf("%d",&sum);
puts("输入退出的编号");
scanf("%d",&num);

pstart=CreatList(sum);  //建立链表
MakeLoop(pstart);       //变为循环链表

pt=pstart->pnext; //取出第一个数据节点地址

while(sum!=0)
{

for(i=0;i<num-1;i++)
pt=pt->pnext;      //往后寻址,找到退出目标的地址

paim=pt;              //临时保存。确定删除节点的地址
pt=pt->pnext;         //确定下次循环的头为pt

printf("退出的是%d号\n",paim->elem);
DeleteNode(pstart,paim);         //删除

sum--;                          //总人数减少

}

return 0;
}

NODE* CreatList(int n)
{
int i;
NODE*p1,*p2;

NODE * phead;

phead=(NODE*)malloc(sizeof(NODE));
if(phead==NULL)
{
fputs("memory error!\n",stderr);
exit(EXIT_FAILURE);

}

phead->pnext=NULL;

/////////////////////////////////
for(i=0;i<n;i++)
{
p1=(NODE*)malloc(sizeof(NODE)); //分配内存
if(p1==NULL)                    //检查合法性
{
fputs("memory error!\n",stderr);
exit(EXIT_FAILURE);
}
p1->elem=i+1;                  //补全结点信息
p1->pnext=NULL;

if(phead->pnext==NULL)         //链接
phead->pnext=p1;
else
p2->pnext=p1;

p2=p1;                          //重置
}

return phead;
}

void MakeLoop(LinkList phead)
{
NODE*p=phead->pnext; //取出第一个数据节点

assert(p!=NULL);

while(p->pnext!=NULL)
p=p->pnext;

p->pnext=phead->pnext;   // 链接,构成循环链表

return ;
}

void DeleteNode(LinkList phead,LinkList paim)
{

NODE*p=phead->pnext;  //取出第一个数据节点

assert(p!=NULL);

while(p->pnext!=paim)
p=p->pnext;

p->pnext=p->pnext->pnext;

if(paim==phead->pnext)   //如果删除的是第一个数据节点,
phead->pnext=p->pnext; //改变头节点指针域的值,使它始终指向
//循环链链表的某一个节点。而不丢失链表节点
free(paim);
return ;
}


链表初始状态:



刚开始写这个程序的时候,遇到一个Bug,那就是没有解决链表丢失问题。比如当退出的节点刚好为1号节点时

,1号节点就会被Free掉,这样就不能通过phead来访问各个节点了,整个链表就丢失了。

于是我在DeleteNode()函数里加了一个判断:当删除节点为第一个数据节点时,更改头节点的指针域的值,

使指向第一个数据节点的下一个节点,这样链表就不会丢失了。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: