简单约瑟夫环的循环单链表实现(C++)
刚刚接触C++以及数据结构,今天做了第一次尝试用C++和数据结构解决问题,问题是基于约瑟夫环问题的简单版。
- 先来看看约瑟夫环问题的介绍:
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始 报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。(摘自百度百科)
程序的输入应该由三个值组成(n, k, m),接下来程序将会自动运行,本文假设每次都从第一个人开始报数,所以是做了一些简化,但是换汤不换药。
- 接下来将分部介绍程序的组成
首先是头文件,命名为circle_single_linked_list.h
基本结构:
template <typename Object>
class circleSingleLinkedList{
private: /*循环单链表的每个的节点定义
*结构简单,所以使用struct
*具体实现请看下文
*/
struct Node{
}; public: /*内嵌类iterator
*是链表中的一个位置的抽象(abtracts the notion of a position)
*类比vector<>的iterator
*在类外的调用方法为:circleSingleLinkedList<int>::iterator ....
*本文省去了对于const_iterator类型的定义
*/
class iterator{
}; public: /*循环链表实现
*由构造函数(含默认实参),big three都没有...(程序比较简陋)
*begin()返回表头位置
*insert以及erase是实现约瑟夫环的主要手段
*循环链表只有2个数据成员, theSize存储链表节点个数, head为头指针, 指向链表中的第一个节点
*具体实现见下文
*/
circleSingleLinkedList(const Object& x = Object()){
} iterator begin()const{
} int size(){
return theSize;
} bool empty(){
return size() == ;
} iterator insert(iterator itr, const Object& x){
} iterator erase(iterator itr){
} void print(ostream& out){
} private:
int theSize;
Node* head;
};
由于编写的是模板类,所以将类的定义,成员函数的实现,以及内嵌类的实现都放在了一个头文件中,本人刚刚接触C++,目前了解的情况是:模板类最好不要用 separate compilation,因为可能会造成complicated looking syntax,具体是什么我目前也不清楚,需要继续学习。
- 接下来是各部分的具体实现
struct Node{
Object data; //用于存放各个节点的数值,在约瑟夫环问题中,存放不同人的编号
Node* next; //每个单链表节点的指向下一个节点的指针
Node(const Object& d = Object(), Node* n=NULL) //默认构造函数
: data(d), next(n) {}
};
内嵌类iterator的实现
//iterator类主要包含了运算符重载:解引用,prefix++,postfix++,==,!=,具体的使用可以类比vector<>::iterator的使用方法.
1 class iterator{
public:
iterator(): current(NULL){} Object & operator*()const{
return current->data;
} iterator & operator++(){
current = current->next;
return *this;
} iterator operator++(int){
iterator old = *this;
++(*this);
return old;
} bool operator==(const iterator& rhs)const{
return current == rhs.current;
} bool operator!=(const iterator& rhs)const{
return !(*this == rhs);
} protected: //protected一般在有继承的情况下使用,这个地方我就懒得改了
Node* current; //iterator是链表中一个具体位置的抽象, current指针用于指向所选定的节点 iterator(Node* p): current(p){} //iterator类型主要使用的构造函数 friend class circleSingleLinkedList<Object>;//使外层包含类也可以访问iterator的非public成员
};
剩下的就是循环单链表的定义,在这里我就想着重讲一下insert以及erase方法,begin()函数,默认构造函数(初始化头结点)以及print函数(输出链表各节点的data数据)这里就不提了。
insert(位置,数值),因为这是单链表,不能通过一个位置来确定它之前的位置(没有指向前一个节点的指针),所以insert是在itr所确定的元素的后面插入一个新节点,函数返回新节点处的位置.
需要注意的是,insert与erase都是的返回类型都是copy passing的,具体原因我暂时还搞不清楚.
1 iterator insert(iterator itr, const Object& x){
Node* p = itr.current;
Node* newNode = new Node(x, p->next);
p->next = newNode;
theSize++;
return iterator(newNode);
7 }
erase函数
erase(位置),删除itr位置之后的元素,原理与insert相同,如果删除的元素师头节点,则将头节点分配给原头节点的下一个元素
1 iterator erase(iterator itr){
Node* p = itr.current;
if(p->next == head)
head = head->next;
Node* old = p->next->next;
delete p->next;
p->next = old;
theSize--;
return itr;
}
- 接下来我们来看一下main函数中的实际应用情况,也就是约瑟夫环问题。
int main()
{
circleSingleLinkedList<int> iList(); //初始化循环链表,其包含一个头节点,由head指针指向,头指针指向的元素就是约瑟夫环问题中的第一个人,编号为1 int n;
cout << "n=" << endl; //输入约瑟夫环问题中的人数n
cin >> n; int i=;
circleSingleLinkedList<int>::iterator iter = iList.begin(); //初始化iter指向头节点
while(i <= n){
iter = iList.insert(iter,i); //为链表添加节点元素,每一次都添加到iter所抽象的元素的下一个,其数值为i
++i;
} iter = iList.begin(); //iter重新指向表头 int m;
cout << "m=" << endl; //输入约瑟夫环问题中的步值m,也就是每做一次删除所数的一个步长
cin >> m; i = ;
while(iList.empty() != true){
while(i < m){ //由于erase是删除iter所指向的下一个元素,而不是删除iter,所以iter需要代表被删除元素之前的一个元素.
++iter;
++i;
}
iter = iList.erase(iter);
iList.print(cout); //每做一次删除就输出显示整个list.
i = ;
} cout << endl; return ;
}
- 最后结果:

