Tekson

禧之狼

博客园 首页 联系 订阅 管理

 

3. 循环链表

1)实现一个循环链表

#include <stdafx.h>

#include <iostream>

using namespace std;

struct CNode

{

     int data;

     CNode *next;

     CNode(){data = 0; next = this;}

/*【注】这里默认构造函数不能再和下面的构造函数合并了,因为this只能用在非静态成员函数中,而下面的构造函数是通过成员初

始化列表来完成对象构造的,这是在编译器便完成了的,而this本身所指向的对象要到运行期才能明确下来,因此不能用this作为默

认参数以及在初始化列表中进行初始化。其实,二者是一个概念,因为构造函数在进入函数体前一定会进行初始化的,如果默认参数

有规定值,则用该值进行初始化,否则编译器进行默认的初始化,然后才进行函数体中赋值操作。*/

     CNode(int _data, CNode *_next):data(_data), next(_next){}

};

int main()

{

     CNode *head, *p, *newCNode;

     head = new CNode;

     p = head;

     int i;

     for(i=1; i<10; ++i)

     {

         newCNode = new CNode(i, head);//循环链表的特色

         p->next = newCNode;

         p = newCNode;

     }

     for(p=head, i=0; i<10; ++i, p=p->next)

         cout << p->data << " ";

     cout << endl;

}

2Josephus问题(约瑟夫问题)

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

#include <stdafx.h>

#include <iostream>

using namespace std;

struct CNode

{

     int data;

     CNode *next;

     CNode(){data = 0; next = this;}

     CNode(int _data, CNode *_next):data(_data), next(_next){}

};

void Josephus(int n, int k, int m)

{

     CNode *head, *currPtr, *prevPtr, *newCNode;

     //第一步:建立Josephus问题对应的循环链表

     head = new CNode;

     /*开始时,不能使用head = new CNode(1, head);因为开始时head并没赋值,将一个没有值的指针传递给

     构造函数的实参将会导致运行时错误(因为可以通过编译时期的类型检测这一关)*/

     head->data = 1;

     currPtr = head;

     for(int i=2; i<=n; ++i)

     {

         newCNode = new CNode(i, head);

         currPtr->next = newCNode;

         currPtr = currPtr->next;

     }

     //【另】循环链表的删除和插入不涉及表首和表尾的特殊情况的考虑,因此,一般不会出现在试题中。

     //第二步:查找第k个结点

     currPtr = head;

     for(int i=1; i<k; ++i)//k>=1,循环k-1次为的是找到第k个结点

     {

         //m=1时,j=m-1=0,于是下面循环的子循环不执行,于是后面的程序便用到这里的prevPtr了。

         prevPtr = currPtr;//不能缺少这条语句,否则m=1时运行失败!

         currPtr = currPtr->next;//循环结束后currPtr指向第k个人

     }

     //第三点:删除结点

     for(int i=1; i<=n; ++i)//n>=1,每次循环减少一个,一共需要n次循环

     {

         for(int j=1; j<m; ++j)//查找要被删除的结点:从~m共需前进m-1

         {

              prevPtr = currPtr;

              currPtr = currPtr->next;

         }

         prevPtr->next = currPtr->next;

         cout << currPtr->data << " is deleted\n";

         delete currPtr;

         //prevPtr的位置不变,currPtr的位置更新为prevPtr的下一结点(其实也是原currPtr的下一结点)

         currPtr = prevPtr->next;

     }

}

int main()

{

     Josephus(13, 4, 1);//m=1意味着从第k(这里为)个人开始,依次进行删除

     return 0;

}

posted on 2009-10-08 17:05  珍宝老王  阅读(223)  评论(0编辑  收藏  举报