Added map
This commit is contained in:
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
`priority_queue`:3 月 24 日(第五周周日)18:30 前
|
`priority_queue`:3 月 24 日(第五周周日)18:30 前
|
||||||
|
|
||||||
未完待续
|
`map`: 4 月 14 日(第八周周日)18:30 前
|
||||||
|
|
||||||
## 迟交惩罚
|
## 迟交惩罚
|
||||||
|
|
||||||
|
34
map/README.md
Normal file
34
map/README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
## 作业要求
|
||||||
|
|
||||||
|
- 这次大作业要求实现与 C++ 标准库类似的数据结构 map,包括迭代器等。框架接口在已本仓库中给出,只需要实现`.hpp`文件内所要求的内容即可。
|
||||||
|
- B班实现可以 AVL 树、AA 树、红黑树三选一,A 班实现红黑树。
|
||||||
|
- 你需要完成下发文件中的作业代码,在 OJ 上面提交`map.hpp`,要求可以实现 map 的基本操作,并且具有一定的鲁棒性。
|
||||||
|
- Bonus: 在测试数据中有一些`type_traits`的测试,感兴趣可以尝试。具体的工作以及计分方法尚未确定,后续可能会有更新。
|
||||||
|
- 在本作业中,只允许使用`cstdio`,`cstring`,`iostream`,`cmath`,`string`五个 C++ 标准库,如需使用其他功能请自行实现。
|
||||||
|
- 我们会检查内存泄漏,如果还不会测内存泄漏,可以看教程[如何检测内存泄漏?](./tutorials/detect-memory-leak/detect-memory-leak.md)
|
||||||
|
|
||||||
|
## 下发文件
|
||||||
|
|
||||||
|
- `data directory`: 测试源码和正确输出
|
||||||
|
- `map.hpp`: 提供接口,完成`TODO`部分代码,请不要随意改动接口,否则会导致测评代码不能正确调用你的文件。
|
||||||
|
- `exception.hpp` `utility.hpp`: 保证测试在本地正确运行的相关代码,请不要随意改动。
|
||||||
|
- 最终 OJ 测试仅仅需`map.hpp`。
|
||||||
|
|
||||||
|
## 实现细节
|
||||||
|
|
||||||
|
**可能需要注意的细节:**
|
||||||
|
|
||||||
|
- 在测试点中,有一些类并不具有默认构造函数,所以直接使用`T* p=new T[...];`可能会出现问题。
|
||||||
|
- 你的程序将会受到一定程度的鲁棒性检测
|
||||||
|
|
||||||
|
## 分数构成
|
||||||
|
|
||||||
|
- **总得分** = 80%(OJ 测试部分) + 20%(code review)=80%(OJ 测试部分) + 16% (基础问题) + 4% (Bonus)
|
||||||
|
- **注意事项:**
|
||||||
|
1. 使用普通的二叉搜索树完成此题,最终得分为:0.4\*以上得分
|
||||||
|
2. 使用非二叉搜索树、以及要求的算法外的方法完成此题,最终得分为:0.7\*以上得分
|
||||||
|
- **关于 Bonus:** 可以是对容器或者迭代器的某个行为的优化,type_traits 相关应用或其他有创意的想法,在 code review 时展示即可(本部分后续会有更新,可能涉及具体工作的改变)
|
||||||
|
- **学术诚信问题**:如果在 CR 时,发现有任何违规行为(包括但不限于使用其它头文件、使用非常规方法通过测试点),你最终的得分都有可能为 0 分。
|
||||||
|
## 截止日期
|
||||||
|
|
||||||
|
作业时间为三周,即 ddl 设在第八周周日上机课之前(4月14号 18:30),大家合理安排时间完成~
|
516
map/data/class-bint.hpp
Normal file
516
map/data/class-bint.hpp
Normal file
@ -0,0 +1,516 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Util {
|
||||||
|
|
||||||
|
const size_t MIN_CAPACITY = 2048;
|
||||||
|
|
||||||
|
class Bint {
|
||||||
|
class NewSpaceFailed : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
NewSpaceFailed();
|
||||||
|
};
|
||||||
|
class BadCast : public std::invalid_argument {
|
||||||
|
public:
|
||||||
|
BadCast();
|
||||||
|
};
|
||||||
|
bool isMinus = false;
|
||||||
|
size_t length;
|
||||||
|
int *data = nullptr;
|
||||||
|
size_t capacity = MIN_CAPACITY;
|
||||||
|
void _DoubleSpace();
|
||||||
|
void _SafeNewSpace(int *&p, const size_t &len);
|
||||||
|
explicit Bint(const size_t &capa);
|
||||||
|
public:
|
||||||
|
Bint();
|
||||||
|
Bint(int x);
|
||||||
|
Bint(long long x);
|
||||||
|
Bint(std::string x);
|
||||||
|
Bint(const Bint &b);
|
||||||
|
Bint(Bint &&b) noexcept;
|
||||||
|
|
||||||
|
Bint &operator=(int rhs);
|
||||||
|
Bint &operator=(long long rhs);
|
||||||
|
Bint &operator=(const Bint &rhs);
|
||||||
|
Bint &operator=(Bint &&rhs) noexcept;
|
||||||
|
|
||||||
|
friend Bint abs(const Bint &x);
|
||||||
|
friend Bint abs(Bint &&x);
|
||||||
|
|
||||||
|
friend bool operator==(const Bint &lhs, const Bint &rhs);
|
||||||
|
friend bool operator!=(const Bint &lhs, const Bint &rhs);
|
||||||
|
friend bool operator<(const Bint &lhs, const Bint &rhs);
|
||||||
|
friend bool operator>(const Bint &lhs, const Bint &rhs);
|
||||||
|
friend bool operator<=(const Bint &lhs, const Bint &rhs);
|
||||||
|
friend bool operator>=(const Bint &lhs, const Bint &rhs);
|
||||||
|
|
||||||
|
friend Bint operator+(const Bint &lhs, const Bint &rhs);
|
||||||
|
friend Bint operator-(const Bint &b);
|
||||||
|
friend Bint operator-(Bint &&b);
|
||||||
|
friend Bint operator-(const Bint &lhs, const Bint &rhs);
|
||||||
|
friend Bint operator*(const Bint &lhs, const Bint &rhs);
|
||||||
|
|
||||||
|
friend std::istream &operator>>(std::istream &is, Bint &b);
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, const Bint &b);
|
||||||
|
|
||||||
|
~Bint();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Util {
|
||||||
|
|
||||||
|
Bint::NewSpaceFailed::NewSpaceFailed() : std::runtime_error("No Enough Memory Space.") {}
|
||||||
|
Bint::BadCast::BadCast() : std::invalid_argument("Cannot convert to a Bint object") {}
|
||||||
|
|
||||||
|
void Bint::_SafeNewSpace(int *&p, const size_t &len)
|
||||||
|
{
|
||||||
|
if (p != nullptr) {
|
||||||
|
delete[] p;
|
||||||
|
p = nullptr;
|
||||||
|
}
|
||||||
|
p = new int[len];
|
||||||
|
if (p == nullptr) {
|
||||||
|
throw NewSpaceFailed();
|
||||||
|
}
|
||||||
|
memset(p, 0, len * sizeof(unsigned int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bint::_DoubleSpace()
|
||||||
|
{
|
||||||
|
int *newMem = nullptr;
|
||||||
|
_SafeNewSpace(newMem, capacity << 1);
|
||||||
|
memcpy(newMem, data, capacity * sizeof(int));
|
||||||
|
delete[] data;
|
||||||
|
data = newMem;
|
||||||
|
capacity <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint::Bint()
|
||||||
|
: length(1)
|
||||||
|
{
|
||||||
|
_SafeNewSpace(data, capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint::Bint(int x)
|
||||||
|
: length(0)
|
||||||
|
{
|
||||||
|
_SafeNewSpace(data, capacity);
|
||||||
|
if (x < 0) {
|
||||||
|
isMinus = true;
|
||||||
|
x = -x;
|
||||||
|
}
|
||||||
|
while (x) {
|
||||||
|
data[length++] = x % 10000;
|
||||||
|
x /= 10000;
|
||||||
|
}
|
||||||
|
if (!length) {
|
||||||
|
length = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint::Bint(long long x)
|
||||||
|
: length(0)
|
||||||
|
{
|
||||||
|
_SafeNewSpace(data, capacity);
|
||||||
|
if (x < 0) {
|
||||||
|
isMinus = true;
|
||||||
|
x = -x;
|
||||||
|
}
|
||||||
|
while (x) {
|
||||||
|
data[length++] = static_cast<unsigned int>(x % 10000);
|
||||||
|
x /= 10000;
|
||||||
|
}
|
||||||
|
if (!length) {
|
||||||
|
length = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint::Bint(const size_t &capa)
|
||||||
|
: length(1)
|
||||||
|
{
|
||||||
|
while (capacity < capa) {
|
||||||
|
capacity <<= 1;
|
||||||
|
}
|
||||||
|
_SafeNewSpace(data, capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint::Bint(std::string x)
|
||||||
|
{
|
||||||
|
while (x[0] == '-') {
|
||||||
|
isMinus = !isMinus;
|
||||||
|
x.erase(0, 1);
|
||||||
|
}
|
||||||
|
while ((capacity << 2) <= x.length()) {
|
||||||
|
capacity <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SafeNewSpace(data, capacity);
|
||||||
|
|
||||||
|
size_t mid = x.length() >> 1;
|
||||||
|
for (size_t i = 0; i < mid; ++i) {
|
||||||
|
std::swap(x[i], x[x.length() - 1 - i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const static unsigned int pow10[4] = {1, 10, 100, 1000};
|
||||||
|
for (size_t i = 0; i < capacity; ++i) {
|
||||||
|
if ((i << 2) >= x.length()) {
|
||||||
|
length = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (size_t j = 0; j < 4; ++j) {
|
||||||
|
if ((i << 2) + j >= x.length()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (x[(i << 2) + j] > '9' || x[(i << 2) + j] < '0') {
|
||||||
|
throw BadCast();
|
||||||
|
}
|
||||||
|
data[i] = data[i] + (x[(i << 2) + j] - '0') * pow10[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint::Bint(const Bint &b)
|
||||||
|
: isMinus(b.isMinus), length(b.length), capacity(b.capacity)
|
||||||
|
{
|
||||||
|
_SafeNewSpace(data, capacity);
|
||||||
|
memcpy(data, b.data, sizeof(unsigned int) * capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint::Bint(Bint &&b) noexcept
|
||||||
|
: isMinus(b.isMinus), length(b.length), capacity(b.capacity)
|
||||||
|
{
|
||||||
|
data = b.data;
|
||||||
|
b.data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint &Bint::operator=(int x)
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(unsigned int) * capacity);
|
||||||
|
length = 0;
|
||||||
|
if (x < 0) {
|
||||||
|
isMinus = true;
|
||||||
|
x = -x;
|
||||||
|
}
|
||||||
|
while (x) {
|
||||||
|
data[length++] = x % 10000;
|
||||||
|
x /= 10000;
|
||||||
|
}
|
||||||
|
if (!length) {
|
||||||
|
length = 1;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint &Bint::operator=(long long x)
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(unsigned int) * capacity);
|
||||||
|
length = 0;
|
||||||
|
if (x < 0) {
|
||||||
|
isMinus = true;
|
||||||
|
x = -x;
|
||||||
|
}
|
||||||
|
while (x) {
|
||||||
|
data[length++] = static_cast<unsigned int>(x % 10000);
|
||||||
|
x /= 10000;
|
||||||
|
}
|
||||||
|
if (!length) {
|
||||||
|
length = 1;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint &Bint::operator=(const Bint &rhs)
|
||||||
|
{
|
||||||
|
if (this == &rhs) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
if (rhs.capacity > capacity) {
|
||||||
|
capacity = rhs.capacity;
|
||||||
|
_SafeNewSpace(data, capacity);
|
||||||
|
}
|
||||||
|
memcpy(data, rhs.data, sizeof(unsigned int) * rhs.capacity);
|
||||||
|
length = rhs.length;
|
||||||
|
isMinus = rhs.isMinus;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint &Bint::operator=(Bint &&rhs) noexcept
|
||||||
|
{
|
||||||
|
if (this == &rhs) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
capacity = rhs.capacity;
|
||||||
|
length = rhs.length;
|
||||||
|
isMinus = rhs.isMinus;
|
||||||
|
data = rhs.data;
|
||||||
|
rhs.data = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, Bint &b)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
is >> s;
|
||||||
|
b = Bint(s);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const Bint &b)
|
||||||
|
{
|
||||||
|
if (b.data == nullptr) {
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
if (b.isMinus && (b.length > 1 || b.data[0] != 0)) {
|
||||||
|
os << "-";
|
||||||
|
}
|
||||||
|
os << b.data[b.length - 1];
|
||||||
|
for (long long i = b.length - 2LL; i >= 0; --i) {
|
||||||
|
os << std::setw(4) << std::setfill('0') << b.data[i];
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint abs(const Bint &b)
|
||||||
|
{
|
||||||
|
Bint result(b);
|
||||||
|
result.isMinus = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint abs(Bint &&b)
|
||||||
|
{
|
||||||
|
b.isMinus = false;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
if (lhs.isMinus != rhs.isMinus) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < lhs.length; ++i) {
|
||||||
|
if (lhs.data[i] != rhs.data[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
if (lhs.isMinus != rhs.isMinus) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < lhs.length; ++i) {
|
||||||
|
if (lhs.data[i] != rhs.data[i]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
if (lhs.isMinus != rhs.isMinus) {
|
||||||
|
return !lhs.isMinus;
|
||||||
|
}
|
||||||
|
if (lhs.isMinus) {
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return lhs.length > rhs.length;
|
||||||
|
}
|
||||||
|
for (long long i = lhs.length - 1; i >= 0; --i) {
|
||||||
|
if (lhs.data[i] != rhs.data[i]) {
|
||||||
|
return lhs.data[i] > rhs.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return lhs.length < rhs.length;
|
||||||
|
}
|
||||||
|
for (long long i = lhs.length - 1; i >= 0; --i) {
|
||||||
|
if (lhs.data[i] != rhs.data[i]) {
|
||||||
|
return lhs.data[i] < rhs.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
return rhs < lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
if (lhs.isMinus != rhs.isMinus) {
|
||||||
|
return !lhs.isMinus;
|
||||||
|
}
|
||||||
|
if (lhs.isMinus) {
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return lhs.length > rhs.length;
|
||||||
|
}
|
||||||
|
for (long long i = lhs.length - 1; i >= 0; --i) {
|
||||||
|
if (lhs.data[i] != rhs.data[i]) {
|
||||||
|
return lhs.data[i] > rhs.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return lhs.length < rhs.length;
|
||||||
|
}
|
||||||
|
for (long long i = lhs.length - 1; i >= 0; --i) {
|
||||||
|
if (lhs.data[i] != rhs.data[i]) {
|
||||||
|
return lhs.data[i] < rhs.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
if (lhs.isMinus != rhs.isMinus) {
|
||||||
|
return lhs.isMinus;
|
||||||
|
}
|
||||||
|
if (lhs.isMinus) {
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return lhs.length < rhs.length;
|
||||||
|
}
|
||||||
|
for (long long i = lhs.length - 1; i >= 0; --i) {
|
||||||
|
if (lhs.data[i] != rhs.data[i]) {
|
||||||
|
return lhs.data[i] < rhs.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (lhs.length != rhs.length) {
|
||||||
|
return lhs.length > rhs.length;
|
||||||
|
}
|
||||||
|
for (long long i = lhs.length - 1; i >= 0; --i) {
|
||||||
|
if (lhs.data[i] != rhs.data[i]) {
|
||||||
|
return lhs.data[i] > rhs.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Bint operator+(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
if (lhs.isMinus == rhs.isMinus) {
|
||||||
|
size_t maxLen = std::max(lhs.length, rhs.length);
|
||||||
|
size_t expectLen = maxLen + 1;
|
||||||
|
Bint result(expectLen); // special constructor
|
||||||
|
for (size_t i = 0; i < maxLen; ++i) {
|
||||||
|
result.data[i] = lhs.data[i] + rhs.data[i];
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < maxLen; ++i) {
|
||||||
|
if (result.data[i] > 10000) {
|
||||||
|
result.data[i] -= 10000;
|
||||||
|
++result.data[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.length = result.data[maxLen] > 0 ? maxLen + 1 : maxLen;
|
||||||
|
result.isMinus = lhs.isMinus;
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
if (lhs.isMinus) {
|
||||||
|
return rhs - abs(lhs);
|
||||||
|
} else {
|
||||||
|
return lhs - abs(rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint operator-(const Bint &b)
|
||||||
|
{
|
||||||
|
Bint result(b);
|
||||||
|
result.isMinus = !result.isMinus;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint operator-(Bint &&b)
|
||||||
|
{
|
||||||
|
b.isMinus = !b.isMinus;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint operator-(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
if (lhs.isMinus == rhs.isMinus) {
|
||||||
|
if (lhs.isMinus) {
|
||||||
|
return -(abs(lhs) - abs(rhs));
|
||||||
|
} else {
|
||||||
|
if (lhs < rhs) {
|
||||||
|
return -(rhs - lhs);
|
||||||
|
}
|
||||||
|
Bint result(std::max(lhs.length, rhs.length));
|
||||||
|
for (size_t i = 0; i < lhs.length; ++i) {
|
||||||
|
result.data[i] = lhs.data[i] - rhs.data[i];
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < lhs.length; ++i) {
|
||||||
|
if (result.data[i] < 0) {
|
||||||
|
result.data[i] += 10000;
|
||||||
|
++result.data[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (result.length > 1 && result.data[result.length - 1] == 0) {
|
||||||
|
--result.length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return lhs + (-rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint operator*(const Bint &lhs, const Bint &rhs)
|
||||||
|
{
|
||||||
|
size_t expectLen = lhs.length + rhs.length + 2;
|
||||||
|
Bint result(expectLen);
|
||||||
|
for (size_t i = 0; i < lhs.length; ++i) {
|
||||||
|
for (size_t j = 0; j < rhs.length; ++j) {
|
||||||
|
long long tmp = result.data[i + j] + static_cast<long long>(lhs.data[i]) * rhs.data[j];
|
||||||
|
if (tmp >= 10000) {
|
||||||
|
result.data[i + j] = tmp % 10000;
|
||||||
|
result.data[i + j + 1] += static_cast<int>(tmp / 10000);
|
||||||
|
} else {
|
||||||
|
result.data[i + j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.length = lhs.length + rhs.length -1;
|
||||||
|
while (result.data[result.length] > 0) {
|
||||||
|
++result.length;
|
||||||
|
}
|
||||||
|
while (result.length > 1 && result.data[result.length - 1] == 0) {
|
||||||
|
--result.length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bint::~Bint()
|
||||||
|
{
|
||||||
|
if (data != nullptr) {
|
||||||
|
delete[] data;
|
||||||
|
data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
map/data/class-integer.hpp
Normal file
11
map/data/class-integer.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class Integer {
|
||||||
|
private:
|
||||||
|
int data;
|
||||||
|
public:
|
||||||
|
Integer(const int &value) : data(value) {}
|
||||||
|
Integer(const Integer &other) : data(other.data) {}
|
||||||
|
bool operator==(const Integer &t)
|
||||||
|
{
|
||||||
|
return data == t.data;
|
||||||
|
}
|
||||||
|
};
|
266
map/data/class-matrix.hpp
Normal file
266
map/data/class-matrix.hpp
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
#ifndef DIAMOND_MATRIX_HPP
|
||||||
|
#define DIAMOND_MATRIX_HPP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Diamond {
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
class Matrix {
|
||||||
|
protected:
|
||||||
|
size_t n_rows = 0;
|
||||||
|
size_t n_cols = 0;
|
||||||
|
std::vector<std::vector<_Td>> data;
|
||||||
|
class RowProxy {
|
||||||
|
std::vector<_Td> &row;
|
||||||
|
public:
|
||||||
|
RowProxy(std::vector<_Td> & _row) : row(_row) {}
|
||||||
|
_Td & operator[](const size_t &pos)
|
||||||
|
{
|
||||||
|
return row[pos];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class ConstRowProxy {
|
||||||
|
const std::vector<_Td> &row;
|
||||||
|
public:
|
||||||
|
ConstRowProxy(const std::vector<_Td> &_row) : row(_row) {}
|
||||||
|
const _Td & operator[](const size_t &pos) const
|
||||||
|
{
|
||||||
|
return row[pos];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
Matrix() {};
|
||||||
|
Matrix(const size_t &_n_rows, const size_t &_n_cols)
|
||||||
|
: n_rows(_n_rows), n_cols(_n_cols), data(std::vector<std::vector<_Td>>(n_rows, std::vector<_Td>(n_cols))) {}
|
||||||
|
Matrix(const size_t &_n_rows, const size_t &_n_cols, const _Td &fillValue)
|
||||||
|
: n_rows(_n_rows), n_cols(_n_cols), data(std::vector<std::vector<_Td>>(n_rows, std::vector<_Td>(n_cols, fillValue))) {}
|
||||||
|
Matrix(const Matrix<_Td> &mat)
|
||||||
|
: n_rows(mat.n_rows), n_cols(mat.n_cols), data(mat.data) {}
|
||||||
|
Matrix(Matrix<_Td> &&mat) noexcept
|
||||||
|
: n_rows(mat.n_rows), n_cols(mat.n_cols), data(mat.data) {}
|
||||||
|
Matrix<_Td> & operator=(const Matrix<_Td> &rhs)
|
||||||
|
{
|
||||||
|
this->n_rows = rhs.n_rows;
|
||||||
|
this->n_cols = rhs.n_cols;
|
||||||
|
this->data = rhs.data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Matrix<_Td> & operator=(Matrix<_Td> &&rhs)
|
||||||
|
{
|
||||||
|
this->n_rows = rhs.n_rows;
|
||||||
|
this->n_cols = rhs.n_cols;
|
||||||
|
this->data = rhs.data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
inline const size_t & RowSize() const
|
||||||
|
{
|
||||||
|
return n_rows;
|
||||||
|
}
|
||||||
|
inline const size_t & ColSize() const
|
||||||
|
{
|
||||||
|
return n_cols;
|
||||||
|
}
|
||||||
|
RowProxy operator[](const size_t &Kth)
|
||||||
|
{
|
||||||
|
return RowProxy(this->data[Kth]);
|
||||||
|
}
|
||||||
|
const ConstRowProxy operator[](const size_t &Kth) const
|
||||||
|
{
|
||||||
|
return ConstRowProxy(this->data[Kth]);
|
||||||
|
}
|
||||||
|
~Matrix() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sum of two matrics.
|
||||||
|
*/
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> operator+(const Matrix<_Td> &a, const Matrix<_Td> &b)
|
||||||
|
{
|
||||||
|
if (a.RowSize() != b.RowSize() || a.ColSize() != b.ColSize()) {
|
||||||
|
throw std::invalid_argument("different matrics\'s sizes");
|
||||||
|
}
|
||||||
|
Matrix<_Td> c(a.RowSize(), a.ColSize());
|
||||||
|
for (size_t i = 0; i < a.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < a.ColSize(); ++j) {
|
||||||
|
c[i][j] = a[i][j] + b[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> operator-(const Matrix<_Td> &a, const Matrix<_Td> &b)
|
||||||
|
{
|
||||||
|
if (a.RowSize() != b.RowSize() || a.ColSize() != b.ColSize()) {
|
||||||
|
throw std::invalid_argument("different matrics\'s sizes");
|
||||||
|
}
|
||||||
|
Matrix<_Td> c(a.RowSize(), a.ColSize());
|
||||||
|
for (size_t i = 0; i < a.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < a.ColSize(); ++j) {
|
||||||
|
c[i][j] = a[i][j] - b[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
template<typename _Td>
|
||||||
|
bool operator==(const Matrix<_Td> &a, const Matrix<_Td> &b)
|
||||||
|
{
|
||||||
|
if (a.RowSize() != b.RowSize() || a.ColSize() != b.ColSize()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < a.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < a.ColSize(); ++j) {
|
||||||
|
if (a[i][j] != b[i][j])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> operator-(const Matrix<_Td> &mat)
|
||||||
|
{
|
||||||
|
Matrix<_Td> result(mat.RowSize(), mat.ColSize());
|
||||||
|
for (size_t i = 0; i < mat.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < mat.ColSize(); ++j) {
|
||||||
|
result[i][j] = -mat[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> operator-(Matrix<_Td> &&mat)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < mat.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < mat.ColSize(); ++j) {
|
||||||
|
mat[i][j] = -mat[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication of two matrics.
|
||||||
|
*/
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> operator*(const Matrix<_Td> &a, const Matrix<_Td> &b)
|
||||||
|
{
|
||||||
|
if (a.ColSize() != b.RowSize()) {
|
||||||
|
throw std::invalid_argument("different matrics\'s sizes");
|
||||||
|
}
|
||||||
|
Matrix<_Td> c(a.RowSize(), b.ColSize(), 0);
|
||||||
|
for (size_t i = 0; i < a.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < b.ColSize(); ++j) {
|
||||||
|
for (size_t k = 0; k < a.ColSize(); ++k) {
|
||||||
|
c[i][j] += a[i][k] * b[k][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operations between a number and a matrix;
|
||||||
|
*/
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> operator*(const Matrix<_Td> &a, const _Td &b)
|
||||||
|
{
|
||||||
|
Matrix<_Td> c(a.RowSize(), a.ColSize());
|
||||||
|
for (size_t i = 0; i < a.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < a.ColSize(); ++j) {
|
||||||
|
c[i][j] = a[i][j] * b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> operator*(const _Td &b, const Matrix<_Td> &a)
|
||||||
|
{
|
||||||
|
Matrix<_Td> c(a.RowSize(), a.ColSize());
|
||||||
|
for (size_t i = 0; i < a.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < a.ColSize(); ++j) {
|
||||||
|
c[i][j] = a[i][j] * b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> operator/(const Matrix<_Td> &a, const double &b)
|
||||||
|
{
|
||||||
|
Matrix<_Td> c(a.RowSize(), a.ColSize());
|
||||||
|
for (size_t i = 0; i < a.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < a.ColSize(); ++j) {
|
||||||
|
c[i][j] = a[i][j] / b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> Transpose(const Matrix<_Td> &a)
|
||||||
|
{
|
||||||
|
Matrix<_Td> res(a.ColSize(), a.RowSize());
|
||||||
|
for (size_t i = 0; i < a.ColSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < a.RowSize(); ++j) {
|
||||||
|
res[i][j] = a[j][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
std::ostream & operator<<(std::ostream &stream, const Matrix<_Td> &mat)
|
||||||
|
{
|
||||||
|
std::ostream::fmtflags oldFlags = stream.flags();
|
||||||
|
stream.precision(8);
|
||||||
|
stream.setf(std::ios::fixed | std::ios::right);
|
||||||
|
|
||||||
|
stream << '\n';
|
||||||
|
for (size_t i = 0; i < mat.RowSize(); ++i) {
|
||||||
|
for (size_t j = 0; j < mat.ColSize(); ++j) {
|
||||||
|
stream << std::setw(15) << mat[i][j];
|
||||||
|
}
|
||||||
|
stream << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.flags(oldFlags);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> I(const size_t &n)
|
||||||
|
{
|
||||||
|
Matrix<_Td> res(n, n, 0);
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
res[i][i] = static_cast<_Td>(1);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Td>
|
||||||
|
Matrix<_Td> Pow(Matrix<_Td> A, size_t &b)
|
||||||
|
{
|
||||||
|
if (A.RowSize() != A.ColSize()) {
|
||||||
|
throw std::invalid_argument("The row size and column size are different.");
|
||||||
|
}
|
||||||
|
Matrix<_Td> result = I<_Td>(A.ColSize());
|
||||||
|
while (b > 0) {
|
||||||
|
if (b & static_cast<size_t>(1)) {
|
||||||
|
result = result * A;
|
||||||
|
}
|
||||||
|
A = A * A;
|
||||||
|
b = b >> static_cast<size_t>(1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
32
map/data/five.memcheck/answer.txt
Normal file
32
map/data/five.memcheck/answer.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
999 1999 2999 3999 4999 5999 6999 7999 8999 9999 SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU SJTU 10000
|
||||||
|
0
|
88
map/data/five.memcheck/code.cpp
Normal file
88
map/data/five.memcheck/code.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "map.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Integer {
|
||||||
|
public:
|
||||||
|
static int counter;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
Integer(int val) : val(val) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer(const Integer &rhs) {
|
||||||
|
val = rhs.val;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer& operator = (const Integer &rhs) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Integer() {
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int Integer::counter = 0;
|
||||||
|
|
||||||
|
class Compare {
|
||||||
|
public:
|
||||||
|
bool operator () (const Integer &lhs, const Integer &rhs) const {
|
||||||
|
return lhs.val < rhs.val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void tester(void) {
|
||||||
|
sjtu::map<Integer, std::string, Compare> map;
|
||||||
|
for (int i = 0; i < 10000; ++i) {
|
||||||
|
std::string string = "";
|
||||||
|
for (int number = i; number; number /= 10) {
|
||||||
|
char digit = '0' + number % 10;
|
||||||
|
string = digit + string;
|
||||||
|
}
|
||||||
|
if (i & 1) {
|
||||||
|
map[Integer(i)] = string;
|
||||||
|
auto result = map.insert(sjtu::pair<Integer, std::string>(Integer(i), string));
|
||||||
|
assert(!result.second);
|
||||||
|
} else {
|
||||||
|
auto result = map.insert(sjtu::pair<Integer, std::string>(Integer(i), string));
|
||||||
|
assert(result.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int counter = 0;
|
||||||
|
for (int time = 0; time <= 30; time++) {
|
||||||
|
sjtu::map<Integer, std::string, Compare>::const_iterator const_iterator;
|
||||||
|
const_iterator = map.cbegin();
|
||||||
|
while (const_iterator != map.cend()) {
|
||||||
|
const Integer integer(const_iterator->first);
|
||||||
|
if ((++counter) % 1000 == 0) {
|
||||||
|
std::cout << const_iterator->second << " ";
|
||||||
|
}
|
||||||
|
const_iterator++;
|
||||||
|
}
|
||||||
|
sjtu::map<Integer, std::string, Compare>::iterator iterator;
|
||||||
|
iterator = map.begin();
|
||||||
|
while (iterator != map.end()) {
|
||||||
|
const Integer integer(iterator->first);
|
||||||
|
std::string tmp = iterator->second;
|
||||||
|
iterator->second = "SJTU";
|
||||||
|
if ((++counter) % 1000 == 0) {
|
||||||
|
std::cout << iterator->second << " ";
|
||||||
|
}
|
||||||
|
iterator->second = tmp;
|
||||||
|
iterator++;
|
||||||
|
}
|
||||||
|
std::cout << map.size() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
std::ios::sync_with_stdio(false);
|
||||||
|
std::cin.tie(0);
|
||||||
|
std::cout.tie(0);
|
||||||
|
tester();
|
||||||
|
std::cout << Integer::counter << std::endl;
|
||||||
|
}
|
32
map/data/five/answer.txt
Normal file
32
map/data/five/answer.txt
Normal file
File diff suppressed because one or more lines are too long
88
map/data/five/code.cpp
Normal file
88
map/data/five/code.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "map.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Integer {
|
||||||
|
public:
|
||||||
|
static int counter;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
Integer(int val) : val(val) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer(const Integer &rhs) {
|
||||||
|
val = rhs.val;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer& operator = (const Integer &rhs) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Integer() {
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int Integer::counter = 0;
|
||||||
|
|
||||||
|
class Compare {
|
||||||
|
public:
|
||||||
|
bool operator () (const Integer &lhs, const Integer &rhs) const {
|
||||||
|
return lhs.val < rhs.val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void tester(void) {
|
||||||
|
sjtu::map<Integer, std::string, Compare> map;
|
||||||
|
for (int i = 0; i < 1000000; ++i) {
|
||||||
|
std::string string = "";
|
||||||
|
for (int number = i; number; number /= 10) {
|
||||||
|
char digit = '0' + number % 10;
|
||||||
|
string = digit + string;
|
||||||
|
}
|
||||||
|
if (i & 1) {
|
||||||
|
map[Integer(i)] = string;
|
||||||
|
auto result = map.insert(sjtu::pair<Integer, std::string>(Integer(i), string));
|
||||||
|
assert(!result.second);
|
||||||
|
} else {
|
||||||
|
auto result = map.insert(sjtu::pair<Integer, std::string>(Integer(i), string));
|
||||||
|
assert(result.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int counter = 0;
|
||||||
|
for (int time = 0; time <= 30; time++) {
|
||||||
|
sjtu::map<Integer, std::string, Compare>::const_iterator const_iterator;
|
||||||
|
const_iterator = map.cbegin();
|
||||||
|
while (const_iterator != map.cend()) {
|
||||||
|
const Integer integer(const_iterator->first);
|
||||||
|
if ((++counter) % 1000 == 0) {
|
||||||
|
std::cout << const_iterator->second << " ";
|
||||||
|
}
|
||||||
|
const_iterator++;
|
||||||
|
}
|
||||||
|
sjtu::map<Integer, std::string, Compare>::iterator iterator;
|
||||||
|
iterator = map.begin();
|
||||||
|
while (iterator != map.end()) {
|
||||||
|
const Integer integer(iterator->first);
|
||||||
|
std::string tmp = iterator->second;
|
||||||
|
iterator->second = "SJTU";
|
||||||
|
if ((++counter) % 1000 == 0) {
|
||||||
|
std::cout << iterator->second << " ";
|
||||||
|
}
|
||||||
|
iterator->second = tmp;
|
||||||
|
iterator++;
|
||||||
|
}
|
||||||
|
std::cout << map.size() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
std::ios::sync_with_stdio(false);
|
||||||
|
std::cin.tie(0);
|
||||||
|
std::cout.tie(0);
|
||||||
|
tester();
|
||||||
|
std::cout << Integer::counter << std::endl;
|
||||||
|
}
|
18
map/data/four.memcheck/answer.txt
Normal file
18
map/data/four.memcheck/answer.txt
Normal file
File diff suppressed because one or more lines are too long
241
map/data/four.memcheck/code.cpp
Normal file
241
map/data/four.memcheck/code.cpp
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
#include<iostream>
|
||||||
|
#include<cstdio>
|
||||||
|
#include<algorithm>
|
||||||
|
#include<cstring>
|
||||||
|
#include "map.hpp"
|
||||||
|
long long aa=13131,bb=5353,MOD=(long long)(1e9+7),now=1;
|
||||||
|
int rand()
|
||||||
|
{
|
||||||
|
for(int i=1;i<3;i++)
|
||||||
|
now=(now * aa + bb) % MOD;
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
class Key{
|
||||||
|
public:
|
||||||
|
int x;
|
||||||
|
Key(const Key &other):x(other.x){}
|
||||||
|
Key(int x):x(x){}
|
||||||
|
int num()const{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class Data{
|
||||||
|
public:
|
||||||
|
int* x;
|
||||||
|
Data():x(new int(1)){}
|
||||||
|
Data(int p):x(new int(p)){}
|
||||||
|
Data(const Data &other):x(new int(*(other.x))){}
|
||||||
|
~Data(){
|
||||||
|
delete x;
|
||||||
|
}
|
||||||
|
Data & operator = (const Data &other){
|
||||||
|
if(this == &other) return *this;
|
||||||
|
*x = *(other.x);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
int num()const{
|
||||||
|
return *x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct cmp{
|
||||||
|
bool operator ()(const Key &a,const Key &b)const{return a.x > b.x;}
|
||||||
|
};
|
||||||
|
sjtu::map<Key,Data,cmp> map;
|
||||||
|
int num = 5000;
|
||||||
|
void test_insert(){
|
||||||
|
puts("Test: insert");
|
||||||
|
std::cout<<"empty:"<<map.empty()<<std::endl;
|
||||||
|
std::cout<<"size:"<<map.size()<<std::endl;
|
||||||
|
int num = 1000;
|
||||||
|
for(int i=1;i<=num;i++)
|
||||||
|
{
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
map[Key(tmp)] = Data(rand());
|
||||||
|
}
|
||||||
|
for(int i=1;i<=num;i++)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
map.at(Key(rand() % 10000)) = Data(rand());
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
Key key(rand() % 10000);
|
||||||
|
Data data(rand());
|
||||||
|
sjtu::pair<sjtu::map<Key,Data,cmp>::iterator,bool> it = map.insert(sjtu::map<Key,Data,cmp>::value_type(key,data));
|
||||||
|
if (it.second) std::cout<<(it.first->second).num()<<' ';
|
||||||
|
else std::cout<<"0 ";
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
std::cout<<(map[Key(tmp)]).num()<<' ';
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
try{
|
||||||
|
std::cout<<(map.at(Key(tmp))).num()<<' ';
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void Print(){
|
||||||
|
for(sjtu::map<Key,Data,cmp>::const_iterator it(map.cbegin());it!=map.cend();++it)
|
||||||
|
std::cout<<(it->first).num()<<' '<<((*it).second).num()<<' ';
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_erase(){
|
||||||
|
puts("Test: erase");
|
||||||
|
for(int i=1;i<=100 && !map.empty();i++){
|
||||||
|
int p = rand() % map.size();
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it(map.begin());
|
||||||
|
while (p--) it++;
|
||||||
|
map.erase(it);
|
||||||
|
}
|
||||||
|
Print();
|
||||||
|
}
|
||||||
|
void test_const_at(){
|
||||||
|
puts("Test: const_at");
|
||||||
|
const sjtu::map<Key,Data,cmp> mm(map);
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
try{
|
||||||
|
std::cout<<(mm.at(Key(tmp))).num()<<' ';
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
try{
|
||||||
|
std::cout<<(mm[Key(tmp)]).num()<<' ';
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_count(){
|
||||||
|
puts("Test: count");
|
||||||
|
const sjtu::map<Key,Data,cmp> mm(map);
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
try{
|
||||||
|
std::cout<<(int)(mm.count(Key(tmp)))<<' ';
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_find(){
|
||||||
|
puts("Test: find");
|
||||||
|
const sjtu::map<Key,Data,cmp> mm(map);
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it(map.find(Key(tmp)));
|
||||||
|
if(it == map.end()) std::cout<<"END ";
|
||||||
|
else std::cout<<(it->first).num()<<' '<<(it->second).num()<<' ';
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
sjtu::map<Key,Data,cmp>::const_iterator it(mm.find(Key(tmp)));
|
||||||
|
if(it == mm.cend()) std::cout<<"END ";
|
||||||
|
else std::cout<<(it->first).num()<<' '<<(it->second).num()<<' ';
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_throw(){
|
||||||
|
puts("Test: throw");
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it;
|
||||||
|
it = map.begin();
|
||||||
|
try{
|
||||||
|
it--;
|
||||||
|
}catch(...){puts("OK1");}
|
||||||
|
try{
|
||||||
|
--it;
|
||||||
|
}catch(...){puts("OK2");}
|
||||||
|
it = map.end();
|
||||||
|
try{
|
||||||
|
it++;
|
||||||
|
}catch(...){puts("OK3");}
|
||||||
|
try{
|
||||||
|
++it;
|
||||||
|
}catch(...){puts("OK4");}
|
||||||
|
sjtu::map<Key,Data,cmp> new_map;
|
||||||
|
it = new_map.begin();
|
||||||
|
try{
|
||||||
|
it++;
|
||||||
|
}catch(...){puts("OK5");}
|
||||||
|
try{
|
||||||
|
++it;
|
||||||
|
}catch(...){puts("OK6");}
|
||||||
|
}
|
||||||
|
void test_const_throw(){
|
||||||
|
puts("Test: const_throw");
|
||||||
|
const sjtu::map<Key,Data,cmp> mm(map);
|
||||||
|
sjtu::map<Key,Data,cmp>::const_iterator it;
|
||||||
|
it = mm.cbegin();
|
||||||
|
try{
|
||||||
|
it--;
|
||||||
|
}catch(...){puts("OK7");}
|
||||||
|
try{
|
||||||
|
--it;
|
||||||
|
}catch(...){puts("OK8");}
|
||||||
|
it = map.cend();
|
||||||
|
try{
|
||||||
|
it++;
|
||||||
|
}catch(...){puts("OK9");}
|
||||||
|
try{
|
||||||
|
++it;
|
||||||
|
}catch(...){puts("OK10");}
|
||||||
|
const sjtu::map<Key,Data,cmp> new_map;
|
||||||
|
it = new_map.cbegin();
|
||||||
|
try{
|
||||||
|
it++;
|
||||||
|
}catch(...){puts("OK11");}
|
||||||
|
try{
|
||||||
|
++it;
|
||||||
|
}catch(...){puts("OK12");}
|
||||||
|
}
|
||||||
|
void test_copy()
|
||||||
|
{
|
||||||
|
puts("Test: copy");
|
||||||
|
sjtu::map<Key,Data,cmp> m1(map),m2;
|
||||||
|
m2 = map;
|
||||||
|
map.clear();
|
||||||
|
std::cout<<map.size()<<' '<<map.empty()<<std::endl;
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it1(m1.begin()),it2(m2.begin());
|
||||||
|
for(;it1!=m1.end() || it2!=m2.end();it1++,it2++)
|
||||||
|
{
|
||||||
|
std::cout<<(it1->first).num()<<' '<<(it1->second).num()<<' '<<(it2->first).num()<<' '<<(it2->second).num()<<' ';
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_iterator()
|
||||||
|
{
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it1 = map.begin();
|
||||||
|
for(int i=1;i<=3;i++)
|
||||||
|
{
|
||||||
|
int tmp = rand() % 5;
|
||||||
|
while (tmp--)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
sjtu::map<Key,Data,cmp>::const_iterator it2(it1++);
|
||||||
|
sjtu::map<Key,Data,cmp>::const_iterator it3(++it1);
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it4(it1++);
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it5(++it1);
|
||||||
|
std::cout<<(it2->first).num()<<' '<<(it2->second).num()<<std::endl;
|
||||||
|
std::cout<<(it3->first).num()<<' '<<(it3->second).num()<<std::endl;
|
||||||
|
std::cout<<(it4->first).num()<<' '<<(it4->second).num()<<std::endl;
|
||||||
|
std::cout<<((*it5).first).num()<<' '<<((*it5).second).num()<<std::endl;
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int main(){
|
||||||
|
test_insert();
|
||||||
|
test_erase();
|
||||||
|
test_const_at();
|
||||||
|
test_count();
|
||||||
|
test_find();
|
||||||
|
test_copy();
|
||||||
|
test_iterator();
|
||||||
|
}
|
18
map/data/four/answer.txt
Normal file
18
map/data/four/answer.txt
Normal file
File diff suppressed because one or more lines are too long
241
map/data/four/code.cpp
Normal file
241
map/data/four/code.cpp
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
#include<iostream>
|
||||||
|
#include<cstdio>
|
||||||
|
#include<algorithm>
|
||||||
|
#include<cstring>
|
||||||
|
#include "map.hpp"
|
||||||
|
long long aa=13131,bb=5353,MOD=(long long)(1e9+7),now=1;
|
||||||
|
int rand()
|
||||||
|
{
|
||||||
|
for(int i=1;i<3;i++)
|
||||||
|
now=(now * aa + bb) % MOD;
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
class Key{
|
||||||
|
public:
|
||||||
|
int x;
|
||||||
|
Key(const Key &other):x(other.x){}
|
||||||
|
Key(int x):x(x){}
|
||||||
|
int num()const{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class Data{
|
||||||
|
public:
|
||||||
|
int* x;
|
||||||
|
Data():x(new int(1)){}
|
||||||
|
Data(int p):x(new int(p)){}
|
||||||
|
Data(const Data &other):x(new int(*(other.x))){}
|
||||||
|
~Data(){
|
||||||
|
delete x;
|
||||||
|
}
|
||||||
|
Data & operator = (const Data &other){
|
||||||
|
if(this == &other) return *this;
|
||||||
|
*x = *(other.x);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
int num()const{
|
||||||
|
return *x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct cmp{
|
||||||
|
bool operator ()(const Key &a,const Key &b)const{return a.x > b.x;}
|
||||||
|
};
|
||||||
|
sjtu::map<Key,Data,cmp> map;
|
||||||
|
int num = 5000;
|
||||||
|
void test_insert(){
|
||||||
|
puts("Test: insert");
|
||||||
|
std::cout<<"empty:"<<map.empty()<<std::endl;
|
||||||
|
std::cout<<"size:"<<map.size()<<std::endl;
|
||||||
|
int num = 1000;
|
||||||
|
for(int i=1;i<=num;i++)
|
||||||
|
{
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
map[Key(tmp)] = Data(rand());
|
||||||
|
}
|
||||||
|
for(int i=1;i<=num;i++)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
map.at(Key(rand() % 10000)) = Data(rand());
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
Key key(rand() % 10000);
|
||||||
|
Data data(rand());
|
||||||
|
sjtu::pair<sjtu::map<Key,Data,cmp>::iterator,bool> it = map.insert(sjtu::map<Key,Data,cmp>::value_type(key,data));
|
||||||
|
if (it.second) std::cout<<(it.first->second).num()<<' ';
|
||||||
|
else std::cout<<"0 ";
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
std::cout<<(map[Key(tmp)]).num()<<' ';
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
try{
|
||||||
|
std::cout<<(map.at(Key(tmp))).num()<<' ';
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void Print(){
|
||||||
|
for(sjtu::map<Key,Data,cmp>::const_iterator it(map.cbegin());it!=map.cend();++it)
|
||||||
|
std::cout<<(it->first).num()<<' '<<((*it).second).num()<<' ';
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_erase(){
|
||||||
|
puts("Test: erase");
|
||||||
|
for(int i=1;i<=100 && !map.empty();i++){
|
||||||
|
int p = rand() % map.size();
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it(map.begin());
|
||||||
|
while (p--) it++;
|
||||||
|
map.erase(it);
|
||||||
|
}
|
||||||
|
Print();
|
||||||
|
}
|
||||||
|
void test_const_at(){
|
||||||
|
puts("Test: const_at");
|
||||||
|
const sjtu::map<Key,Data,cmp> mm(map);
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
try{
|
||||||
|
std::cout<<(mm.at(Key(tmp))).num()<<' ';
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
try{
|
||||||
|
std::cout<<(mm[Key(tmp)]).num()<<' ';
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_count(){
|
||||||
|
puts("Test: count");
|
||||||
|
const sjtu::map<Key,Data,cmp> mm(map);
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
try{
|
||||||
|
std::cout<<(int)(mm.count(Key(tmp)))<<' ';
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_find(){
|
||||||
|
puts("Test: find");
|
||||||
|
const sjtu::map<Key,Data,cmp> mm(map);
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it(map.find(Key(tmp)));
|
||||||
|
if(it == map.end()) std::cout<<"END ";
|
||||||
|
else std::cout<<(it->first).num()<<' '<<(it->second).num()<<' ';
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
for(int i=1;i<=num;i++){
|
||||||
|
int tmp(rand() % 10000);
|
||||||
|
sjtu::map<Key,Data,cmp>::const_iterator it(mm.find(Key(tmp)));
|
||||||
|
if(it == mm.cend()) std::cout<<"END ";
|
||||||
|
else std::cout<<(it->first).num()<<' '<<(it->second).num()<<' ';
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_throw(){
|
||||||
|
puts("Test: throw");
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it;
|
||||||
|
it = map.begin();
|
||||||
|
try{
|
||||||
|
it--;
|
||||||
|
}catch(...){puts("OK1");}
|
||||||
|
try{
|
||||||
|
--it;
|
||||||
|
}catch(...){puts("OK2");}
|
||||||
|
it = map.end();
|
||||||
|
try{
|
||||||
|
it++;
|
||||||
|
}catch(...){puts("OK3");}
|
||||||
|
try{
|
||||||
|
++it;
|
||||||
|
}catch(...){puts("OK4");}
|
||||||
|
sjtu::map<Key,Data,cmp> new_map;
|
||||||
|
it = new_map.begin();
|
||||||
|
try{
|
||||||
|
it++;
|
||||||
|
}catch(...){puts("OK5");}
|
||||||
|
try{
|
||||||
|
++it;
|
||||||
|
}catch(...){puts("OK6");}
|
||||||
|
}
|
||||||
|
void test_const_throw(){
|
||||||
|
puts("Test: const_throw");
|
||||||
|
const sjtu::map<Key,Data,cmp> mm(map);
|
||||||
|
sjtu::map<Key,Data,cmp>::const_iterator it;
|
||||||
|
it = mm.cbegin();
|
||||||
|
try{
|
||||||
|
it--;
|
||||||
|
}catch(...){puts("OK7");}
|
||||||
|
try{
|
||||||
|
--it;
|
||||||
|
}catch(...){puts("OK8");}
|
||||||
|
it = map.cend();
|
||||||
|
try{
|
||||||
|
it++;
|
||||||
|
}catch(...){puts("OK9");}
|
||||||
|
try{
|
||||||
|
++it;
|
||||||
|
}catch(...){puts("OK10");}
|
||||||
|
const sjtu::map<Key,Data,cmp> new_map;
|
||||||
|
it = new_map.cbegin();
|
||||||
|
try{
|
||||||
|
it++;
|
||||||
|
}catch(...){puts("OK11");}
|
||||||
|
try{
|
||||||
|
++it;
|
||||||
|
}catch(...){puts("OK12");}
|
||||||
|
}
|
||||||
|
void test_copy()
|
||||||
|
{
|
||||||
|
puts("Test: copy");
|
||||||
|
sjtu::map<Key,Data,cmp> m1(map),m2;
|
||||||
|
m2 = map;
|
||||||
|
map.clear();
|
||||||
|
std::cout<<map.size()<<' '<<map.empty()<<std::endl;
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it1(m1.begin()),it2(m2.begin());
|
||||||
|
for(;it1!=m1.end() || it2!=m2.end();it1++,it2++)
|
||||||
|
{
|
||||||
|
std::cout<<(it1->first).num()<<' '<<(it1->second).num()<<' '<<(it2->first).num()<<' '<<(it2->second).num()<<' ';
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
void test_iterator()
|
||||||
|
{
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it1 = map.begin();
|
||||||
|
for(int i=1;i<=3;i++)
|
||||||
|
{
|
||||||
|
int tmp = rand() % 5;
|
||||||
|
while (tmp--)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
sjtu::map<Key,Data,cmp>::const_iterator it2(it1++);
|
||||||
|
sjtu::map<Key,Data,cmp>::const_iterator it3(++it1);
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it4(it1++);
|
||||||
|
sjtu::map<Key,Data,cmp>::iterator it5(++it1);
|
||||||
|
std::cout<<(it2->first).num()<<' '<<(it2->second).num()<<std::endl;
|
||||||
|
std::cout<<(it3->first).num()<<' '<<(it3->second).num()<<std::endl;
|
||||||
|
std::cout<<(it4->first).num()<<' '<<(it4->second).num()<<std::endl;
|
||||||
|
std::cout<<((*it5).first).num()<<' '<<((*it5).second).num()<<std::endl;
|
||||||
|
}catch(...){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int main(){
|
||||||
|
test_insert();
|
||||||
|
test_erase();
|
||||||
|
test_const_at();
|
||||||
|
test_count();
|
||||||
|
test_find();
|
||||||
|
test_copy();
|
||||||
|
test_iterator();
|
||||||
|
}
|
5
map/data/one.memcheck/answer.txt
Normal file
5
map/data/one.memcheck/answer.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0
|
||||||
|
1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
|
||||||
|
2016 2015 2014 2013 2012 2011 2010 2009 2008 2007 2006 2005 2004 2003 2002 2001 2000 1999 1998 1997 1996 1995 1994 1993 1992 1991 1990 1989 1988 1987 1986 1985 1984 1983 1982 1981 1980 1979 1978 1977 1976 1975 1974 1973 1972 1971 1970 1969 1968 1967 1966 1965 1964 1963 1962 1961 1960 1959 1958 1957 1956 1955 1954 1953 1952 1951 1950 1949 1948 1947 1946 1945 1944 1943 1942 1941 1940 1939 1938 1937 1936 1935 1934 1933 1932 1931 1930 1929 1928 1927 1926 1925 1924 1923 1922 1921 1920 1919 1918 1917 1916 1915 1914 1913 1912 1911 1910 1909 1908 1907 1906 1905 1904 1903 1902 1901 1900 1899 1898 1897
|
||||||
|
10000
|
||||||
|
0
|
119
map/data/one.memcheck/code.cpp
Normal file
119
map/data/one.memcheck/code.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "map.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Integer {
|
||||||
|
public:
|
||||||
|
static int counter;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
Integer(int val) : val(val) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer(const Integer &rhs) {
|
||||||
|
val = rhs.val;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer& operator = (const Integer &rhs) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Integer() {
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int Integer::counter = 0;
|
||||||
|
|
||||||
|
class Compare {
|
||||||
|
public:
|
||||||
|
bool operator () (const Integer &lhs, const Integer &rhs) const {
|
||||||
|
return lhs.val < rhs.val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void tester(void) {
|
||||||
|
// test: constructor
|
||||||
|
sjtu::map<Integer, std::string, Compare> map;
|
||||||
|
// test: empty(), size()
|
||||||
|
assert(map.empty() && map.size() == 0);
|
||||||
|
// test: operator[], insert()
|
||||||
|
for (int i = 0; i < 10000; ++i) {
|
||||||
|
std::string string = "";
|
||||||
|
for (int number = i; number; number /= 10) {
|
||||||
|
char digit = '0' + number % 10;
|
||||||
|
string = digit + string;
|
||||||
|
}
|
||||||
|
if (i & 1) {
|
||||||
|
map[Integer(i)] = string;
|
||||||
|
auto result = map.insert(sjtu::pair<Integer, std::string>(Integer(i), string));
|
||||||
|
assert(!result.second);
|
||||||
|
} else {
|
||||||
|
auto result = map.insert(sjtu::pair<Integer, std::string>(Integer(i), string));
|
||||||
|
assert(result.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// test: count(), find(), erase()
|
||||||
|
for (int i = 0; i < 10000; ++i) {
|
||||||
|
if (i > 1896 && i <= 2016) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert(map.count(Integer(i)) == 1);
|
||||||
|
assert(map.find(Integer(i)) != map.end());
|
||||||
|
map.erase(map.find(Integer(i)));
|
||||||
|
}
|
||||||
|
// test: constructor, operator=, clear();
|
||||||
|
for (int i = 0; i < (int)map.size(); ++i) {
|
||||||
|
sjtu::map<Integer, std::string, Compare> copy(map);
|
||||||
|
map.clear();
|
||||||
|
std::cout << map.size() << " " << copy.size() << " ";
|
||||||
|
map = copy;
|
||||||
|
copy.clear();
|
||||||
|
std::cout << map.size() << " " << copy.size() << " ";
|
||||||
|
copy = map;
|
||||||
|
map.clear();
|
||||||
|
std::cout << map.size() << " " << copy.size() << " ";
|
||||||
|
map = copy;
|
||||||
|
copy.clear();
|
||||||
|
std::cout << map.size() << " " << copy.size() << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
// test: const_iterator, cbegin(), cend(), operator++, at()
|
||||||
|
sjtu::map<Integer, std::string, Compare>::const_iterator const_iterator;
|
||||||
|
const_iterator = map.cbegin();
|
||||||
|
while (const_iterator != map.cend()) {
|
||||||
|
const Integer integer(const_iterator->first);
|
||||||
|
const_iterator++;
|
||||||
|
std::cout << map.at(integer) << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
// test: iterator, operator--, operator->
|
||||||
|
sjtu::map<Integer, std::string, Compare>::iterator iterator;
|
||||||
|
iterator = map.end();
|
||||||
|
while (true) {
|
||||||
|
sjtu::map<Integer, std::string, Compare>::iterator peek = iterator;
|
||||||
|
if (peek == map.begin()) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::cout << (--iterator)->second << " ";
|
||||||
|
}
|
||||||
|
// test: erase()
|
||||||
|
while (map.begin() != map.end()) {
|
||||||
|
map.erase(map.begin());
|
||||||
|
}
|
||||||
|
assert(map.empty() && map.size() == 0);
|
||||||
|
// test: operator[]
|
||||||
|
for (int i = 0; i < 10000; ++i) {
|
||||||
|
std::cout << map[Integer(i)];
|
||||||
|
}
|
||||||
|
std::cout << map.size() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
tester();
|
||||||
|
std::cout << Integer::counter << std::endl;
|
||||||
|
}
|
5
map/data/one/answer.txt
Normal file
5
map/data/one/answer.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0 0 120 120 0
|
||||||
|
1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
|
||||||
|
2016 2015 2014 2013 2012 2011 2010 2009 2008 2007 2006 2005 2004 2003 2002 2001 2000 1999 1998 1997 1996 1995 1994 1993 1992 1991 1990 1989 1988 1987 1986 1985 1984 1983 1982 1981 1980 1979 1978 1977 1976 1975 1974 1973 1972 1971 1970 1969 1968 1967 1966 1965 1964 1963 1962 1961 1960 1959 1958 1957 1956 1955 1954 1953 1952 1951 1950 1949 1948 1947 1946 1945 1944 1943 1942 1941 1940 1939 1938 1937 1936 1935 1934 1933 1932 1931 1930 1929 1928 1927 1926 1925 1924 1923 1922 1921 1920 1919 1918 1917 1916 1915 1914 1913 1912 1911 1910 1909 1908 1907 1906 1905 1904 1903 1902 1901 1900 1899 1898 1897
|
||||||
|
100000
|
||||||
|
0
|
119
map/data/one/code.cpp
Normal file
119
map/data/one/code.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "map.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Integer {
|
||||||
|
public:
|
||||||
|
static int counter;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
Integer(int val) : val(val) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer(const Integer &rhs) {
|
||||||
|
val = rhs.val;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer& operator = (const Integer &rhs) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Integer() {
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int Integer::counter = 0;
|
||||||
|
|
||||||
|
class Compare {
|
||||||
|
public:
|
||||||
|
bool operator () (const Integer &lhs, const Integer &rhs) const {
|
||||||
|
return lhs.val < rhs.val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void tester(void) {
|
||||||
|
// test: constructor
|
||||||
|
sjtu::map<Integer, std::string, Compare> map;
|
||||||
|
// test: empty(), size()
|
||||||
|
assert(map.empty() && map.size() == 0);
|
||||||
|
// test: operator[], insert()
|
||||||
|
for (int i = 0; i < 100000; ++i) {
|
||||||
|
std::string string = "";
|
||||||
|
for (int number = i; number; number /= 10) {
|
||||||
|
char digit = '0' + number % 10;
|
||||||
|
string = digit + string;
|
||||||
|
}
|
||||||
|
if (i & 1) {
|
||||||
|
map[Integer(i)] = string;
|
||||||
|
auto result = map.insert(sjtu::pair<Integer, std::string>(Integer(i), string));
|
||||||
|
assert(!result.second);
|
||||||
|
} else {
|
||||||
|
auto result = map.insert(sjtu::pair<Integer, std::string>(Integer(i), string));
|
||||||
|
assert(result.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// test: count(), find(), erase()
|
||||||
|
for (int i = 0; i < 100000; ++i) {
|
||||||
|
if (i > 1896 && i <= 2016) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert(map.count(Integer(i)) == 1);
|
||||||
|
assert(map.find(Integer(i)) != map.end());
|
||||||
|
map.erase(map.find(Integer(i)));
|
||||||
|
}
|
||||||
|
// test: constructor, operator=, clear();
|
||||||
|
for (int i = 0; i < (int)map.size(); ++i) {
|
||||||
|
sjtu::map<Integer, std::string, Compare> copy(map);
|
||||||
|
map.clear();
|
||||||
|
std::cout << map.size() << " " << copy.size() << " ";
|
||||||
|
map = copy;
|
||||||
|
copy.clear();
|
||||||
|
std::cout << map.size() << " " << copy.size() << " ";
|
||||||
|
copy = map;
|
||||||
|
map.clear();
|
||||||
|
std::cout << map.size() << " " << copy.size() << " ";
|
||||||
|
map = copy;
|
||||||
|
copy.clear();
|
||||||
|
std::cout << map.size() << " " << copy.size() << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
// test: const_iterator, cbegin(), cend(), operator++, at()
|
||||||
|
sjtu::map<Integer, std::string, Compare>::const_iterator const_iterator;
|
||||||
|
const_iterator = map.cbegin();
|
||||||
|
while (const_iterator != map.cend()) {
|
||||||
|
const Integer integer(const_iterator->first);
|
||||||
|
const_iterator++;
|
||||||
|
std::cout << map.at(integer) << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
// test: iterator, operator--, operator->
|
||||||
|
sjtu::map<Integer, std::string, Compare>::iterator iterator;
|
||||||
|
iterator = map.end();
|
||||||
|
while (true) {
|
||||||
|
sjtu::map<Integer, std::string, Compare>::iterator peek = iterator;
|
||||||
|
if (peek == map.begin()) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::cout << (--iterator)->second << " ";
|
||||||
|
}
|
||||||
|
// test: erase()
|
||||||
|
while (map.begin() != map.end()) {
|
||||||
|
map.erase(map.begin());
|
||||||
|
}
|
||||||
|
assert(map.empty() && map.size() == 0);
|
||||||
|
// test: operator[]
|
||||||
|
for (int i = 0; i < 100000; ++i) {
|
||||||
|
std::cout << map[Integer(i)];
|
||||||
|
}
|
||||||
|
std::cout << map.size() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
tester();
|
||||||
|
std::cout << Integer::counter << std::endl;
|
||||||
|
}
|
15
map/data/three.memcheck/answer.txt
Normal file
15
map/data/three.memcheck/answer.txt
Normal file
File diff suppressed because one or more lines are too long
622
map/data/three.memcheck/code.cpp
Normal file
622
map/data/three.memcheck/code.cpp
Normal file
@ -0,0 +1,622 @@
|
|||||||
|
#include<iostream>
|
||||||
|
#include<map>
|
||||||
|
#include<ctime>
|
||||||
|
#include<queue>
|
||||||
|
#include<cmath>
|
||||||
|
#include<vector>
|
||||||
|
#include<cstdio>
|
||||||
|
#include<cstdlib>
|
||||||
|
#include<cstring>
|
||||||
|
#include<algorithm>
|
||||||
|
#include "map.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
bool check1(){ //insert by []
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
for(int i = 1; i <= 10000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q[a] = b; stdQ[a] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> :: value_type pp;
|
||||||
|
for(int i = 1; i <= 10000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q.insert(sjtu::map<int, int> :: value_type(a, b));
|
||||||
|
stdQ.insert(std::map<int, int> :: value_type(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q.begin(); it != Q.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check2(){//Q.insert
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
int num[51];
|
||||||
|
for(int i = 1; i <= 50; i++) num[i] =i;
|
||||||
|
for(int i = 1; i <= 100; i++) swap(num[rand() % 50 + 1], num[rand() % 50 + 1]);
|
||||||
|
for(int i = 1; i <= 50; i++) Q[num[i]] = rand();
|
||||||
|
int p = Q[6];
|
||||||
|
if(Q.insert(sjtu::map<int, int>::value_type(6, 9)).second) return 0;
|
||||||
|
it = Q.insert(sjtu::pair<int, int>(6, 9)).first;
|
||||||
|
if(it -> second != Q[6]) return 0;
|
||||||
|
|
||||||
|
it = Q.insert(sjtu::map<int, int>::value_type(325, 666)).first;
|
||||||
|
if(it -> first != 325 || it -> second != 666) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check3(){//find remove
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
int num[30001];
|
||||||
|
num[0] = 0;
|
||||||
|
for(int i = 1; i <= 30000; i++) num[i] = num[i - 1] + rand() % 325 + 1;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 30000; i++){
|
||||||
|
int t = rand();
|
||||||
|
stdQ[num[i]] = t; Q[num[i]] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 10325; i++){
|
||||||
|
it = Q.find(num[i]);
|
||||||
|
Q.erase(it);
|
||||||
|
stdit = stdQ.find(num[i]); stdQ.erase(stdit);
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check4(){//const_iterator
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
for(int i = 1; i <= 30000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q[a] = b; stdQ[a] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> :: iterator pt;
|
||||||
|
pt = Q.begin();
|
||||||
|
sjtu::map<int, int> :: const_iterator it(pt), itt;
|
||||||
|
std::map<int, int> :: const_iterator stdit;
|
||||||
|
stdit = stdQ.cbegin();
|
||||||
|
for(it = Q.cbegin(); it != Q.cend(); ++it){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.cend();
|
||||||
|
for(it = --Q.cend(); it != Q.cbegin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
itt = --Q.cend();
|
||||||
|
if(it == itt) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check5(){// insert && remove
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q[a] = b; stdQ[a] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(!stdQ.empty()){
|
||||||
|
if(Q.begin() -> first != stdQ.begin() -> first || Q.begin() -> second != stdQ.begin() -> second) return 0;
|
||||||
|
Q.erase(Q.begin());
|
||||||
|
stdQ.erase(stdQ.begin());
|
||||||
|
}
|
||||||
|
if(Q.begin() != Q.end()) return 0;
|
||||||
|
Q.clear(); stdQ.clear();
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
std::map<int, int> :: iterator stdit;
|
||||||
|
int num[3001], left[3001];
|
||||||
|
memset(left, 0, sizeof(left));
|
||||||
|
for(int i = 1; i <= 2000; i++) num[i] = i;
|
||||||
|
for(int i = 2001; i <= 3000; i++) num[i] = i - 2000;
|
||||||
|
for(int i = 1; i <= 6000; i++) swap(num[rand() % 3000 + 1], num[rand() % 3000 + 1]);
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
if(left[num[i]]){
|
||||||
|
if(stdQ.count(num[i])){
|
||||||
|
it = Q.find(num[i]); Q.erase(it);
|
||||||
|
stdit = stdQ.find(num[i]); stdQ.erase(stdit);
|
||||||
|
}
|
||||||
|
else cout << "fuck you!" << endl;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Q[num[i]] = num[i];
|
||||||
|
stdQ[num[i]] = num[i];
|
||||||
|
left[num[i]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); --it){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check6(){ // copy test
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q1;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
sjtu::map<int, int> :: value_type pp;
|
||||||
|
for(int i = 1; i <= 1000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q1.count(a)){
|
||||||
|
Q1.insert(sjtu::pair<int, int>(a, b));
|
||||||
|
stdQ.insert(std::map<int, int> :: value_type(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> Q(Q1);
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q.begin(); it != Q.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
while(!Q.empty()) Q.erase(Q.begin());
|
||||||
|
if(Q.size() != 0 || Q.begin() != Q.end()) return 0;
|
||||||
|
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q1.begin(); it != Q1.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q1.end(); it != Q1.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check7(){ //"=" operator
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q1;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
sjtu::map<int, int> :: value_type pp;
|
||||||
|
for(int i = 1; i <= 1000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q1.count(a)){
|
||||||
|
Q1.insert(sjtu::map<int, int> :: value_type(a, b));
|
||||||
|
stdQ.insert(std::map<int, int> :: value_type(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
Q = Q1;
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q.begin(); it != Q.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
while(!Q.empty()) Q.erase(Q.begin());
|
||||||
|
if(Q.size() != 0 || Q.begin() != Q.end()) return 0;
|
||||||
|
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q1.begin(); it != Q1.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q1.end(); it != Q1.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check8(){ // clear && insert
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
for(int i = 1; i <= 1000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!stdQ.count(a)){
|
||||||
|
if(Q.count(a)) return 0;
|
||||||
|
stdQ[a] = b; Q[a] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q.clear(); stdQ.clear();
|
||||||
|
if(Q.begin() != Q.end()) return 0;
|
||||||
|
if(Q.size()) return 0;
|
||||||
|
for(int i = 1; i <= 1000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!stdQ.count(a)){
|
||||||
|
if(Q.count(a)) return 0;
|
||||||
|
stdQ[a] = b;
|
||||||
|
Q.insert(sjtu::map<int, int> :: value_type(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
std::map<int, int> :: iterator stdit;
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q.begin(); it != Q.end(); ++it){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check9(){//just have fun!
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
sjtu::map<int, int> :: iterator fun;
|
||||||
|
sjtu::map<int, int> :: const_iterator cfun;
|
||||||
|
fun = Q.find(325); cfun = Q.find(325);
|
||||||
|
sjtu::map<int, int> P(Q);
|
||||||
|
sjtu::map<int, int> O;
|
||||||
|
O = Q;
|
||||||
|
Q.clear();
|
||||||
|
if(Q.size()) return 0;
|
||||||
|
Q[3] = 5; Q[6] = 10;
|
||||||
|
const sjtu::map<int, int> Q_const(Q);
|
||||||
|
sjtu::map<int, int> :: const_iterator cit;
|
||||||
|
Q_const.at(3);
|
||||||
|
cit = Q_const.find(3);
|
||||||
|
O = Q;
|
||||||
|
sjtu::map<int, int> :: iterator itQ, itO;
|
||||||
|
sjtu::map<int, int> :: const_iterator citQ, citO;
|
||||||
|
itQ = Q.end(); itO = O.end();
|
||||||
|
citQ = Q.cend(); citO = O.cend();
|
||||||
|
if(itQ == itO) return 0; if(citQ == citO) return 0;
|
||||||
|
if(!(itQ != itO)) return 0; if(!(citQ != citO)) return 0;
|
||||||
|
if(itQ == citO) return 0; if(itO == citQ) return 0;
|
||||||
|
if(!(itQ != citO)) return 0; if(!(itO != citQ)) return 0;
|
||||||
|
if(!(citQ == itQ)) return 0; if(citQ != itQ) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class node{
|
||||||
|
private:
|
||||||
|
int num;
|
||||||
|
public:
|
||||||
|
node() : num(0) {}
|
||||||
|
node(int p) : num(p) {}
|
||||||
|
bool operator <(const node &b) const{
|
||||||
|
return num < b.num;
|
||||||
|
}
|
||||||
|
bool operator !=(const node &b) const{
|
||||||
|
return num != b.num;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bool check10(){//class writen by users
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<node, int> Q;
|
||||||
|
std::map<node, int> stdQ;
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q[node(a)] = b; stdQ[node(a)] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(!stdQ.empty()){
|
||||||
|
if(Q.begin() -> first != stdQ.begin() -> first || Q.begin() -> second != stdQ.begin() -> second) return 0;
|
||||||
|
Q.erase(Q.begin());
|
||||||
|
stdQ.erase(stdQ.begin());
|
||||||
|
}
|
||||||
|
if(Q.begin() != Q.end()) return 0;
|
||||||
|
Q.clear(); stdQ.clear();
|
||||||
|
sjtu::map<node, int> :: iterator it;
|
||||||
|
std::map<node, int> :: iterator stdit;
|
||||||
|
int num[3001], left[3001];
|
||||||
|
memset(left, 0, sizeof(left));
|
||||||
|
for(int i = 1; i <= 2000; i++) num[i] = i;
|
||||||
|
for(int i = 2001; i <= 3000; i++) num[i] = i - 2000;
|
||||||
|
for(int i = 1; i <= 6000; i++) swap(num[rand() % 3000 + 1], num[rand() % 3000 + 1]);
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
if(left[num[i]]){
|
||||||
|
if(stdQ.count(node(num[i]))){
|
||||||
|
it = Q.find(node(num[i])); Q.erase(it);
|
||||||
|
stdit = stdQ.find(node(num[i])); stdQ.erase(stdit);
|
||||||
|
}
|
||||||
|
else cout << "fuck you!" << endl;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Q[node(num[i])] = num[i];
|
||||||
|
stdQ[node(num[i])] = num[i];
|
||||||
|
left[num[i]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); --it){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check11(){
|
||||||
|
sjtu::map<string, int> Q;
|
||||||
|
sjtu::map<string, int> :: iterator kit;
|
||||||
|
kit = Q.begin();
|
||||||
|
Q["aa"] = 5;
|
||||||
|
Q["bb"] = 16;
|
||||||
|
Q["cc"] = 20;
|
||||||
|
Q["lucky"] = 325;
|
||||||
|
Q["lwher"] = 666;
|
||||||
|
int p = Q.at("lwher");
|
||||||
|
if(p != 666) return 0;
|
||||||
|
p = Q.at("lucky");
|
||||||
|
if(p != 325) return 0;
|
||||||
|
int OK = 0;
|
||||||
|
try{
|
||||||
|
p = Q.at("dd");
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
sjtu::map<string, int> :: iterator it;
|
||||||
|
try{
|
||||||
|
it = Q.find("ok");
|
||||||
|
Q.erase(it);
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
try{
|
||||||
|
Q.erase(kit);
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
sjtu::map<string, int> Q2(Q);
|
||||||
|
try{
|
||||||
|
it = Q2.find("cc");
|
||||||
|
Q.erase(it);
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
it = Q.find("cc");
|
||||||
|
Q.erase(it);
|
||||||
|
try{
|
||||||
|
p = Q.at("cc");
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
const sjtu::map<string, int> Qc(Q);
|
||||||
|
try{
|
||||||
|
Qc["hehe"];
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
return OK == 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check12(){ // erase(it++)
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
int num[30001];
|
||||||
|
num[0] = 0;
|
||||||
|
for(int i = 1; i <= 30000; i++) num[i] = num[i - 1] + rand() % 325 + 1;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 30000; i++){
|
||||||
|
int t = rand();
|
||||||
|
stdQ[num[i]] = t; Q[num[i]] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 10325; i++){
|
||||||
|
it = Q.find(num[i]); Q.erase(it++);
|
||||||
|
stdit = stdQ.find(num[i]); stdQ.erase(stdit++);
|
||||||
|
if(it == Q.end()){
|
||||||
|
if(stdit != stdQ.end()) return 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(it -> first != stdit -> first) return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check13(){ // erase(it--)
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
int num[30001];
|
||||||
|
num[0] = 0;
|
||||||
|
for(int i = 1; i <= 30000; i++) num[i] = num[i - 1] + rand() % 325 + 1;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 30000; i++){
|
||||||
|
int t = rand();
|
||||||
|
stdQ[num[i]] = t; Q[num[i]] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 10325; i++){
|
||||||
|
it = Q.find(num[i]); if(it != Q.begin()) Q.erase(it--);
|
||||||
|
stdit = stdQ.find(num[i]); if(stdit != stdQ.begin()) stdQ.erase(stdit--);
|
||||||
|
if(it -> first != stdit -> first)return 0;
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check14(){// have fun
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
Q[3] = 25; Q[25] = 3; Q[1314] = 520; Q[3225] = 1; Q[10000] = 6666;
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
it = Q.find(3225);
|
||||||
|
Q.erase(--Q.end());
|
||||||
|
if(it -> first != 3225 || it -> second != 1) return 0;
|
||||||
|
Q.erase(Q.begin());
|
||||||
|
if(it -> first != 3225 || it -> second != 1) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*bool check100(){
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
Q[3] = 5;
|
||||||
|
Q[6] =10;
|
||||||
|
const sjtu::map<int, int> Q_const(Q);
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
it = Q.begin();
|
||||||
|
//it -> first++;
|
||||||
|
//it = Q_const.begin();
|
||||||
|
//it = Q_const.find(6);
|
||||||
|
sjtu::map<int, int> :: const_iterator cit;
|
||||||
|
cit = Q_const.find(3);
|
||||||
|
//cit -> second = 6;
|
||||||
|
//(cit -> second)++;
|
||||||
|
//cit -> fisrt = 10;
|
||||||
|
//++Q_const.at(6);
|
||||||
|
}*/
|
||||||
|
int A = 325, B = 2336, Last = 233, Mod = 1000007;
|
||||||
|
|
||||||
|
int Rand(){
|
||||||
|
return Last = (A * Last + B) % Mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
void easy_test(){
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
Q.clear();
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
int num[3001], left[3001];
|
||||||
|
memset(left, 0, sizeof(left));
|
||||||
|
for(int i = 1; i <= 2000; i++) num[i] = i;
|
||||||
|
for(int i = 2001; i <= 3000; i++) num[i] = i - 2000;
|
||||||
|
for(int i = 1; i <= 6000; i++) swap(num[Rand() % 3000 + 1], num[Rand() % 3000 + 1]);
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
if(left[num[i]]){
|
||||||
|
if(Q.count(num[i])){
|
||||||
|
it = Q.find(num[i]); Q.erase(it);
|
||||||
|
}
|
||||||
|
else cout << "fuck you!" << endl;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Q[num[i]] = num[i];
|
||||||
|
left[num[i]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(it = Q.begin(); it != Q.end(); ++it){
|
||||||
|
cout << it -> first << " " << it -> second << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
//freopen("testans_advance.out", "w", stdout);
|
||||||
|
srand(time(NULL));
|
||||||
|
easy_test();
|
||||||
|
if(!check1()) cout << "Test 1 Failed......" << endl; else cout << "Test 1 Passed!" << endl;
|
||||||
|
if(!check2()) cout << "Test 2 Failed......" << endl; else cout << "Test 2 Passed!" << endl;
|
||||||
|
if(!check3()) cout << "Test 3 Failed......" << endl; else cout << "Test 3 Passed!" << endl;
|
||||||
|
if(!check4()) cout << "Test 4 Failed......" << endl; else cout << "Test 4 Passed!" << endl;
|
||||||
|
if(!check5()) cout << "Test 5 Failed......" << endl; else cout << "Test 5 Passed!" << endl;
|
||||||
|
if(!check6()) cout << "Test 6 Failed......" << endl; else cout << "Test 6 Passed!" << endl;
|
||||||
|
if(!check7()) cout << "Test 7 Failed......" << endl; else cout << "Test 7 Passed!" << endl;
|
||||||
|
if(!check8()) cout << "Test 8 Failed......" << endl; else cout << "Test 8 Passed!" << endl;
|
||||||
|
if(!check9()) cout << "Test 9 Failed......" << endl; else cout << "Test 9 Passed!" << endl;
|
||||||
|
if(!check10()) cout << "Test 10 Failed......" << endl; else cout << "Test 10 Passed!" << endl;
|
||||||
|
if(!check11()) cout << "Test 11 Failed......" << endl; else cout << "Test 11 Passed!" << endl;
|
||||||
|
if(!check12()) cout << "Test 12 Failed......" << endl; else cout << "Test 12 Passed!" << endl;
|
||||||
|
if(!check13()) cout << "Test 13 Failed......" << endl; else cout << "Test 13 Passed!" << endl;
|
||||||
|
if(!check14()) cout << "Test 14 Failed......" << endl; else cout << "Test 14 Passed!" << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
15
map/data/three/answer.txt
Normal file
15
map/data/three/answer.txt
Normal file
File diff suppressed because one or more lines are too long
622
map/data/three/code.cpp
Normal file
622
map/data/three/code.cpp
Normal file
@ -0,0 +1,622 @@
|
|||||||
|
#include<iostream>
|
||||||
|
#include<map>
|
||||||
|
#include<ctime>
|
||||||
|
#include<queue>
|
||||||
|
#include<cmath>
|
||||||
|
#include<vector>
|
||||||
|
#include<cstdio>
|
||||||
|
#include<cstdlib>
|
||||||
|
#include<cstring>
|
||||||
|
#include<algorithm>
|
||||||
|
#include "map.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
bool check1(){ //insert by []
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
for(int i = 1; i <= 100000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q[a] = b; stdQ[a] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> :: value_type pp;
|
||||||
|
for(int i = 1; i <= 100000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q.insert(sjtu::map<int, int> :: value_type(a, b));
|
||||||
|
stdQ.insert(std::map<int, int> :: value_type(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q.begin(); it != Q.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check2(){//Q.insert
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
int num[51];
|
||||||
|
for(int i = 1; i <= 50; i++) num[i] =i;
|
||||||
|
for(int i = 1; i <= 100; i++) swap(num[rand() % 50 + 1], num[rand() % 50 + 1]);
|
||||||
|
for(int i = 1; i <= 50; i++) Q[num[i]] = rand();
|
||||||
|
int p = Q[6];
|
||||||
|
if(Q.insert(sjtu::map<int, int>::value_type(6, 9)).second) return 0;
|
||||||
|
it = Q.insert(sjtu::pair<int, int>(6, 9)).first;
|
||||||
|
if(it -> second != Q[6]) return 0;
|
||||||
|
|
||||||
|
it = Q.insert(sjtu::map<int, int>::value_type(325, 666)).first;
|
||||||
|
if(it -> first != 325 || it -> second != 666) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check3(){//find remove
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
int num[30001];
|
||||||
|
num[0] = 0;
|
||||||
|
for(int i = 1; i <= 30000; i++) num[i] = num[i - 1] + rand() % 325 + 1;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 30000; i++){
|
||||||
|
int t = rand();
|
||||||
|
stdQ[num[i]] = t; Q[num[i]] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 10325; i++){
|
||||||
|
it = Q.find(num[i]);
|
||||||
|
Q.erase(it);
|
||||||
|
stdit = stdQ.find(num[i]); stdQ.erase(stdit);
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check4(){//const_iterator
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
for(int i = 1; i <= 30000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q[a] = b; stdQ[a] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> :: iterator pt;
|
||||||
|
pt = Q.begin();
|
||||||
|
sjtu::map<int, int> :: const_iterator it(pt), itt;
|
||||||
|
std::map<int, int> :: const_iterator stdit;
|
||||||
|
stdit = stdQ.cbegin();
|
||||||
|
for(it = Q.cbegin(); it != Q.cend(); ++it){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.cend();
|
||||||
|
for(it = --Q.cend(); it != Q.cbegin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
itt = --Q.cend();
|
||||||
|
if(it == itt) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check5(){// insert && remove
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q[a] = b; stdQ[a] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(!stdQ.empty()){
|
||||||
|
if(Q.begin() -> first != stdQ.begin() -> first || Q.begin() -> second != stdQ.begin() -> second) return 0;
|
||||||
|
Q.erase(Q.begin());
|
||||||
|
stdQ.erase(stdQ.begin());
|
||||||
|
}
|
||||||
|
if(Q.begin() != Q.end()) return 0;
|
||||||
|
Q.clear(); stdQ.clear();
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
std::map<int, int> :: iterator stdit;
|
||||||
|
int num[3001], left[3001];
|
||||||
|
memset(left, 0, sizeof(left));
|
||||||
|
for(int i = 1; i <= 2000; i++) num[i] = i;
|
||||||
|
for(int i = 2001; i <= 3000; i++) num[i] = i - 2000;
|
||||||
|
for(int i = 1; i <= 6000; i++) swap(num[rand() % 3000 + 1], num[rand() % 3000 + 1]);
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
if(left[num[i]]){
|
||||||
|
if(stdQ.count(num[i])){
|
||||||
|
it = Q.find(num[i]); Q.erase(it);
|
||||||
|
stdit = stdQ.find(num[i]); stdQ.erase(stdit);
|
||||||
|
}
|
||||||
|
else cout << "fuck you!" << endl;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Q[num[i]] = num[i];
|
||||||
|
stdQ[num[i]] = num[i];
|
||||||
|
left[num[i]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); --it){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check6(){ // copy test
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q1;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
sjtu::map<int, int> :: value_type pp;
|
||||||
|
for(int i = 1; i <= 10000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q1.count(a)){
|
||||||
|
Q1.insert(sjtu::pair<int, int>(a, b));
|
||||||
|
stdQ.insert(std::map<int, int> :: value_type(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> Q(Q1);
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q.begin(); it != Q.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
while(!Q.empty()) Q.erase(Q.begin());
|
||||||
|
if(Q.size() != 0 || Q.begin() != Q.end()) return 0;
|
||||||
|
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q1.begin(); it != Q1.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q1.end(); it != Q1.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check7(){ //"=" operator
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q1;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
sjtu::map<int, int> :: value_type pp;
|
||||||
|
for(int i = 1; i <= 10000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q1.count(a)){
|
||||||
|
Q1.insert(sjtu::map<int, int> :: value_type(a, b));
|
||||||
|
stdQ.insert(std::map<int, int> :: value_type(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
Q = Q1;
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q.begin(); it != Q.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
while(!Q.empty()) Q.erase(Q.begin());
|
||||||
|
if(Q.size() != 0 || Q.begin() != Q.end()) return 0;
|
||||||
|
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q1.begin(); it != Q1.end(); it++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q1.end(); it != Q1.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check8(){ // clear && insert
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
for(int i = 1; i <= 1000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!stdQ.count(a)){
|
||||||
|
if(Q.count(a)) return 0;
|
||||||
|
stdQ[a] = b; Q[a] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q.clear(); stdQ.clear();
|
||||||
|
if(Q.begin() != Q.end()) return 0;
|
||||||
|
if(Q.size()) return 0;
|
||||||
|
for(int i = 1; i <= 1000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!stdQ.count(a)){
|
||||||
|
if(Q.count(a)) return 0;
|
||||||
|
stdQ[a] = b;
|
||||||
|
Q.insert(sjtu::map<int, int> :: value_type(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
std::map<int, int> :: iterator stdit;
|
||||||
|
stdit = stdQ.begin();
|
||||||
|
for(it = Q.begin(); it != Q.end(); ++it){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check9(){//just have fun!
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
sjtu::map<int, int> :: iterator fun;
|
||||||
|
sjtu::map<int, int> :: const_iterator cfun;
|
||||||
|
fun = Q.find(325); cfun = Q.find(325);
|
||||||
|
sjtu::map<int, int> P(Q);
|
||||||
|
sjtu::map<int, int> O;
|
||||||
|
O = Q;
|
||||||
|
Q.clear();
|
||||||
|
if(Q.size()) return 0;
|
||||||
|
Q[3] = 5; Q[6] = 10;
|
||||||
|
const sjtu::map<int, int> Q_const(Q);
|
||||||
|
sjtu::map<int, int> :: const_iterator cit;
|
||||||
|
Q_const.at(3);
|
||||||
|
cit = Q_const.find(3);
|
||||||
|
O = Q;
|
||||||
|
sjtu::map<int, int> :: iterator itQ, itO;
|
||||||
|
sjtu::map<int, int> :: const_iterator citQ, citO;
|
||||||
|
itQ = Q.end(); itO = O.end();
|
||||||
|
citQ = Q.cend(); citO = O.cend();
|
||||||
|
if(itQ == itO) return 0; if(citQ == citO) return 0;
|
||||||
|
if(!(itQ != itO)) return 0; if(!(citQ != citO)) return 0;
|
||||||
|
if(itQ == citO) return 0; if(itO == citQ) return 0;
|
||||||
|
if(!(itQ != citO)) return 0; if(!(itO != citQ)) return 0;
|
||||||
|
if(!(citQ == itQ)) return 0; if(citQ != itQ) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class node{
|
||||||
|
private:
|
||||||
|
int num;
|
||||||
|
public:
|
||||||
|
node() : num(0) {}
|
||||||
|
node(int p) : num(p) {}
|
||||||
|
bool operator <(const node &b) const{
|
||||||
|
return num < b.num;
|
||||||
|
}
|
||||||
|
bool operator !=(const node &b) const{
|
||||||
|
return num != b.num;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bool check10(){//class writen by users
|
||||||
|
int a, b;
|
||||||
|
sjtu::map<node, int> Q;
|
||||||
|
std::map<node, int> stdQ;
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
a = rand(); b = rand();
|
||||||
|
if(!Q.count(a)){
|
||||||
|
Q[node(a)] = b; stdQ[node(a)] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(!stdQ.empty()){
|
||||||
|
if(Q.begin() -> first != stdQ.begin() -> first || Q.begin() -> second != stdQ.begin() -> second) return 0;
|
||||||
|
Q.erase(Q.begin());
|
||||||
|
stdQ.erase(stdQ.begin());
|
||||||
|
}
|
||||||
|
if(Q.begin() != Q.end()) return 0;
|
||||||
|
Q.clear(); stdQ.clear();
|
||||||
|
sjtu::map<node, int> :: iterator it;
|
||||||
|
std::map<node, int> :: iterator stdit;
|
||||||
|
int num[3001], left[3001];
|
||||||
|
memset(left, 0, sizeof(left));
|
||||||
|
for(int i = 1; i <= 2000; i++) num[i] = i;
|
||||||
|
for(int i = 2001; i <= 3000; i++) num[i] = i - 2000;
|
||||||
|
for(int i = 1; i <= 6000; i++) swap(num[rand() % 3000 + 1], num[rand() % 3000 + 1]);
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
if(left[num[i]]){
|
||||||
|
if(stdQ.count(node(num[i]))){
|
||||||
|
it = Q.find(node(num[i])); Q.erase(it);
|
||||||
|
stdit = stdQ.find(node(num[i])); stdQ.erase(stdit);
|
||||||
|
}
|
||||||
|
else cout << "fuck you!" << endl;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Q[node(num[i])] = num[i];
|
||||||
|
stdQ[node(num[i])] = num[i];
|
||||||
|
left[num[i]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); --it){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check11(){
|
||||||
|
sjtu::map<string, int> Q;
|
||||||
|
sjtu::map<string, int> :: iterator kit;
|
||||||
|
kit = Q.begin();
|
||||||
|
Q["aa"] = 5;
|
||||||
|
Q["bb"] = 16;
|
||||||
|
Q["cc"] = 20;
|
||||||
|
Q["lucky"] = 325;
|
||||||
|
Q["lwher"] = 666;
|
||||||
|
int p = Q.at("lwher");
|
||||||
|
if(p != 666) return 0;
|
||||||
|
p = Q.at("lucky");
|
||||||
|
if(p != 325) return 0;
|
||||||
|
int OK = 0;
|
||||||
|
try{
|
||||||
|
p = Q.at("dd");
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
sjtu::map<string, int> :: iterator it;
|
||||||
|
try{
|
||||||
|
it = Q.find("ok");
|
||||||
|
Q.erase(it);
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
try{
|
||||||
|
Q.erase(kit);
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
sjtu::map<string, int> Q2(Q);
|
||||||
|
try{
|
||||||
|
it = Q2.find("cc");
|
||||||
|
Q.erase(it);
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
it = Q.find("cc");
|
||||||
|
Q.erase(it);
|
||||||
|
try{
|
||||||
|
p = Q.at("cc");
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
const sjtu::map<string, int> Qc(Q);
|
||||||
|
try{
|
||||||
|
Qc["hehe"];
|
||||||
|
}
|
||||||
|
catch(...) {OK++;}
|
||||||
|
return OK == 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check12(){ // erase(it++)
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
int num[30001];
|
||||||
|
num[0] = 0;
|
||||||
|
for(int i = 1; i <= 30000; i++) num[i] = num[i - 1] + rand() % 325 + 1;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 30000; i++){
|
||||||
|
int t = rand();
|
||||||
|
stdQ[num[i]] = t; Q[num[i]] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 10325; i++){
|
||||||
|
it = Q.find(num[i]); Q.erase(it++);
|
||||||
|
stdit = stdQ.find(num[i]); stdQ.erase(stdit++);
|
||||||
|
if(it == Q.end()){
|
||||||
|
if(stdit != stdQ.end()) return 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(it -> first != stdit -> first) return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check13(){ // erase(it--)
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
std::map<int, int> stdQ;
|
||||||
|
int num[30001];
|
||||||
|
num[0] = 0;
|
||||||
|
for(int i = 1; i <= 30000; i++) num[i] = num[i - 1] + rand() % 325 + 1;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 30000; i++){
|
||||||
|
int t = rand();
|
||||||
|
stdQ[num[i]] = t; Q[num[i]] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
std::map<int, int>::iterator stdit;
|
||||||
|
for(int i = 1; i <= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]);
|
||||||
|
for(int i = 1; i <= 10325; i++){
|
||||||
|
it = Q.find(num[i]); if(it != Q.begin()) Q.erase(it--);
|
||||||
|
stdit = stdQ.find(num[i]); if(stdit != stdQ.begin()) stdQ.erase(stdit--);
|
||||||
|
if(it -> first != stdit -> first)return 0;
|
||||||
|
}
|
||||||
|
if(Q.size() != stdQ.size()) return 0;
|
||||||
|
it = Q.begin();
|
||||||
|
for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
stdit = --stdQ.end();
|
||||||
|
for(it = --Q.end(); it != Q.begin(); it--){
|
||||||
|
if(stdit -> first != it -> first) return 0;
|
||||||
|
if(stdit -> second != (*it).second) return 0;
|
||||||
|
stdit--;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check14(){// have fun
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
Q[3] = 25; Q[25] = 3; Q[1314] = 520; Q[3225] = 1; Q[10000] = 6666;
|
||||||
|
sjtu::map<int, int>::iterator it;
|
||||||
|
it = Q.find(3225);
|
||||||
|
Q.erase(--Q.end());
|
||||||
|
if(it -> first != 3225 || it -> second != 1) return 0;
|
||||||
|
Q.erase(Q.begin());
|
||||||
|
if(it -> first != 3225 || it -> second != 1) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*bool check100(){
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
Q[3] = 5;
|
||||||
|
Q[6] =10;
|
||||||
|
const sjtu::map<int, int> Q_const(Q);
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
it = Q.begin();
|
||||||
|
//it -> first++;
|
||||||
|
//it = Q_const.begin();
|
||||||
|
//it = Q_const.find(6);
|
||||||
|
sjtu::map<int, int> :: const_iterator cit;
|
||||||
|
cit = Q_const.find(3);
|
||||||
|
//cit -> second = 6;
|
||||||
|
//(cit -> second)++;
|
||||||
|
//cit -> fisrt = 10;
|
||||||
|
//++Q_const.at(6);
|
||||||
|
}*/
|
||||||
|
int A = 325, B = 2336, Last = 233, Mod = 1000007;
|
||||||
|
|
||||||
|
int Rand(){
|
||||||
|
return Last = (A * Last + B) % Mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
void easy_test(){
|
||||||
|
sjtu::map<int, int> Q;
|
||||||
|
Q.clear();
|
||||||
|
sjtu::map<int, int> :: iterator it;
|
||||||
|
int num[3001], left[3001];
|
||||||
|
memset(left, 0, sizeof(left));
|
||||||
|
for(int i = 1; i <= 2000; i++) num[i] = i;
|
||||||
|
for(int i = 2001; i <= 3000; i++) num[i] = i - 2000;
|
||||||
|
for(int i = 1; i <= 6000; i++) swap(num[Rand() % 3000 + 1], num[Rand() % 3000 + 1]);
|
||||||
|
for(int i = 1; i <= 3000; i++){
|
||||||
|
if(left[num[i]]){
|
||||||
|
if(Q.count(num[i])){
|
||||||
|
it = Q.find(num[i]); Q.erase(it);
|
||||||
|
}
|
||||||
|
else cout << "fuck you!" << endl;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Q[num[i]] = num[i];
|
||||||
|
left[num[i]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(it = Q.begin(); it != Q.end(); ++it){
|
||||||
|
cout << it -> first << " " << it -> second << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
//freopen("testans_advance.out", "w", stdout);
|
||||||
|
srand(time(NULL));
|
||||||
|
easy_test();
|
||||||
|
if(!check1()) cout << "Test 1 Failed......" << endl; else cout << "Test 1 Passed!" << endl;
|
||||||
|
if(!check2()) cout << "Test 2 Failed......" << endl; else cout << "Test 2 Passed!" << endl;
|
||||||
|
if(!check3()) cout << "Test 3 Failed......" << endl; else cout << "Test 3 Passed!" << endl;
|
||||||
|
if(!check4()) cout << "Test 4 Failed......" << endl; else cout << "Test 4 Passed!" << endl;
|
||||||
|
if(!check5()) cout << "Test 5 Failed......" << endl; else cout << "Test 5 Passed!" << endl;
|
||||||
|
if(!check6()) cout << "Test 6 Failed......" << endl; else cout << "Test 6 Passed!" << endl;
|
||||||
|
if(!check7()) cout << "Test 7 Failed......" << endl; else cout << "Test 7 Passed!" << endl;
|
||||||
|
if(!check8()) cout << "Test 8 Failed......" << endl; else cout << "Test 8 Passed!" << endl;
|
||||||
|
if(!check9()) cout << "Test 9 Failed......" << endl; else cout << "Test 9 Passed!" << endl;
|
||||||
|
if(!check10()) cout << "Test 10 Failed......" << endl; else cout << "Test 10 Passed!" << endl;
|
||||||
|
if(!check11()) cout << "Test 11 Failed......" << endl; else cout << "Test 11 Passed!" << endl;
|
||||||
|
if(!check12()) cout << "Test 12 Failed......" << endl; else cout << "Test 12 Passed!" << endl;
|
||||||
|
if(!check13()) cout << "Test 13 Failed......" << endl; else cout << "Test 13 Passed!" << endl;
|
||||||
|
if(!check14()) cout << "Test 14 Failed......" << endl; else cout << "Test 14 Passed!" << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
11
map/data/two.memcheck/answer.txt
Normal file
11
map/data/two.memcheck/answer.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Test 1: Operator [] & Iterator traverse testing... PASSED
|
||||||
|
Test 2: Insertion function testing... PASSED
|
||||||
|
Test 3: Deletion & Find function testing... PASSED
|
||||||
|
Test 4: Error throwing A - Invalid Iterator testing... PASSED
|
||||||
|
Test 5: Error throwing B - Invalid Const_Iterator testing... PASSED
|
||||||
|
Test 6: Error throwing C - Invalid Index testing... PASSED
|
||||||
|
Test 7: Copy constructure testing... PASSED
|
||||||
|
Test 8: Operator = testing... PASSED
|
||||||
|
Test 9: At function testing... PASSED
|
||||||
|
Test 10: Objects' independence testing... PASSED
|
||||||
|
Test 11: Comprehensive testing... PASSED
|
622
map/data/two.memcheck/code.cpp
Normal file
622
map/data/two.memcheck/code.cpp
Normal file
@ -0,0 +1,622 @@
|
|||||||
|
#include <fstream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <ctime>
|
||||||
|
#include "exceptions.hpp"
|
||||||
|
#include "map.hpp"
|
||||||
|
|
||||||
|
const int MAXN = 5001;
|
||||||
|
|
||||||
|
enum Color{
|
||||||
|
Red, Green, Blue, Normal
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestCore{
|
||||||
|
private:
|
||||||
|
const char *title;
|
||||||
|
const int id, total;
|
||||||
|
long dfn;
|
||||||
|
int counter, enter;
|
||||||
|
public:
|
||||||
|
TestCore(const char *title, const int &id, const int &total) : title(title), id(id), total(total), dfn(clock()), counter(0), enter(0) {
|
||||||
|
}
|
||||||
|
void init() {
|
||||||
|
static char tmp[200];
|
||||||
|
sprintf(tmp, "Test %d: %-55s", id, title);
|
||||||
|
printf("%-65s", tmp);
|
||||||
|
}
|
||||||
|
void showMessage(const char *s, const Color &c = Normal) {
|
||||||
|
}
|
||||||
|
void showProgress() {
|
||||||
|
}
|
||||||
|
void pass() {
|
||||||
|
showMessage("PASSED", Green);
|
||||||
|
printf("PASSED");
|
||||||
|
}
|
||||||
|
void fail() {
|
||||||
|
showMessage("FAILED", Red);
|
||||||
|
printf("FAILED");
|
||||||
|
}
|
||||||
|
~TestCore() {
|
||||||
|
puts("");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IntA{
|
||||||
|
public:
|
||||||
|
static int counter;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
IntA(int val) : val(val) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntA(const IntA &rhs) {
|
||||||
|
val = rhs.val;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntA & operator = (const IntA &rhs) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ==(const IntA &rhs) {
|
||||||
|
return val == rhs.val;
|
||||||
|
}
|
||||||
|
friend bool operator < (const IntA &lhs, const IntA &rhs) {
|
||||||
|
return lhs.val > rhs.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
~IntA() {
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int IntA::counter = 0;
|
||||||
|
|
||||||
|
class IntB{
|
||||||
|
public:
|
||||||
|
int *val;
|
||||||
|
explicit IntB(int val = 0) : val(new int(val)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
IntB(const IntB &rhs) {
|
||||||
|
val = new int(*rhs.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
IntB & operator =(const IntB &rhs) {
|
||||||
|
if (this == &rhs) return *this;
|
||||||
|
delete this->val;
|
||||||
|
val = new int(*rhs.val);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator !=(const IntB &rhs) const {
|
||||||
|
return *val != *rhs.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ==(const IntB &rhs) const {
|
||||||
|
return *val == *rhs.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
~IntB() {
|
||||||
|
delete this->val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Compare{
|
||||||
|
bool operator ()(const IntA &a, const IntA &b)const {
|
||||||
|
return a.val > b.val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::vector<int> & generator(int n = MAXN) {
|
||||||
|
static std::vector<int> raw;
|
||||||
|
raw.clear();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
raw.push_back(rand());
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester1() {
|
||||||
|
TestCore console("Operator [] & Iterator traverse testing...", 1, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap[x] = tmp;
|
||||||
|
srcmap[x] = tmp;
|
||||||
|
//printf("insert(%d, %d)\n", x, tmp.val);
|
||||||
|
for (int c = 0; c < 10; c++) {
|
||||||
|
int p = rand() % (i + 1);
|
||||||
|
if (stdmap[ret[p]] != srcmap[ret[p]]) {
|
||||||
|
//std::cerr << ret[p] << " ";
|
||||||
|
//std::cerr << stdmap[ret[p]] << " " << srcmap[ret[p]] << std::endl;
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.cbegin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester2() {
|
||||||
|
TestCore console("Insertion function testing...", 2, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
for (int c = 0; c < 10; c++) {
|
||||||
|
int p = rand() % (i + 1);
|
||||||
|
if (stdmap[ret[p]] != srcmap[ret[p]]) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.begin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester3() {
|
||||||
|
TestCore console("Deletion & Find function testing...", 3, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
std::random_shuffle(ret.begin(), ret.end());
|
||||||
|
for (auto x : ret) {
|
||||||
|
if (stdmap.find(x) != stdmap.end()) {
|
||||||
|
srcmap.erase(srcmap.find(x));
|
||||||
|
stdmap.erase(stdmap.find(x));
|
||||||
|
}
|
||||||
|
for (int c = 0; c < 10; c++) {
|
||||||
|
int p = rand() % ret.size();
|
||||||
|
if (stdmap.find(ret[p]) != stdmap.end()) {
|
||||||
|
if (stdmap[ret[p]] != srcmap[ret[p]]) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester4() {
|
||||||
|
TestCore console("Error throwing A - Invalid Iterator testing...", 4, 0);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
++srcmap.end();
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
--srcmap.begin();
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.end()++;
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.begin()--;
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
console.pass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester5() {
|
||||||
|
TestCore console("Error throwing B - Invalid Const_Iterator testing...", 5, 0);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
++srcmap.cend();
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
--srcmap.cbegin();
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.cend()++;
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.cbegin()--;
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
console.pass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester6() {
|
||||||
|
TestCore console("Error throwing C - Invalid Index testing...", 6, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (auto x : ret) {
|
||||||
|
srcmap[x] = IntB(rand());
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.at(IntA(-1)) = IntB(2);
|
||||||
|
} catch (...) {
|
||||||
|
console.pass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester7() {
|
||||||
|
const int MAXC = MAXN / 2;
|
||||||
|
TestCore console("Copy constructure testing...", 7, MAXN + MAXC + 2 * (MAXN - MAXC));
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
std::map<IntA, IntB, Compare> tmp1(stdmap);
|
||||||
|
sjtu::map<IntA, IntB, Compare> tmp2(srcmap);
|
||||||
|
std::random_shuffle(ret.begin(), ret.end());
|
||||||
|
for (int i = 0; i < MAXC; i++) {
|
||||||
|
if (stdmap.find(ret[i]) != stdmap.end()) {
|
||||||
|
srcmap.erase(srcmap.find(ret[i]));
|
||||||
|
stdmap.erase(stdmap.find(ret[i]));
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.begin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
itB = tmp2.begin();
|
||||||
|
for (auto itA = tmp1.begin(); itA != tmp1.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester8() {
|
||||||
|
const int MAXC = MAXN / 2;
|
||||||
|
TestCore console("Operator = testing...", 8, MAXN + MAXC + 2 * (MAXN - MAXC));
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
std::map<IntA, IntB, Compare> tmp1;
|
||||||
|
tmp1 = stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> tmp2;
|
||||||
|
tmp2 = srcmap;
|
||||||
|
std::random_shuffle(ret.begin(), ret.end());
|
||||||
|
for (int i = 0; i < MAXC; i++) {
|
||||||
|
if (stdmap.find(ret[i]) != stdmap.end()) {
|
||||||
|
srcmap.erase(srcmap.find(ret[i]));
|
||||||
|
stdmap.erase(stdmap.find(ret[i]));
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.cbegin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
itB = tmp2.cbegin();
|
||||||
|
for (auto itA = tmp1.begin(); itA != tmp1.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester9() {
|
||||||
|
TestCore console("At function testing...", 9, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap[x] = tmp;
|
||||||
|
srcmap[x] = tmp;
|
||||||
|
for (int c = 0; c < 10; c++) {
|
||||||
|
int p = rand() % (i + 1);
|
||||||
|
if (stdmap.at(ret[p]) != srcmap.at(ret[p])) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmp = IntB(rand());
|
||||||
|
stdmap.at(ret[p]) = tmp;
|
||||||
|
srcmap.at(ret[p]) = tmp;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.cbegin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester10() {
|
||||||
|
TestCore console("Objects' independence testing...", 10, 6 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
std::map<IntA, IntB, Compare> std1(stdmap), std2;
|
||||||
|
std2 = std1 = std1;
|
||||||
|
sjtu::map<IntA, IntB, Compare> src1(srcmap), src2;
|
||||||
|
src2 = src1 = src1;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
if (stdmap.find(ret[i]) != stdmap.end()) {
|
||||||
|
srcmap.erase(srcmap.find(ret[i]));
|
||||||
|
stdmap.erase(stdmap.find(ret[i]));
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
ret = generator(MAXN);
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
std1.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
src1.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto itB = srcmap.begin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
itB = src1.begin();
|
||||||
|
for (auto itA = std1.begin(); itA != std1.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
itB = src2.begin();
|
||||||
|
for (auto itA = std2.begin(); itA != std2.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester11() {
|
||||||
|
const int MAXN = 10001;
|
||||||
|
TestCore console("Comprehensive testing...", 11, 3 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0, cnt = 0; i < (int)ret.size(); i++, cnt++) {
|
||||||
|
int tmp = rand();
|
||||||
|
auto retA = stdmap.insert(std::map<IntA, IntB, Compare>::value_type(IntA(ret[i]), IntB(tmp)));
|
||||||
|
auto retB = srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(IntA(ret[i]), IntB(tmp)));
|
||||||
|
console.showProgress();
|
||||||
|
if (!retA.second) {
|
||||||
|
cnt--;
|
||||||
|
ret[i] = -1;
|
||||||
|
console.showProgress();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (rand() % 100 < 12 && cnt > 0) {
|
||||||
|
int p = 0;
|
||||||
|
while (ret[p] < 0) {
|
||||||
|
p = rand() % (i + 1);
|
||||||
|
}
|
||||||
|
stdmap.erase(stdmap.find(ret[p]));
|
||||||
|
srcmap.erase(srcmap.find(ret[p]));
|
||||||
|
ret[p] = -1;
|
||||||
|
cnt++;
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
if (stdmap.size() != srcmap.size()) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto itB = srcmap.cbegin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto stdtmp(stdmap);
|
||||||
|
const auto srctmp(srcmap);
|
||||||
|
|
||||||
|
std::map<IntA, IntB, Compare>::const_iterator citA = stdtmp.cbegin();
|
||||||
|
sjtu::map<IntA, IntB, Compare>::const_iterator citB = srctmp.cbegin();
|
||||||
|
|
||||||
|
stdtmp.size();
|
||||||
|
srctmp.size();
|
||||||
|
|
||||||
|
for (auto x : ret) {
|
||||||
|
if (x >= 0) {
|
||||||
|
if (stdmap.at(x) != srcmap.at(x)) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (srctmp.count(x) == 0) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
#ifdef SPECIAL
|
||||||
|
puts("AATree-Map Checker Version 1.2");
|
||||||
|
#endif
|
||||||
|
tester1();
|
||||||
|
tester2();
|
||||||
|
tester3();
|
||||||
|
tester4();
|
||||||
|
tester5();
|
||||||
|
tester6();
|
||||||
|
tester7();
|
||||||
|
tester8();
|
||||||
|
tester9();
|
||||||
|
tester10();
|
||||||
|
tester11();
|
||||||
|
return 0;
|
||||||
|
}
|
11
map/data/two/answer.txt
Normal file
11
map/data/two/answer.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Test 1: Operator [] & Iterator traverse testing... PASSED
|
||||||
|
Test 2: Insertion function testing... PASSED
|
||||||
|
Test 3: Deletion & Find function testing... PASSED
|
||||||
|
Test 4: Error throwing A - Invalid Iterator testing... PASSED
|
||||||
|
Test 5: Error throwing B - Invalid Const_Iterator testing... PASSED
|
||||||
|
Test 6: Error throwing C - Invalid Index testing... PASSED
|
||||||
|
Test 7: Copy constructure testing... PASSED
|
||||||
|
Test 8: Operator = testing... PASSED
|
||||||
|
Test 9: At function testing... PASSED
|
||||||
|
Test 10: Objects' independence testing... PASSED
|
||||||
|
Test 11: Comprehensive testing... PASSED
|
622
map/data/two/code.cpp
Normal file
622
map/data/two/code.cpp
Normal file
@ -0,0 +1,622 @@
|
|||||||
|
#include <fstream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <ctime>
|
||||||
|
#include "exceptions.hpp"
|
||||||
|
#include "map.hpp"
|
||||||
|
|
||||||
|
const int MAXN = 50001;
|
||||||
|
|
||||||
|
enum Color{
|
||||||
|
Red, Green, Blue, Normal
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestCore{
|
||||||
|
private:
|
||||||
|
const char *title;
|
||||||
|
const int id, total;
|
||||||
|
long dfn;
|
||||||
|
int counter, enter;
|
||||||
|
public:
|
||||||
|
TestCore(const char *title, const int &id, const int &total) : title(title), id(id), total(total), dfn(clock()), counter(0), enter(0) {
|
||||||
|
}
|
||||||
|
void init() {
|
||||||
|
static char tmp[200];
|
||||||
|
sprintf(tmp, "Test %d: %-55s", id, title);
|
||||||
|
printf("%-65s", tmp);
|
||||||
|
}
|
||||||
|
void showMessage(const char *s, const Color &c = Normal) {
|
||||||
|
}
|
||||||
|
void showProgress() {
|
||||||
|
}
|
||||||
|
void pass() {
|
||||||
|
showMessage("PASSED", Green);
|
||||||
|
printf("PASSED");
|
||||||
|
}
|
||||||
|
void fail() {
|
||||||
|
showMessage("FAILED", Red);
|
||||||
|
printf("FAILED");
|
||||||
|
}
|
||||||
|
~TestCore() {
|
||||||
|
puts("");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IntA{
|
||||||
|
public:
|
||||||
|
static int counter;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
IntA(int val) : val(val) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntA(const IntA &rhs) {
|
||||||
|
val = rhs.val;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntA & operator = (const IntA &rhs) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ==(const IntA &rhs) {
|
||||||
|
return val == rhs.val;
|
||||||
|
}
|
||||||
|
friend bool operator < (const IntA &lhs, const IntA &rhs) {
|
||||||
|
return lhs.val > rhs.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
~IntA() {
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int IntA::counter = 0;
|
||||||
|
|
||||||
|
class IntB{
|
||||||
|
public:
|
||||||
|
int *val;
|
||||||
|
explicit IntB(int val = 0) : val(new int(val)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
IntB(const IntB &rhs) {
|
||||||
|
val = new int(*rhs.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
IntB & operator =(const IntB &rhs) {
|
||||||
|
if (this == &rhs) return *this;
|
||||||
|
delete this->val;
|
||||||
|
val = new int(*rhs.val);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator !=(const IntB &rhs) const {
|
||||||
|
return *val != *rhs.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ==(const IntB &rhs) const {
|
||||||
|
return *val == *rhs.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
~IntB() {
|
||||||
|
delete this->val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Compare{
|
||||||
|
bool operator ()(const IntA &a, const IntA &b)const {
|
||||||
|
return a.val > b.val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::vector<int> & generator(int n = MAXN) {
|
||||||
|
static std::vector<int> raw;
|
||||||
|
raw.clear();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
raw.push_back(rand());
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester1() {
|
||||||
|
TestCore console("Operator [] & Iterator traverse testing...", 1, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap[x] = tmp;
|
||||||
|
srcmap[x] = tmp;
|
||||||
|
//printf("insert(%d, %d)\n", x, tmp.val);
|
||||||
|
for (int c = 0; c < 10; c++) {
|
||||||
|
int p = rand() % (i + 1);
|
||||||
|
if (stdmap[ret[p]] != srcmap[ret[p]]) {
|
||||||
|
//std::cerr << ret[p] << " ";
|
||||||
|
//std::cerr << stdmap[ret[p]] << " " << srcmap[ret[p]] << std::endl;
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.cbegin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester2() {
|
||||||
|
TestCore console("Insertion function testing...", 2, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
for (int c = 0; c < 10; c++) {
|
||||||
|
int p = rand() % (i + 1);
|
||||||
|
if (stdmap[ret[p]] != srcmap[ret[p]]) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.begin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester3() {
|
||||||
|
TestCore console("Deletion & Find function testing...", 3, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
std::random_shuffle(ret.begin(), ret.end());
|
||||||
|
for (auto x : ret) {
|
||||||
|
if (stdmap.find(x) != stdmap.end()) {
|
||||||
|
srcmap.erase(srcmap.find(x));
|
||||||
|
stdmap.erase(stdmap.find(x));
|
||||||
|
}
|
||||||
|
for (int c = 0; c < 10; c++) {
|
||||||
|
int p = rand() % ret.size();
|
||||||
|
if (stdmap.find(ret[p]) != stdmap.end()) {
|
||||||
|
if (stdmap[ret[p]] != srcmap[ret[p]]) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester4() {
|
||||||
|
TestCore console("Error throwing A - Invalid Iterator testing...", 4, 0);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
++srcmap.end();
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
--srcmap.begin();
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.end()++;
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.begin()--;
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
console.pass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester5() {
|
||||||
|
TestCore console("Error throwing B - Invalid Const_Iterator testing...", 5, 0);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
++srcmap.cend();
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
--srcmap.cbegin();
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.cend()++;
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.cbegin()--;
|
||||||
|
} catch (sjtu::exception error) {
|
||||||
|
console.pass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester6() {
|
||||||
|
TestCore console("Error throwing C - Invalid Index testing...", 6, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (auto x : ret) {
|
||||||
|
srcmap[x] = IntB(rand());
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
srcmap.at(IntA(-1)) = IntB(2);
|
||||||
|
} catch (...) {
|
||||||
|
console.pass();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester7() {
|
||||||
|
const int MAXC = MAXN / 2;
|
||||||
|
TestCore console("Copy constructure testing...", 7, MAXN + MAXC + 2 * (MAXN - MAXC));
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
std::map<IntA, IntB, Compare> tmp1(stdmap);
|
||||||
|
sjtu::map<IntA, IntB, Compare> tmp2(srcmap);
|
||||||
|
std::random_shuffle(ret.begin(), ret.end());
|
||||||
|
for (int i = 0; i < MAXC; i++) {
|
||||||
|
if (stdmap.find(ret[i]) != stdmap.end()) {
|
||||||
|
srcmap.erase(srcmap.find(ret[i]));
|
||||||
|
stdmap.erase(stdmap.find(ret[i]));
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.begin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
itB = tmp2.begin();
|
||||||
|
for (auto itA = tmp1.begin(); itA != tmp1.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester8() {
|
||||||
|
const int MAXC = MAXN / 2;
|
||||||
|
TestCore console("Operator = testing...", 8, MAXN + MAXC + 2 * (MAXN - MAXC));
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
std::map<IntA, IntB, Compare> tmp1;
|
||||||
|
tmp1 = stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> tmp2;
|
||||||
|
tmp2 = srcmap;
|
||||||
|
std::random_shuffle(ret.begin(), ret.end());
|
||||||
|
for (int i = 0; i < MAXC; i++) {
|
||||||
|
if (stdmap.find(ret[i]) != stdmap.end()) {
|
||||||
|
srcmap.erase(srcmap.find(ret[i]));
|
||||||
|
stdmap.erase(stdmap.find(ret[i]));
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.cbegin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
itB = tmp2.cbegin();
|
||||||
|
for (auto itA = tmp1.begin(); itA != tmp1.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester9() {
|
||||||
|
TestCore console("At function testing...", 9, 2 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap[x] = tmp;
|
||||||
|
srcmap[x] = tmp;
|
||||||
|
for (int c = 0; c < 10; c++) {
|
||||||
|
int p = rand() % (i + 1);
|
||||||
|
if (stdmap.at(ret[p]) != srcmap.at(ret[p])) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmp = IntB(rand());
|
||||||
|
stdmap.at(ret[p]) = tmp;
|
||||||
|
srcmap.at(ret[p]) = tmp;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
auto itB = srcmap.cbegin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester10() {
|
||||||
|
TestCore console("Objects' independence testing...", 10, 6 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
stdmap.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
std::map<IntA, IntB, Compare> std1(stdmap), std2;
|
||||||
|
std2 = std1 = std1;
|
||||||
|
sjtu::map<IntA, IntB, Compare> src1(srcmap), src2;
|
||||||
|
src2 = src1 = src1;
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
if (stdmap.find(ret[i]) != stdmap.end()) {
|
||||||
|
srcmap.erase(srcmap.find(ret[i]));
|
||||||
|
stdmap.erase(stdmap.find(ret[i]));
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
ret = generator(MAXN);
|
||||||
|
for (int i = 0; i < (int)ret.size(); i++) {
|
||||||
|
auto x = ret[i];
|
||||||
|
IntB tmp = IntB(rand());
|
||||||
|
std1.insert(std::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
src1.insert(sjtu::map<IntA, IntB, Compare>::value_type(x, tmp));
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto itB = srcmap.begin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
itB = src1.begin();
|
||||||
|
for (auto itA = std1.begin(); itA != std1.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
itB = src2.begin();
|
||||||
|
for (auto itA = std2.begin(); itA != std2.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tester11() {
|
||||||
|
const int MAXN = 100001;
|
||||||
|
TestCore console("Comprehensive testing...", 11, 3 * MAXN);
|
||||||
|
console.init();
|
||||||
|
auto ret = generator(MAXN);
|
||||||
|
try{
|
||||||
|
std::map<IntA, IntB, Compare> stdmap;
|
||||||
|
sjtu::map<IntA, IntB, Compare> srcmap;
|
||||||
|
for (int i = 0, cnt = 0; i < (int)ret.size(); i++, cnt++) {
|
||||||
|
int tmp = rand();
|
||||||
|
auto retA = stdmap.insert(std::map<IntA, IntB, Compare>::value_type(IntA(ret[i]), IntB(tmp)));
|
||||||
|
auto retB = srcmap.insert(sjtu::map<IntA, IntB, Compare>::value_type(IntA(ret[i]), IntB(tmp)));
|
||||||
|
console.showProgress();
|
||||||
|
if (!retA.second) {
|
||||||
|
cnt--;
|
||||||
|
ret[i] = -1;
|
||||||
|
console.showProgress();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (rand() % 100 < 12 && cnt > 0) {
|
||||||
|
int p = 0;
|
||||||
|
while (ret[p] < 0) {
|
||||||
|
p = rand() % (i + 1);
|
||||||
|
}
|
||||||
|
stdmap.erase(stdmap.find(ret[p]));
|
||||||
|
srcmap.erase(srcmap.find(ret[p]));
|
||||||
|
ret[p] = -1;
|
||||||
|
cnt++;
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
if (stdmap.size() != srcmap.size()) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto itB = srcmap.cbegin();
|
||||||
|
for (auto itA = stdmap.begin(); itA != stdmap.end(); ++itA, ++itB) {
|
||||||
|
if ((itA -> first).val != (itA -> first).val || (itB -> first).val != (itB -> first).val) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto stdtmp(stdmap);
|
||||||
|
const auto srctmp(srcmap);
|
||||||
|
|
||||||
|
std::map<IntA, IntB, Compare>::const_iterator citA = stdtmp.cbegin();
|
||||||
|
sjtu::map<IntA, IntB, Compare>::const_iterator citB = srctmp.cbegin();
|
||||||
|
|
||||||
|
stdtmp.size();
|
||||||
|
srctmp.size();
|
||||||
|
|
||||||
|
for (auto x : ret) {
|
||||||
|
if (x >= 0) {
|
||||||
|
if (stdmap.at(x) != srcmap.at(x)) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (srctmp.count(x) == 0) {
|
||||||
|
console.fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.showProgress();
|
||||||
|
}
|
||||||
|
} catch(...) {
|
||||||
|
console.showMessage("Unknown error occured.", Blue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
#ifdef SPECIAL
|
||||||
|
puts("AATree-Map Checker Version 1.2");
|
||||||
|
#endif
|
||||||
|
tester1();
|
||||||
|
tester2();
|
||||||
|
tester3();
|
||||||
|
tester4();
|
||||||
|
tester5();
|
||||||
|
tester6();
|
||||||
|
tester7();
|
||||||
|
tester8();
|
||||||
|
tester9();
|
||||||
|
tester10();
|
||||||
|
tester11();
|
||||||
|
return 0;
|
||||||
|
}
|
39
map/src/exceptions.hpp
Normal file
39
map/src/exceptions.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef SJTU_EXCEPTIONS_HPP
|
||||||
|
#define SJTU_EXCEPTIONS_HPP
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace sjtu {
|
||||||
|
|
||||||
|
class exception {
|
||||||
|
protected:
|
||||||
|
const std::string variant = "";
|
||||||
|
std::string detail = "";
|
||||||
|
public:
|
||||||
|
exception() {}
|
||||||
|
exception(const exception &ec) : variant(ec.variant), detail(ec.detail) {}
|
||||||
|
virtual std::string what() {
|
||||||
|
return variant + " " + detail;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class index_out_of_bound : public exception {
|
||||||
|
/* __________________________ */
|
||||||
|
};
|
||||||
|
|
||||||
|
class runtime_error : public exception {
|
||||||
|
/* __________________________ */
|
||||||
|
};
|
||||||
|
|
||||||
|
class invalid_iterator : public exception {
|
||||||
|
/* __________________________ */
|
||||||
|
};
|
||||||
|
|
||||||
|
class container_is_empty : public exception {
|
||||||
|
/* __________________________ */
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
190
map/src/map.hpp
Normal file
190
map/src/map.hpp
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/**
|
||||||
|
* implement a container like std::map
|
||||||
|
*/
|
||||||
|
#ifndef SJTU_MAP_HPP
|
||||||
|
#define SJTU_MAP_HPP
|
||||||
|
|
||||||
|
// only for std::less<T>
|
||||||
|
#include <functional>
|
||||||
|
#include <cstddef>
|
||||||
|
#include "utility.hpp"
|
||||||
|
#include "exceptions.hpp"
|
||||||
|
|
||||||
|
namespace sjtu {
|
||||||
|
|
||||||
|
template<
|
||||||
|
class Key,
|
||||||
|
class T,
|
||||||
|
class Compare = std::less<Key>
|
||||||
|
> class map {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* the internal type of data.
|
||||||
|
* it should have a default constructor, a copy constructor.
|
||||||
|
* You can use sjtu::map as value_type by typedef.
|
||||||
|
*/
|
||||||
|
typedef pair<const Key, T> value_type;
|
||||||
|
/**
|
||||||
|
* see BidirectionalIterator at CppReference for help.
|
||||||
|
*
|
||||||
|
* if there is anything wrong throw invalid_iterator.
|
||||||
|
* like it = map.begin(); --it;
|
||||||
|
* or it = map.end(); ++end();
|
||||||
|
*/
|
||||||
|
class const_iterator;
|
||||||
|
class iterator {
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* TODO add data members
|
||||||
|
* just add whatever you want.
|
||||||
|
*/
|
||||||
|
public:
|
||||||
|
iterator() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
iterator(const iterator &other) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO iter++
|
||||||
|
*/
|
||||||
|
iterator operator++(int) {}
|
||||||
|
/**
|
||||||
|
* TODO ++iter
|
||||||
|
*/
|
||||||
|
iterator & operator++() {}
|
||||||
|
/**
|
||||||
|
* TODO iter--
|
||||||
|
*/
|
||||||
|
iterator operator--(int) {}
|
||||||
|
/**
|
||||||
|
* TODO --iter
|
||||||
|
*/
|
||||||
|
iterator & operator--() {}
|
||||||
|
/**
|
||||||
|
* a operator to check whether two iterators are same (pointing to the same memory).
|
||||||
|
*/
|
||||||
|
value_type & operator*() const {}
|
||||||
|
bool operator==(const iterator &rhs) const {}
|
||||||
|
bool operator==(const const_iterator &rhs) const {}
|
||||||
|
/**
|
||||||
|
* some other operator for iterator.
|
||||||
|
*/
|
||||||
|
bool operator!=(const iterator &rhs) const {}
|
||||||
|
bool operator!=(const const_iterator &rhs) const {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for the support of it->first.
|
||||||
|
* See <http://kelvinh.github.io/blog/2013/11/20/overloading-of-member-access-operator-dash-greater-than-symbol-in-cpp/> for help.
|
||||||
|
*/
|
||||||
|
value_type* operator->() const noexcept {}
|
||||||
|
};
|
||||||
|
class const_iterator {
|
||||||
|
// it should has similar member method as iterator.
|
||||||
|
// and it should be able to construct from an iterator.
|
||||||
|
private:
|
||||||
|
// data members.
|
||||||
|
public:
|
||||||
|
const_iterator() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
const_iterator(const const_iterator &other) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
const_iterator(const iterator &other) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
// And other methods in iterator.
|
||||||
|
// And other methods in iterator.
|
||||||
|
// And other methods in iterator.
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* TODO two constructors
|
||||||
|
*/
|
||||||
|
map() {}
|
||||||
|
map(const map &other) {}
|
||||||
|
/**
|
||||||
|
* TODO assignment operator
|
||||||
|
*/
|
||||||
|
map & operator=(const map &other) {}
|
||||||
|
/**
|
||||||
|
* TODO Destructors
|
||||||
|
*/
|
||||||
|
~map() {}
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* access specified element with bounds checking
|
||||||
|
* Returns a reference to the mapped value of the element with key equivalent to key.
|
||||||
|
* If no such element exists, an exception of type `index_out_of_bound'
|
||||||
|
*/
|
||||||
|
T & at(const Key &key) {}
|
||||||
|
const T & at(const Key &key) const {}
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* access specified element
|
||||||
|
* Returns a reference to the value that is mapped to a key equivalent to key,
|
||||||
|
* performing an insertion if such key does not already exist.
|
||||||
|
*/
|
||||||
|
T & operator[](const Key &key) {}
|
||||||
|
/**
|
||||||
|
* behave like at() throw index_out_of_bound if such key does not exist.
|
||||||
|
*/
|
||||||
|
const T & operator[](const Key &key) const {}
|
||||||
|
/**
|
||||||
|
* return a iterator to the beginning
|
||||||
|
*/
|
||||||
|
iterator begin() {}
|
||||||
|
const_iterator cbegin() const {}
|
||||||
|
/**
|
||||||
|
* return a iterator to the end
|
||||||
|
* in fact, it returns past-the-end.
|
||||||
|
*/
|
||||||
|
iterator end() {}
|
||||||
|
const_iterator cend() const {}
|
||||||
|
/**
|
||||||
|
* checks whether the container is empty
|
||||||
|
* return true if empty, otherwise false.
|
||||||
|
*/
|
||||||
|
bool empty() const {}
|
||||||
|
/**
|
||||||
|
* returns the number of elements.
|
||||||
|
*/
|
||||||
|
size_t size() const {}
|
||||||
|
/**
|
||||||
|
* clears the contents
|
||||||
|
*/
|
||||||
|
void clear() {}
|
||||||
|
/**
|
||||||
|
* insert an element.
|
||||||
|
* return a pair, the first of the pair is
|
||||||
|
* the iterator to the new element (or the element that prevented the insertion),
|
||||||
|
* the second one is true if insert successfully, or false.
|
||||||
|
*/
|
||||||
|
pair<iterator, bool> insert(const value_type &value) {}
|
||||||
|
/**
|
||||||
|
* erase the element at pos.
|
||||||
|
*
|
||||||
|
* throw if pos pointed to a bad element (pos == this->end() || pos points an element out of this)
|
||||||
|
*/
|
||||||
|
void erase(iterator pos) {}
|
||||||
|
/**
|
||||||
|
* Returns the number of elements with key
|
||||||
|
* that compares equivalent to the specified argument,
|
||||||
|
* which is either 1 or 0
|
||||||
|
* since this container does not allow duplicates.
|
||||||
|
* The default method of check the equivalence is !(a < b || b > a)
|
||||||
|
*/
|
||||||
|
size_t count(const Key &key) const {}
|
||||||
|
/**
|
||||||
|
* Finds an element with key equivalent to key.
|
||||||
|
* key value of the element to search for.
|
||||||
|
* Iterator to an element with key equivalent to key.
|
||||||
|
* If no such element is found, past-the-end (see end()) iterator is returned.
|
||||||
|
*/
|
||||||
|
iterator find(const Key &key) {}
|
||||||
|
const_iterator find(const Key &key) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
27
map/src/utility.hpp
Normal file
27
map/src/utility.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef SJTU_UTILITY_HPP
|
||||||
|
#define SJTU_UTILITY_HPP
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace sjtu {
|
||||||
|
|
||||||
|
template<class T1, class T2>
|
||||||
|
class pair {
|
||||||
|
public:
|
||||||
|
T1 first;
|
||||||
|
T2 second;
|
||||||
|
constexpr pair() : first(), second() {}
|
||||||
|
pair(const pair &other) = default;
|
||||||
|
pair(pair &&other) = default;
|
||||||
|
pair(const T1 &x, const T2 &y) : first(x), second(y) {}
|
||||||
|
template<class U1, class U2>
|
||||||
|
pair(U1 &&x, U2 &&y) : first(x), second(y) {}
|
||||||
|
template<class U1, class U2>
|
||||||
|
pair(const pair<U1, U2> &other) : first(other.first), second(other.second) {}
|
||||||
|
template<class U1, class U2>
|
||||||
|
pair(pair<U1, U2> &&other) : first(other.first), second(other.second) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
81
map/tutorials/detect-memory-leak/detect-memory-leak.md
Normal file
81
map/tutorials/detect-memory-leak/detect-memory-leak.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# How to Detect Memory Leak
|
||||||
|
## why memory leak?
|
||||||
|
申请的动态空间没有释放,即
|
||||||
|
* `new` 没有对应的 `delete`
|
||||||
|
* `malloc` 没有对应的 `free`
|
||||||
|
## How to detect?
|
||||||
|
### 一. Valgrind
|
||||||
|
#### 1.查看有没有装Valgrind:
|
||||||
|
```bash
|
||||||
|
valgrind
|
||||||
|
```
|
||||||
|
或
|
||||||
|
```
|
||||||
|
valgrind --version
|
||||||
|
```
|
||||||
|
若已安装valgrind应显示
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
或
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 2.安装Valgrind:
|
||||||
|
```bash
|
||||||
|
sudo apt install valgrind
|
||||||
|
```
|
||||||
|
另外还可以通过下载源码编译安装
|
||||||
|
|
||||||
|
源码地址:https://valgrind.org/
|
||||||
|
|
||||||
|
下载源码:
|
||||||
|
```bash
|
||||||
|
wget https://sourceware.org/pub/valgrind/valgrind-3.20.0.tar.bz2
|
||||||
|
```
|
||||||
|
解压并安装:
|
||||||
|
```bash
|
||||||
|
tar -jxvf valgrind-3.20.0.tar.bz2
|
||||||
|
cd valgrind-3.20.0
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
安装后可以再次按照上面的步骤检查是否成功安装了valgrind
|
||||||
|
#### 3.开始使用
|
||||||
|
假设现在有一份有 memory leak 的代码如下:
|
||||||
|
```cpp
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void f(void)
|
||||||
|
{
|
||||||
|
int* x = malloc(10 * sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
我们即可编译代码并使用valgrind检测:
|
||||||
|
```bash
|
||||||
|
gcc -g test.c -o valgrind_test
|
||||||
|
valgrind --leak-check=yes ./valgrind_test
|
||||||
|
```
|
||||||
|
关于更多valgrind的使用方法,可以参考官方文档:https://valgrind.org/docs/manual/index.html
|
||||||
|
### 二. 使用 gcc 或 g++ 的 -fsanitize=leak 编译选项
|
||||||
|
g++ `-fsanitize` 编译选项其实已经提供了很多内存检测的功能,包括内存泄漏检测、内存访问越界检测等等,这些功能都是在编译时开启的。
|
||||||
|
常用的三个 `-fsanitize` 编译选项如下:
|
||||||
|
* `-fsanitize=address`:内存访问越界检测
|
||||||
|
* `-fsanitize=undefined`:未定义行为检测
|
||||||
|
* `-fsanitize=leak`:内存泄漏检测
|
||||||
|
有时我们需要更加详细的信息(比如:定位到错误在源代码中的位置)可以再加上 `-g` 选项。
|
||||||
|
|
||||||
|
对于同样的例子,我们使用 `-fsanitize=leak` 编译选项进行检测:
|
||||||
|
```bash
|
||||||
|
gcc test.c -o gcc_test -fsanitize=leak -g
|
||||||
|
./gcc_test
|
||||||
|
```
|
||||||
|
若检测出错误则会,显示如下信息:
|
||||||
|

|
BIN
map/tutorials/detect-memory-leak/img/gcc_test.png
Normal file
BIN
map/tutorials/detect-memory-leak/img/gcc_test.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 934 KiB |
BIN
map/tutorials/detect-memory-leak/img/valgrind_exist0.png
Normal file
BIN
map/tutorials/detect-memory-leak/img/valgrind_exist0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
BIN
map/tutorials/detect-memory-leak/img/valgrind_exist1.png
Normal file
BIN
map/tutorials/detect-memory-leak/img/valgrind_exist1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 82 KiB |
124
map/tutorials/type_traits/Tutorial.md
Normal file
124
map/tutorials/type_traits/Tutorial.md
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# A Little Tutorial
|
||||||
|
这个文档对 C++ 11 中的 type_traits 做一个简短的介绍和实现指导。但主要还是需要同学们自学。
|
||||||
|
## What is traits in C++ 11?
|
||||||
|
在 C++11 中,traits 是指一组类型萃取机制(type trait mechanism),用于提取类型信息,并根据这些信息在编译期间进行类型转换和编译期间的决策。它们在头文件 `type_traits` 中。
|
||||||
|
|
||||||
|
traits 通常使用**模板元编程**的技术实现,它允许我们在编译期间确定一个类型的属性,如是否是一个指针、是否是一个常量类型、是否是一个类等等。
|
||||||
|
|
||||||
|
我们给出若干个使用 C++ 11 type_traits 的代码实例:
|
||||||
|
```C++
|
||||||
|
#include <iostream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void print_type(T x)
|
||||||
|
{
|
||||||
|
if (std::is_floating_point<T>::value)
|
||||||
|
std::cout << x << " is a floating point number.\n";
|
||||||
|
else
|
||||||
|
std::cout << x << " is not a floating point number.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
void compare_types(T x, U y)
|
||||||
|
{
|
||||||
|
if (std::is_same<T, U>::value)
|
||||||
|
std::cout << x << " and "<< y << " have the same type.\n";
|
||||||
|
else
|
||||||
|
std::cout << x << " and "<< y << " have different type.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct A {}; // empty class
|
||||||
|
struct B { int x; }; // non-empty class
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << std::boolalpha;
|
||||||
|
std::cout << std::is_pointer<int>::value << std::endl; // 输出 false
|
||||||
|
std::cout << std::is_pointer<int*>::value << std::endl; // 输出 true
|
||||||
|
|
||||||
|
print_type(1.1451); // prints 1.1451 is a floating point number.
|
||||||
|
print_type(11451); // prints 11451 is not a floating point number.
|
||||||
|
|
||||||
|
compare_types(1.1451, 11451); // prints 1.1451 and 11451 have different types.
|
||||||
|
compare_types('a', 'b'); // prints a and b have the same type.
|
||||||
|
|
||||||
|
std::cout << std::boolalpha;
|
||||||
|
std::cout << "Is A an empty class? " << std::is_empty<A>::value << "\n"; // prints true
|
||||||
|
std::cout << "Is B an empty class? " << std::is_empty<B>::value << "\n"; // prints false
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
以及traits自定义模板类的实现示例:
|
||||||
|
```
|
||||||
|
// 定义数据 type 类
|
||||||
|
enum Type {
|
||||||
|
TYPE_1,
|
||||||
|
TYPE_2,
|
||||||
|
TYPE_3
|
||||||
|
}
|
||||||
|
// 自定义数据类型
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
Type type = TYPE_1;
|
||||||
|
};
|
||||||
|
class Bar {
|
||||||
|
public:
|
||||||
|
Type type = TYPE_2;
|
||||||
|
};
|
||||||
|
// 定义type traits的模板类,所有像这个模板类一样含有Type的类会被萃取出来进行模板化处理
|
||||||
|
template<typename T>
|
||||||
|
struct type_traits {
|
||||||
|
Type type = T::type;
|
||||||
|
}
|
||||||
|
// 内置数据类型同样可以进行这种萃取
|
||||||
|
template<typename int>
|
||||||
|
struct type_traits {
|
||||||
|
Type type = Type::TYPE_1;
|
||||||
|
}
|
||||||
|
template<typename double>
|
||||||
|
struct type_traits {
|
||||||
|
Type type = Type::TYPE_3;
|
||||||
|
}
|
||||||
|
// 萃取之后进行统一处理,写统一的编码函数
|
||||||
|
template<typename T>
|
||||||
|
void decode<const T& data, char* buf) {
|
||||||
|
if(type_traits<T>::type == Type::TYPE_1) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
else if(type_traits<T>::type == Type::TYPE_2) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Bonus
|
||||||
|
我们的 Bonus 可以是实现类似于 C++ 11 中的 type_traits 的某些功能,但是不要求完全一致。
|
||||||
|
|
||||||
|
这里举一个示例,我们以“迭代器可否被赋值特性”给出一个简单的实现思路:
|
||||||
|
```C++
|
||||||
|
//1.定义一个 type_traits 模板类
|
||||||
|
template<typename T>
|
||||||
|
struct my_type_traits{
|
||||||
|
using iterator_assignable = typename T::iterator_assignable;
|
||||||
|
};
|
||||||
|
//2.定义两个类,表示迭代器是否可被赋值的特性(这一步也可以使用枚举变量来实现)
|
||||||
|
struct my_true_type{
|
||||||
|
//todo
|
||||||
|
};
|
||||||
|
struct my_false_type{
|
||||||
|
//todo
|
||||||
|
};
|
||||||
|
//3.分别在可被赋值的迭代器和不可被赋值的迭代器中定义 iterator_assignable 类型
|
||||||
|
class iterator{
|
||||||
|
using iterator_assignable = my_true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_iterator{
|
||||||
|
using iterator_assignable = my_false_type;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
这部分我们不会提供提示数据,所以你需要自己设计测试代码,并且在 code review 时向助教展示。
|
||||||
|
|
||||||
|
如果想了解更多关于type traits,可以参考 https://en.cppreference.com/w/cpp/header/type_traits,或许其中的一些做法会给你一些思路的启发。
|
||||||
|
|
||||||
|
我们鼓励大家多去尝试,但不建议大家在这个作业中花费太多时间。
|
Reference in New Issue
Block a user