您的位置:首页 > 理论基础 > 数据结构算法

数据结构基础之双向链表(约瑟夫问题)

2016-02-05 22:41 435 查看
约瑟夫问题。有n个小朋友,编号分别为1,2....n,按编号围成一个圈,他们按顺时针方向从编号为K的人由1开始报数,报数为m的人出列

他的下一个人重新从1开始报数,数到m的人出列,照这样重复下去,直到所有人都出列。编写一个算法,输入n、k和m,按照出列顺序输出编号

双向链表:一个节点包含两个指针域,一个前驱结点,一个后继节点

分析:1.先建立一个双向链表

2.找到第k个节点,作为第一个开始报数的人

3.第一个人开始从1报数,报道m的人出列并删除改结点

#include"stdio.h"
#include"malloc.h"
#include"stdlib.h"
typedef int DataType;
typedef struct Node
{//定义双向链表类型
DataType data;
struct Node *prior;
struct Node *next;
}DListNode,*DLinkList;

DLinkList CreateDList(int n);
int InitDList(DLinkList *head);
void Josephus(DLinkList head,int n,int m,int k);
void main()
{
DLinkList h;
int n,k,m;
printf("输入环中的个数n=");
scanf("%d",&n);
printf("输入开始报数的序号k=");
scanf("%d",&k);
printf("报数为m的人出列m=");
scanf("%d",&m);
h=CreateDList(n);
Josephus(h,n,m,k);
}

void Josephus(DLinkList head,int n,int m,int k)
{
DListNode *p,*q;
int i;
p=head;
for(i=1;i<k;i++) //从第K人开始报数
{
q=p;
p=p->next;
}
while(p->next!=p)
{
for(i=1;i<m;i++)//数到m的人出列
{
q=p;
p=p->next;
}
q->next=p->next;  //删除p指向的结点
p->next->prior=q;
printf("%4d",p->data);
free(p);
p=q->next;
}
printf("%4d/n",p->data);

}
DLinkList CreateDList(int n)
{//创建双向链表
DLinkList head=NULL;
DListNode *s,*q;
int i;
for(i=1;i<=n;i++)
{
s=(DListNode *)malloc(sizeof(DListNode));
s->data=1;
s->next=NULL;
if(head==NULL)
{
head=s;
s->prior=head;
s->next=head;
}
else
{
s->next=q->next;
q->next=s;
s->prior=q;
head->prior=s;
}
q=s;  //q始终指向链表的最后一个节点
}
return head;
}
int InitDList(DLinkList *head)
{
*head=(DListNode*)malloc(sizeof(DListNode));
if(!head)
return -1;
(*head)->next=*head;//头结点的prior指针和next指针指向自己
(*head)->prior=*head;
return 1;
}
参考书:《数据结构》——陈锐
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: