// professional c++ 4th edition p388
//2020年06月08日 21时36分43秒
#include
void func(const std::map<int, int>& m)
{
// cout << m[1] << endl; // Error
}
class Data final
{
public:
explicit Data(int value = 0) : mValue(value) { }
int getValue() const { return mValue; }
void setValue(int value) { mValue = value; }
private:
int mValue;
};
//professional c++ 4th edition p392
class BankAccount final
{
public:
BankAccount(int acctNum, std::string_view name) : mAcctNum(acctNum), mClientName(name) {}
void setAcctNum(int acctNum) { mAcctNum = acctNum; }
int getAcctNum() const { return mAcctNum; }
void setClientName(std::string_view name) { mClientName = name; }
std::string_view getClientName() const { return mClientName; }
private:
int mAcctNum;
std::string mClientName;
};
class BankDB final
{
public:
// Adds account to the bank database. If an account exists already
// with that number, the new account is not added. Returns true
// if the account is added, false if it’s not.
bool addAccount(const BankAccount& account);
// Removes the account acctNum from the database.
void deleteAccount(int acctNum);
// Returns a reference to the account represented
// by its number or the client name.
// Throws out_of_range if the account is not found.
BankAccount& findAccount(int acctNum);
BankAccount& findAccount(std::string_view name);
// Adds all the accounts from db to this database.
// Deletes all the accounts from db.
void mergeDatabase(BankDB& db);
private:
std::map<int, BankAccount> mAccounts;
};
bool BankDB::addAccount(const BankAccount& acct)
{
// Do the actual insert, using the account number as the key
auto res = mAccounts.emplace(acct.getAcctNum(), acct);
return res.second;
}
void BankDB::deleteAccount(int acctNum)
{
mAccounts.erase(acctNum);
}
BankAccount& BankDB::findAccount(int acctNum)
{
// Finding an element via its key can be done with find()
auto it = mAccounts.find(acctNum);
if (it == end(mAccounts)) {
throw std::out_of_range("No account with that number.");
}
// Remember that iterators into maps refer to pairs of key/value
return it->second;
}
BankAccount& BankDB::findAccount(std::string_view name)
{
for (auto& [acctNum, account] : mAccounts) {
if (account.getClientName() == name) {
return account; // found it!
}
}
throw std::out_of_range(“No account with that name.”);
}
void BankDB::mergeDatabase(BankDB& db)
{
// Use C++17 merge().
mAccounts.merge(db.mAccounts);
// Or: mAccounts.insert(begin(db.mAccounts), end(db.mAccounts));
// Now clear the source database.
db.mAccounts.clear();
}
int main()
{
std::map<int, int> m;
m[1] = 11;
m[2] = 22;
m[3] = 33;
func(m);
std::map<int, Data> dataMap1;
dataMap1[1] = Data(4);
dataMap1[1] = Data(6); // Replaces the element with key 1
// Using C++11 auto keyword
for (auto iter = cbegin(dataMap1); iter != cend(dataMap1); ++iter) {
std::cout << iter->second.getValue() << std::endl;
}
// Using C++11 range-based for loop
for (const auto& p : dataMap1) {
std::cout << p.second.getValue() << std::endl;
}
// Using range-based for loop + C++17 structured bindings
for (const auto& [key, data] : dataMap1) {
std::cout << data.getValue() << std::endl;
}
// If your compiler does not support the above C++11 versions
for (std::map<int, Data>::const_iterator iter = dataMap1.begin();
iter != dataMap1.end(); ++iter) {
std::cout << iter->second.getValue() << std::endl;
}
std::map<int, Data> dataMap2;
dataMap2[1] = Data(4);
dataMap2[1] = Data(6);
dataMap2[1].setValue(100);
auto it = dataMap2.find(1);
// If your compiler does not support the C++11 auto keyword:
//map<int, Data>::iterator it = dataMap.find(1);
if (it != end(dataMap2)) {
it->second.setValue(100);
}
std::cout << "There are " << dataMap2.count(1) << " elements with key 1" << std::endl;
dataMap2.erase(1);
std::cout << "There are " << dataMap2.count(1) << " elements with key 1" << std::endl;
/* // p616
All the ordered and unordered associative containers are so-called noded-based data structures.
Starting with C++17, the Standard Library provides direct access to nodes in the form of node
handles. The exact type is unspecified, but each container has a type alias called node_type that
specifies the type of a node handle for that container. A node handle can only be moved, and is the
owner of the element stored in a node. It provides read/write access to both the key and the value.
Nodes can be extraccted from an associative container as a node handle using the extract() method,
based either on a given iterator position or on a given key. Extracting a node from a container
removes it from the container, because the returned node handle is the sole owner of the extracted
element.
New insert() overloads are provided that allow you to insert a node handle into a container.
Using extract() to extract node handles, and insert() to insert node handles, you can effectively
transfer data from one associative constainer to another one without any copying or moving involved
.You can even move nodes from a map to a multimap, and from a set to a multiset.
*/
dataMap2.insert(dataMap2.extract(1));
std::map<int, int> src = { { 1, 11 },{ 2, 22 } };
std::map<int, int> dst = { { 2, 22 },{ 3, 33 },{ 4, 44 },{ 5, 55 } };
dst.merge(src);
BankDB db;
db.addAccount(BankAccount(100, "Nicholas Solter"));
db.addAccount(BankAccount(200, "Scott Kleper"));
try {
auto& acct = db.findAccount(100);
std::cout << "Found account 100" << std::endl;
acct.setClientName("Nicholas A Solter");
auto& acct2 = db.findAccount("Scott Kleper");
std::cout << "Found account of Scott Kleper" << std::endl;
auto& acct3 = db.findAccount(1000);
} catch (const std::out_of_range& caughtException) {
std::cout << "Unable to find account: " << caughtException.what() << std::endl;
}
return 0;
}
/*
wannian07@wannian07-PC:~$ g++ -std=c++17 -o c12 c12.cpp
wannian07@wannian07-PC:~$ ./c12
6
6
6
6
There are 1 elements with key 1
There are 0 elements with key 1
Found account 100
Found account of Scott Kleper
Unable to find account: No account with that number.
Josephus数 Concrete Mathematics p18/549
假 设n 个竞赛者排成一个环形,依次顺序编号1,2,…,n。从某个指定的第1 号开始,沿环计数,每数到第2个人就让其出列,且从下一个人开始重新计数,继续进行下去。这个过程一直进行到所有的人都出列为止。最后出列者为优胜者。优 胜者的号码定义为第一类Josephus数,J(n)。显然,1<=J(n)<=n。
下面的递推公式引用其中:
J(1) = 1; J(10) = 2 J(5) - 1 = 5
J(2n) = 2J(n)-1, n>=1; J(20) = 2J(10) - 1 = 2 * 5 - 1 = 9
J(2n+1) = 2J(n)+1, n>=1; J(41) = 2J(20) + 1 = 2 * 9 + 1 = 19 (2^M + L) = (2^5 + 9) = 2*9+1
https://www.xuebuyuan.com/3260450.html 数学分析, 高等代数和计算机算法并无多大联系 TOJ 平台
Josephus问题
关于该问题简单描述:假设有n个人排成一个圈。从第一个人开始报数,数到第m个人的时候这个人从队列里出列。然后继续在环里数后面第m个人,让其出列直到所有人都出列。最后一个出列的是胜出者。
思路1: 若共有N = 9 个人, 且每数M = 5个人就排除对应者,
出列顺序为: 5, 1, 7, 4, 3, 6, 9, 2. 8 是最后的人
算法的灵魂在于思想, 而不是实现.
将算法的思想用具体的语言工具表达出来, 解决实际遇到的问题.
思路2:
由于这个问题是学习数据结构中链表时的一个典型例子.题目只要求输出最后一个出列的人的号码, 并没有要求模拟整个过程.
每个人出列后, 剩下的人又组成了另一个子问题. 只是他们的编号变化了.
第一个出列的人肯定是a[1] = m(mod)n(m/n的余数), 他除去后剩下的人是 :1, 2, …a[1]-2, a[1]-1, a[1]+1, a[1]+2…n
对应的新编号是 : 1, 2, 3…n-1; // < m >
设此时某个人的新编号是 i 很容易看出, 他原来的编号就是(i+a[1])%n.
这便形成了简单的递归问题
假如 知道这个问题(n-1)个人的解是: x ,
那么, 原问题的(n)个人的 解是: (x+m%n)%n = (x + m)%n.
问题的开始条件: 如果n = 1, 那么结果就是 1;
#include
int main(){
int i, n, m, ans(1); // ans 是最后一个出列的人
std::cin >> n >> m;
for(i = 2; i <= n; i++){
ans = (ans + m) % i;
if(ans == 0) ans = i; // 遇到0 后把它变成i(因为编号是1, 2, 3 … i)
}
std::cout << ans << std::endl;
}
https://www.xuebuyuan.com/3260450.html
*/