题目:有N个人做成一圈玩游戏,编号为1至N。从编号为1的人开始传递马铃薯。M次传递后,持有马铃薯的人退出游戏。圈缩小,然后游戏从退出的人下面的人开始,继续进行。最终留下来的人获胜。写出一个程序解决约瑟夫环问题,此时M和N为任意值。

 

编程如下:

#include <iostream>

using namespace std;

template <typename Object>
class List
{
    private:
        struct Node                             //List内部维护的节点类
        {
            Object data;
            Node *prev;
            Node *next;

            Node( const Object &d = Object(),Node *p = NULL,Node *n = NULL )
                : data( d ),prev( p ),next( n ) { }
        };

    public:
        class const_iterator                    //常量迭代器
        {
            public:
                const_iterator() : current( NULL )
                { }

                const Object &operator*() const
                { return retrieve(); }

                const_iterator &operator++()
                {
                    current = current->next;
                    return *this;
                }

                const_iterator operator++( int )
                {
                    const_iterator old = *this;
                    ++( *this );
                    return old;
                }

                bool operator== ( const const_iterator &rhs ) const
                { return current == rhs.current; }

                bool operator!= ( const const_iterator &rhs ) const
                { return !( *this == rhs ); }

            protected:
                Node *current;

                Object &retrieve() const
                { return current->data; }

                const_iterator( Node *p ) : current( p )
                { }

                friend class List<Object>;
        };

        class iterator : public const_iterator  //迭代器类继承自常量迭代器类
        {
            public:
            iterator()
            { }

            Object &operator*()
            { return const_iterator::retrieve(); }

            const Object &operator*() const
            { return const_iterator::operator*(); }

            iterator &operator++()
            {
                const_iterator::current = const_iterator::current->next;
                return *this;
            }

            iterator operator++( int )
            {
                iterator old = *this;
                ++( *this );

                return old;
            }

            protected:
                iterator( Node *p ) : const_iterator( p )
                { }

                friend class List<Object>;
        };

    public:
        List()
        { init(); }

        ~List()
        {
            clear();
            delete head;
            delete tail;
        }

        List( const List &rhs )
        {
            init();
            *this = rhs;
        }

        const List &operator= ( const List &rhs )
        {
            if ( this == &rhs )
                return *this;
            clear();
            for ( const_iterator itr = rhs.begin() ; itr != rhs.end() ; ++itr )
                push_back( *itr );

            return *this;
        }

        iterator begin()
        { return iterator( head->next ); }
        const_iterator begin() const
        { return const_iterator( head->next ); }
        iterator end()
        { return iterator( tail ); }
        const_iterator end() const
        { return const_iterator( tail ); }

        int size() const
        { return theSize; }
        bool empty() const
        { return size() == 0; }

        void clear()
        {
            while ( !empty() )
                pop_front();
        }

        Object &front()
        { return *begin(); }
        const Object &front() const
        { return *begin(); }
        Object &back()
        { return *--end(); }
        const Object &back() const
        { return *--end(); }
        void push_front( const Object &x )
        { insert( begin(),x ); }
        void push_back( const Object &x )
        { insert( end(),x ); }
        void pop_front()
        { erase( begin() ); }
        void pop_back()
        { erase( --end() ); }

        iterator insert( iterator itr,const Object &x )
        {
            Node *p = itr.current;
            theSize++;
            return ( p->prev = p->prev->next = new Node( x,p->prev,p ) );
        }

        iterator erase( iterator itr )
        {
            Node *p = itr.current;
            iterator retVal( p->next );
            p->prev->next = p->next;
            p->next->prev = p->prev;
            delete p;
            theSize--;

            return retVal;
        }

        iterator erase( iterator start,iterator end )
        {
            for ( iterator itr = start ; itr != end; )
                itr = erase( itr );

            return end;
        }

    private:
        int theSize;
        Node *head;
        Node *tail;

        void init()
        {
            theSize = 0;
            head = new Node;
            tail = new Node;
            head->next = tail;
            tail->prev = head;
        }
};

void PrintList( List<int> &list )                   //打印List
{
    for ( List<int>::iterator itr = list.begin() ; itr != list.end() ; ++itr )
        cout << *itr << " ";

    cout << endl;
}

int main( void )
{
    List<int>Number;
    int count = 0;
    cout << "参加游戏的是几个人?" << endl;
    cin >> count;

    int M = 0;
    cout << "传递几次人员退出?" << endl;
    cin >> M;

    for ( int i = 0 ; i != count ; ++i )
        Number.push_back( i + 1 );

    cout << "游戏刚开始时人员情况:" << endl;
    PrintList( Number );

    count = 0;
    List<int>::iterator iter = Number.begin();
    while ( Number.size() - 1 ){                        //剩下最后一个人时退出循环
        for ( int j = 0 ; j != M ; j++ ){
            if ( iter == Number.end() )                 //当循环到最后,迭代器指向第一个人。
                iter = Number.begin();
            iter++;
        }

        if ( iter == Number.end() )                     //当循环到最后,迭代器指向第一个人。
                iter = Number.begin();

        cout << "要退场的人的编号是:" << *iter << endl;
        iter = Number.erase( iter );

        count++;
        cout << "" << count << "轮后人数情况:" << endl;
        PrintList( Number );
    }

    cout << "胜利者是:" << *( Number.begin() ) << "" << endl;

    return 0;
}

运行效果:

运行时间关键在于M和N。Number链表迭代N-1次,且M≠0时,for循环的运行时间是O(M),每次删除节点就调用for循环,运行时间应该是O(MN)。