快速业务通道

高效实现Josephus算法

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29

Josephus定义:假设N个人编号1-N,围成圈。从1号开始报数,报到M时,此人退出,然 后继续从1开始报数,直到所有人退出为止。简单的实现是使用循环单链表,设置一个计数器 count,当count == M ,删除当前节点,并将count重置。

假设M = 9,N = 5;

这里有两处地方可以优化:

1.当M>N时,取M`= M mod N,即M` = 9 % 5 = 4;报数到9与报数到4效果一致,但少遍历一次链表;

2.当M` > N / 2时,可逆 向走N - M'' + 1步,此时反向走比正向走距离更近,但需要将数据结构设置为循环双链 表。

对于M = 9,N = 5,实现优化后流程如下:

---

链表:1 2 3 4 5

N = 5
M` = 9 mod 5 = 4
M` = 4 > N / 2 = 2

反走(5 - 4 + 1) = 2 步,删除节点4,此时起点在节点3;

---

链表:1 2 3 5

N = 4
M` = 9 mod 4 = 1
M'' = 1 < N / 2 = 2

正走1步,删除节点5,此时起点在节点3;

---

链 表:1 2 3

N = 3
M` = 9 mod 3 = 0
M` = 0 < N / 2 = 1

正走0步,删除节点3,此时起点在节点2;

---

链表:1 2

N = 2
M` = 9 mod 2 = 1
M` = 1 = N / 2 = 1

正 走1步,删除节点1,此时起点在节点2;

---

链表:2

N = 1
M` = 9 mod 1 = 0
M` = 0 = N / 2 = 0

正走0步,删除节点2,此时 链表空;

算法C实现:

#include <stdio.h>
#include "dlinkedlist.h"
#define SIZE 5
#define N SIZE
#define M 9
static List init();
void print(List l);
void process(List l);
int main()
{
    List josephus = init();
    print (josephus);
    process(josephus);
    return 0;
}
/* 初始化链表 */
static List init()
{
    int i;
     List josephus = CreateList(1);
    Position p = josephus;
     for (i = 2; i <= SIZE; i++)
    {
        Insert(i, josephus, p);
        p = NextPosition(p);
    }
     return josephus;
}
/* 打印链表 */
void print(List l)
{
    if (l == NULL)
        return;
    printf ("%d ",Retrieve(l));
    Position p = NextPosition(l);
     while (p != l)
    {
        printf("%d ",Retrieve(p));
        p = NextPosition(p);
    }
    printf("\n");
}
/* Josephus处理 */
void process(List l)
{
    int n = N;
    int m = M % n;
    int i;
    Position p = l;
    while (n > 1)
     {
        if (m > n / 2)
        {
             for (i = 0; i < n - m + 1; i++)
                 p = PreviousPosition(p);
        }
         else
        {
            for (i = 0; i < m; i++)
               p = NextPosition(p);
         }
        p = PreviousPosition(p);
        printf ("%d out\n",Retrieve(NextPosition(p)));
        Remove (NextPosition(p), &l);
        n--;
        m = M % n;
        printf("current: ");
         print(l);
    }
}

测试结果:

1 2 3 4 5
4 out
current: 1 2 3 5
5 out
current: 1 2 3
3 out
current: 1 2
1 out
current: 2

这里给出循环双链表数据结构 ADT和实现

假定链表不带哨兵节点。

dlinkedlist.h
typedef int ElementType;
#ifndef DLINKEDLIST_H_INCLUDED
#define DLINKEDLIST_H_INCLUDED
struct Node;
typedef struc

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号