通過例子進階學習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 ¤t->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定義;建構函式;解構函式;
- 通過模板庫實現約瑟夫環問題
本文從構思到完成,可謂是耗費了大量的心血。
如果您閱讀本文後哪怕有一丟丟收穫,請不要吝嗇你手中關注和點讚的權力,謝謝!
另外,如果需要相關程式碼,請留言,可以提供完整原始碼