输入n=10, m=3, 由于我默认程序从第一个节点(1)开始数,所以第一个删除的节点是4(也就是编号为4的人),删除之后,从4的下一个节点(5)开始数3,第二个删除的元素为8,以此类推.
- 总结:这是第一次用数据结构和C++解决实际问题,也是第一次发博文,目前对数据结构的理解是,其是对内存空间进行某种特定规律的管理的一种手段,以特殊的策略实现功能程序的优化。
希望继续练习,熟悉更多的结构。
2013-11-08 11:12:23
简单约瑟夫环的循环单链表实现(C++)的更多相关文章
- C代码实现非循环单链表
C代码实现非循环单链表, 直接上代码. # include <stdio.h> # include <stdlib.h> # include <malloc.h> ...
- PTA 循环单链表区间删除 (15 分)
本题要求实现带头结点的循环单链表的创建和单链表的区间删除.L是一个带头结点的循环单链表,函数ListCreate_CL用于创建一个循环单链表,函数ListDelete_CL用于删除取值大于min小于m ...
- C语言版本:循环单链表的实现
SClist.h #ifndef __SCLIST_H__ #define __SCLIST_H__ #include<cstdio> #include<malloc.h> # ...
- c语言循环单链表
/************************************************************************* > File Name: singleLin ...
- c语言有头循环单链表
/************************************************************************* > File Name: singleLin ...
- 【c++版数据结构】之循环单链表的实现(带头结点以及尾节点)
所实现的循环单链表的结构例如以下图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill ...
- 带头结点的循环单链表----------C语言
/***************************************************** Author:Simon_Kly Version:0.1 Date: 20170520 D ...
- 循环单链表定义初始化及创建(C语言)
#include <stdio.h> #include <stdlib.h> /** * 含头节点循环单链表定义,初始化 及创建 */ #define OK 1; #defin ...
- 用最简单的方式学Python单链表
Python 实现单链表 在本博客中,我们介绍单链表这种数据结构,链表结构为基于数组的序列提供了另一种选择(例如Python列表). 基于数组的序列和链表都能够对其中的元素保持一定得顺序,但采用的方式 ...
随机推荐
- OpenGL ES 3.0 点,线,三角形绘制形式总结
OpenGL ES 3.0 顶点 -1, 1, 0, -0.5f, 0, 0, 0, -1, 0, -1, 0, 0, 0.5f, 0, 0, 1, -1, ...
- Difference Between XML and XAML.
XML, or Extensible Markup Language, is a subset of the more complex SGML (Standard Generalized Mark ...
- How to customize authentication to my own set of tables in asp.net web api 2?
ssuming your table is called AppUser, convert your own AppUser domain object to IUser(using Microsof ...
- vs2010 web 发布
1.在服务器上安装web deploy,这时iis中右侧功能中就多了“导入应用程序” 2.在代码的项目中,点击项目属性,将debug改为release,选择对应的平台.目标平台,主要用来区分32位还是 ...
- 在MVC中写Filter时经常filterContext无法代码提示HttpContext的方法和属性的原因
需要用System.Web.Abstractions.dll HttpContextBase是在System.Web.Abstractions下的,添加对System.Web.Abstractions ...
- Xcode 7真机测试详解
1.准备 注意:一定要让你的真机设备的系统版本和app的系统版本想对应,如果不对应就会出现一个很常见的问题:could not find developer disk image 首先,准备好下面的设 ...
- SVN Global ignore pattern 忽略文件正则后缀
*.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo __pycache__ *.rej *~ #*# .#* .*.swp .DS_St ...
- Debian 8.0(Jessie) 无线网卡,ATI显卡驱动和输入法等安装记录。
转载请注明作者与出处!谢谢! 最近准备彻底转换到Linux平台,之前一直用的是Red Hat,对Debian不是很熟悉,花了不少时间摸索.下面记录一下安装的过程以便备忘,顺便给他人能做个参考. 我的是 ...
- Jqprint 轻量级页面打印插件
最近项目中需要在页面上添加一个打印的按钮,上网搜索了一下就发现了这个好用的超轻量插件,使用起来很方便 1.首先需要引入必须的js文件 <script language="javascr ...
- 设置session的生命周期(php)
PHP中,Session变量保存在服务器端(默认以文件格式保存),而Session ID以cookie形式保存在客户端. 销毁session的方法有2种 第一种是通过程序 session_destor ...