滴水逆向联盟

标题: VC++2012编程演练数据结构《2》单循环链表与约瑟夫问题 [打印本页]

作者: 大灰狼    时间: 2014-9-24 08:33
标题: VC++2012编程演练数据结构《2》单循环链表与约瑟夫问题

循环链表(Circular Linked List)是一种首尾相接的链表,它与单链表的唯一区别在于对尾结点的处理;因为在单链表中尾结点的指针域NULL改为指向头结点就得到了单循环链表。单循环链表可以用头指针

head或尾指针rear表示,用尾指针rear表示的单循环链表查找开始结点a1和尾结点an就很方便;查找时间都是O(1)。


启动IDE



我们基于VC++2012创建一个2的工程。


我们来实现一个单循环链表

头文件定义如下


[cpp] view plaincopy






类的实现如下


[cpp] view plaincopy




我们来演练一下类的操作

[cpp] view plaincopy


  • cout<<"运行结果:\n";  
  • int m=150,i,n=10,x,it;  
  • cirlinklist p,t,q,mylink;  
  • p.CreateCLinkL(n,m,1);  
  • if(p.CListEmpty()) cout<<"单循环链表p空!\n";  
  • else cout<<"单循环链表p非空!\n";  
  • cout<<"单循环链表p(升序):\n";  
  • p.TraverseCList();  
  • if(p.CListEmpty()) cout<<"单循环链表p空!\n";  
  • else cout<<"单循环链表p非空!\n";  
  • if(p.EndCList()) cout<<"单循环链表p满!\n";  
  • else cout<<"单循环链表p非满!\n";  
  • cout<<"单循环链表t(无序):\n";  
  • t.CreateCLinkL(n-2,m);  
  • t.TraverseCList();  
  • cout<<"单循环链表t的长度:"<<t.CListSize()<<endl;  
  • cout<<"单循环链表q(降序):\n";  
  • q.CreateCLinkL(n,m,-1);  
  • q.TraverseCList();  
  • cout<<"单循环链表q的长度:"<<q.CListSize()<<endl;  
  • cout<<"链表q的第1个元素:"<<q.GetElem(1)<<endl;  
  • cout<<"链表q的第1个元素地址:"<<q.Index(1)<<endl;  
  • cout<<"链表q的第5个元素:"<<q.GetElem(5)<<endl;  
  • cout<<"链表q的第5个元素地址:"<<q.Index(5)<<endl;  
  • cout<<"链表q的第10个元素:"<<q.GetElem(10)<<endl;  
  • cout<<"链表q的第10个元素地址:"<<q.Index(10)<<endl;  
  • cout<<"链表q的curr->next所指元素地址:"<<q.Next()<<endl;  
  • x=65;it=66;  
  • if(q.FindCList(x)) cout<<x<<"查找成功!\n";  
  • else cout<<x<<"查找不成功!\n";  
  • if(q.UpdateCList(x,it)) cout<<x<<"更新成功!\n";  
  • else cout<<x<<"更新不成功!\n";  
  • cout<<"更新后单循环链表q:\n";  
  • q.TraverseCList();  
  • cout<<"插入后单循环链表q:\n";  
  • it=100;q.InsertCList(it,1);  
  • q.TraverseCList();  
  • cout<<"插入后单循环链表q:\n";  
  • it=101;q.InsertCList(it,5);  
  • q.TraverseCList();  
  • cout<<"插入后单循环链表q:\n";  
  • it=102;q.InsertCList(it,12);  
  • q.TraverseCList();  
  • cout<<"插入后q表长:"<<q.CListSize()<<endl;  
  • cout<<"第1个数:"<<q.DeleteCList(1)<<"删除成功!\n";  
  • cout<<"删除后q表长:"<<q.CListSize()<<endl;  
  • q.TraverseCList();  
  • cout<<"第5个数:"<<q.DeleteCList(5)<<"删除成功!\n";  
  • cout<<"删除后q表长:"<<q.CListSize()<<endl;  
  • q.TraverseCList();  
  • cout<<"第11个数:"<<q.DeleteCList(11)<<"删除成功!\n";  
  • cout<<"删除后q表长:"<<q.CListSize()<<endl;  
  • q.TraverseCList();  
  •   
  • cin.get();  









来解决约瑟夫问题。

据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
  17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。

代码实现如下,人数自定义,数量自己定义


[cpp] view plaincopy


  • cout<<"约瑟夫(Josephus)问题\n";  
  • //求解约瑟夫(Josephus)问题  
  • cout<<"输入人数n:";cin>>n;  
  • cout<<"输入第次数m:";cin>>m;  
  • for(i=0;i<n;i++) mylink.InsertCList(i+1,i);  
  • cout<<"员工编号依次为:";  
  • LNode *w=mylink.Reset();  
  • while(!mylink.EndOCList())  
  • {  
  • cout<<setw(3)<<w->data;  
  • w=mylink.Next();}  
  • cout<<endl;  
  • cout<<"删除次序依次为:\n";  
  • mylink.Reset(-1);  
  • for(i=0;i<n-1;i++)  
  • {  
  •     for(int j=0;j<m-1;j++)  
  • {  
  •         w=mylink.Next();  
  • if(mylink.EndOCList())  
  • {  
  •     w=mylink.Next();  
  • }  
  •     }  
  • if(mylink.EndCList()) w=mylink.Next();  
  • cout<<"删除第"<<mylink.DeleteNext()<<"人\n";}  
  • cout<<"最后剩下的是:第"<<mylink.GetElem(1)<<"个人\n";  
  • cin.get();  
  • cin.get();  












欢迎光临 滴水逆向联盟 (http://www.dtdebug.com/) Powered by Discuz! X3.2