约瑟夫环问题——legend

来源:互联网 发布:女性就业歧视知乎 编辑:程序博客网 时间:2024/05/22 10:28


约瑟夫环问题:
(一)问题:
已知有n个人(编号为1,2,3...n)围坐在一个圆桌周围,从编号为k的人开始报数,数到m的那个人出队,出队的下一个位置的人继续从k开始数数,数到m的那个人继续出队,。。。,知道所有的人都出队了,求出队序列。

(二)方法一:循环链表。
(1)步骤:
1.构造一个有n个元素的循环链表,无头节点。
2.确定第一个报数人的位置;
3.不断从链表中删除节点;

(2)代码实现:
typedef struct linkNode{
 DataType data;
 linkNode* next;
}

linkNode* creatLoopLink(int n){
 static linkNode * pnode;
 pnode=(linkNode*) malloc(sizeof(linkNode));//产生一个新节点;
 pnode->data=1;
 pnode->next=NULL;

 LinkNode* curNode,*lastNode=pnode;

 for(int i=2;i<=n;i++){
  curNode=(linkNode*) malloc(sizeof(linkNode));//产生一个新节点
  curNode->data=i;
  curNode->next=NULL;

  lastNode->next=curNode;//尾接法创建一个链表
  lastNode=curNode;
 }

 lastNode->next=pnode;//最后一个节点的尾部连接头。
return pnode;
}


/*
从循环链表link中,不断删除编号为m的节点。
k表示起始读数;
m要删除的编号
n为节点个数
*/
deleteNode_m(linkNode* link, int k, int m ,int n){
 
 linkNode* pre,cur=link;
 for(int i=1;i<=k;i++){//定位到第k个节点,即第一个报数的人。
  pre=cur;
  cur=cur->next;
 }

 for(int i=n;i>=1;i--){//计算出队序列
  for(int j=k;j<=m;j++){//从k定位到m
   pre=cur;
   cur=cur->next;
  }

  pre->next=cur->next;
  visit(cur->data);
  free(cur);

  cur=pre->next;//下一个从删除节点的下一个开始数数。
 }
}

(三)方法二:循环队列

(1)步骤:
1.初始化队列:
将编号为1,2,3....n的人依次入队;
2.定位k:
依次出队,直到m,并且将出队的元素同时插入到队尾。
3.删除m:
从k到m-1,依次出队,并且入队到队尾,m直接出队,不再入队。

4.下一个k的位置,就是不再入队的m的下一个元素。循环3、直到全部删除。


0 0
原创粉丝点击