Added map

This commit is contained in:
Polaris_Dane
2024-03-24 15:42:18 +08:00
parent 066b5db646
commit b48b580e1c
33 changed files with 4835 additions and 1 deletions

View File

@ -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
View 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
View 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;
}
}
}

View 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
View 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

View 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

View 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

File diff suppressed because one or more lines are too long

88
map/data/five/code.cpp Normal file
View 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;
}

File diff suppressed because one or more lines are too long

View 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

File diff suppressed because one or more lines are too long

241
map/data/four/code.cpp Normal file
View 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();
}

View 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

View 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
View 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
View 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;
}

File diff suppressed because one or more lines are too long

View 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

File diff suppressed because one or more lines are too long

622
map/data/three/code.cpp Normal file
View 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;
}

View 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

View 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
View 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
View 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
View 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
View 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
View 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

View 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应显示
![](img/valgrind_exist0.png)
![](img/valgrind_exist1.png)
#### 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
```
若检测出错误则会,显示如下信息:
![](img/gcc_test.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View 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或许其中的一些做法会给你一些思路的启发。
我们鼓励大家多去尝试,但不建议大家在这个作业中花费太多时间。