zoukankan      html  css  js  c++  java
  • 通过例子进阶学习C++(七)CMake项目通过模板库实现约瑟夫环

    本文是通过例子学习C++的第七篇,通过这个例子可以快速入门c++相关的语法。

    1.问题描述

    回顾一下约瑟夫环问题:n 个人围坐在一个圆桌周围,现在从第 s 个人开始报数,数到第 **m **个人,让他出局;然后从出局的下一个人重新开始报数,数到第 m 个人,再让他出局......,如此反复直到所有人全部出局为止。

    上一篇我们通过数组、静态链表实现了约瑟夫环,具体参考:

    通过例子进阶学习C++(六)你真的能写出约瑟夫环么

    本文,我们进一步深入分析约瑟夫环问题,并通过c++模板库实现该问题求解,最后我们说明用模板库的优劣之处。

    2.模板库项目搭建

    本文我们用c++的模板库通过单向循环链表实现约瑟夫环问题,用c++模板库实现约瑟夫环。

    首先我们在Visual Studio中“文件”--“新建”--”CMake项目“:

    点击“下一步”:

    点击“创建”,即可生成一个CMake的C++项目。

    在解决方案上面,点击“右键”,“添加”--“新建文件夹”:

    在文件夹中新建文件“circList.h”、“CMakeLists.txt”和“main.cpp”。

    然后在整个项目的“CMakeLists.txt"中增加如下内容:

    3.C++模板库通过循环链表实现约瑟夫环

    用C++模板库实现约瑟夫环,主要包括这3个文件:“circList.h”、“CMakeLists.txt”和“main.cpp”。整个代码以《数据结构 用面向对象方法与c++语言描述》(第2版)上面的实现为基础。

    用书本上面的例子,是无法直接运行的,耗费了一定的时间才修改好。

    circList.h相关代码:

    template<class T>
    struct CircLinkNode {
    	T data;
    	CircLinkNode<T>* link;
    	CircLinkNode(CircLinkNode<T> *next = NULL):link(next){}
    	CircLinkNode(T d, CircLinkNode<T> *next = NULL):data(d),link(next){}
    };
    
    template<class T>
    class CircList {
    public:
    	CircList() {
    		first = last = NULL;
    	}
    	CircList(const T& x) {
    		first = new CircLinkNode<T>(x);
    	}
    	CircList(CircList<T>& L) {
    		T value;
    		CircLinkNode<T>* srcptr = L.getHead();
    		CircLinkNode<T>* destptr = first = new CircLinkNode<T>;
    		while (srcptr->link != NULL) {
    			value = srcptr->link->data;
    			destptr->link = new CircLinkNode<T>(value);
    			destptr = destptr->link;
    			srcptr = srcptr->link;
    		}
    		destptr->link = NULL;
    	}
    	~CircList() {
    		//makeEmpty();
    	}
    	void makeEmpty() {
    		CircLinkNode<T>* q;
    		while (first!=NULL && first->link != first) {
    			q = first->link;
    			first->link = q->link;
    			delete q;
    		}
    	}
    	int length() const {
    		CircLinkNode<T>* p = first->link;
    		int count = 0;
    		while (p != NULL) {
    			count++;
    			p = p->link;
    		}
    		return count;
    	}
    	CircLinkNode<T>* getHead()const {
    		return first;
    	}
    	void setHead(CircLinkNode<T>* p) {
    		first = p;
    	}
    	CircLinkNode<T>* Search(T x) {
    		CircLinkNode<T>* current = first->link;
    		while (current != first) {
    			if (current->data == x) break;
    			else current = current->link;
    		}
    		return current;
    	}
    	CircLinkNode<T>* Locate(int i) {
    		if (i < 0) return NULL;
    		CircLinkNode<T>* current = first;
    		int k = 0;
    		while (current->link != first && k < i) {
    			current = current->link;
    			k++;
    		}
    		return current;
    	}
    	T* getData(int i) {
    		if (i < 0) return NULL;
    		CircLinkNode<T>* current = Locate(i);
    		if (current == NULL) return NULL;
    		else return &current->data;
    	}
    
    	void setData(int i, T& x) {
    		if (i < 0) return;
    		CircLinkNode<T>* current = Locate(i);
    		if (current == NULL) return;
    		else current->data = x;
    	}
    
    	bool Insert(int i, T& x) {
    		CircLinkNode<T>* newNode = new CircLinkNode<T>(x);
    		if (newNode == NULL) {
    			cerr << "存储分配失败!" << endl;
    			exit(1);
    		}
    		
    		if (i == 1) {
    			first = last = newNode;
    			first->link = newNode;
    		}
    		else {
    			last->link = newNode;
    			last = newNode;
    		}
    		
    		newNode->link = first;	
    		return true;
    	}
    	bool Remove(int i, CircLinkNode<T> * p, CircLinkNode<T>* pre) {
    		if (first == p) {
    			first = p->link;
    		}
    		if (last == p) {
    			last = pre;
    		}
    		delete p;
    		return true;
    	}
    	void output() {
    		CircLinkNode<T>* current = first->link; 
    		cout << first->data << "  ";
    
    		while (current != last->link) {
    			cout << current->data <<"  ";
    			current = current->link;
    		}
    		cout << endl;
    	}
    private:
    	CircLinkNode<T>* first, * last;
    };
    

    CMakeLists.txt相关代码如下:

    # CMakeList.txt: DataStructure 的 CMake 项目,在此处包括源代码并定义
    # 项目特定的逻辑。
    #
    cmake_minimum_required (VERSION 3.8)
    
    # 将源代码添加到此项目的可执行文件。
    add_executable (circList "main.cpp" "circList.h" )
    
    # TODO: 如有需要,请添加测试并安装目标。
    
    

    main.cpp相关代码如下:

    #include<iostream>
    #include "circList.h"
    
    using namespace std;
    
    template<class T>
    void Josephus(CircList<T> &Js,int n,int m) {
    	CircLinkNode<T>* p = Js.getHead();
    	CircLinkNode<T>* pre = NULL;
    
    	int i, j;
    	for (i = 0; i < n - 1; i++) {
    		for (j = 0; j < m-1; j++) {
    			pre = p;
    			p = p->link;
    		}
    		
    		cout << "出列的是:" << p->data << endl;
    		pre->link = p->link;
    
    		Js.Remove(p->data,p,pre);
    		
    		p = pre->link;
    
    		cout << "出列后的队列为:" << endl;
    		Js.output();
    		cout << "当前元素为:" << p->data << endl;
    	}
    }
    
    int main() {
    	CircList<int> clist;
    	int i, n, m;
    	cout << "输入游戏者人数和报数间隔:"<<endl;
    	cin >> n >> m;
    	for (i = 1; i <= n; i++) {
    		clist.Insert(i,i);
    	}
    
    	Josephus(clist, n, m);
    }
    

    程序运行后效果如下:

    4.总结

    本着Talk is cheap. Show me the code原则,代码实现不做过多解释。

    通过该例子,可以学习:

    • 在Visual Studio中搭建CMake项目;
    • 在CMake项目中增加“可执行文件”;
    • 掌握struct定义;class定义;template class 、function定义;构造函数;析构函数;
    • 通过模板库实现约瑟夫环问题

    本文从构思到完成,可谓是耗费了大量的心血。

    如果您阅读本文后哪怕有一丢丢收获,请不要吝啬你手中关注点赞的权力,谢谢!

    另外,如果需要相关代码,请留言,可以提供完整源代码

    所有文章,坚持原创。如有转载,敬请标注出处。
  • 相关阅读:
    如何去掉修改Joomla、joomlart及其模版版权、标志、图标的方法
    如何joomla修改版权信息
    嫌我的键盘的backspace太小,就尝试了一下改键工具--keyTweak
    css3 -- 过渡与动画
    css3 -- 2D变换
    css3 -- 渐变
    css3 -- 颜色与不透明度
    css3 -- 背景图处理
    css3 -- 多列
    css3 -- 文本
  • 原文地址:https://www.cnblogs.com/siweihz/p/12202811.html
Copyright © 2011-2022 走看看