Unverified Commit aa98beba authored by ouuan's avatar ouuan Committed by GitHub
Browse files

🔀 Merge pull request #1664 from cmpute/lang

add Python相关, add STL相关, fix 一些翻译
parents a71d5f11 91d35323
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -54,9 +54,9 @@ int q[SIZE], ql = 1, qr;

有人问这个东西有什么用吗?参见下面这道题。这道题顺便可以给大家一个 **双栈模拟双端队列** 的方法。

### 例题
## 例题

LOJ6515 贪玩蓝月
 [LOJ6515「雅礼集训 2018 Day10」贪玩蓝月](https://loj.ac/problem/6515) 

> 一个双端队列(deque),m 个事件:
>
+3 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ author: Konano, Enter-tainer, JulieSigtuna, GldHkkowo
-    [ZOJ](https://zoj.pintia.cn/home) 浙江大学在线测评系统。
-    [NOJ](http://acm.njupt.edu.cn/) 南京邮电大学在线测评系统,自身拥有题目两千余,同时支持对多个国内外 OJ 的提交,可以直接在 NOJ 提交别的 OJ 的题。
-    [Lutece](https://acm.uestc.edu.cn/home) 电子科技大学在线测评系统,基于开源项目 [Lutece](https://github.com/lutece-awesome)
-    [清澄](http://www.tsinsen.com/) 始于 2005 年,最近挂掉了。

### 国外

@@ -85,7 +86,7 @@ author: Konano, Enter-tainer, JulieSigtuna, GldHkkowo
-   《具体数学》第二版 - Ronald L. Graham/Donald E. Knuth/Oren Patashnik 
    英文版原名_Concrete Mathematics_
-   《组合数学》第五版 - Richard A.Brualdi 
    英文版原名_Concrete mathematices_
    英文版原名_Introductory Conbinatorics_
-    [Competitive Programmer's Handbook](https://cses.fi/book/index.html) 
-   《挑战程序设计竞赛》全套 - 秋叶拓哉,岩田阳一,北川宜稔
    通俗易懂。
@@ -126,3 +127,4 @@ author: Konano, Enter-tainer, JulieSigtuna, GldHkkowo
-    [GitHub.com:OI-wiki/libs](https://github.com/OI-wiki/libs) 
-    [多校联合训练](http://acm.hdu.edu.cn) 关键词: `Multi-University Training Contest` 
-    [Vjudge](https://vjudge.net/) 
-    [Project Euler](https://projecteuler.net/) 

docs/lang/c-cpp.md

0 → 100644
+41 −0
Original line number Diff line number Diff line
本文介绍 C 与 C++ 之间重要的或者容易忽略的区别。尽管 C++ 几乎是 C 的超集,C/C++ 代码混用一般也没什么问题,但是了解 C/C++ 间比较重要区别可以避免碰到一些奇怪的 bug。如果你是以 C 为主力语言的 OIer,那么本文也能让你更顺利地上手 C++。C++ 相比 C 增加的独特特性可以阅读 [C++ 进阶](./class.md) 部分的教程。

## 宏与模板

C++ 的模板在设计之初的一个用途就是用来替换宏定义。学会模板编程是从 C 迈向 C++ 的重要一步。模板不同于宏的文字替换,在编译时会得到更全面的编译器检查,便于编写更健全的代码,利用 inline 关键字还能获得编译器充分的优化。模板特性在 C++11 后支持了可变长度的模板参数表,可以用来替代 C 中的可变长度函数并保证类型安全。

## 指针与引用

C++ 中你仍然可以使用 C 风格的指针,但是对于变量传递而言,更推荐使用 C++ 的 [引用](./reference.md) 特性来实现类似的功能。由于引用指向的对象不能为空,因此可以避免一些空地址访问的问题。不过指针由于其灵活性,也仍然有其用武之处。值得一提的是,C 中的 `NULL` 空指针在 C++ 中有类型安全的替代品 `nullptr` 。引用和指针之间可以通过 [ `*` 和 `&` 运算符](./op.md) 相互转换。

## struct

尽管在 C 和 C++ 中都有 struct 的概念,但是他们对应的东西是不能混用的!C 中的 struct 用来描述一种固定的内存组织结构,而 C++ 中的 struct 就是一种类, **它与类唯一的区别就是它的成员和继承行为默认是 public 的** ,而一般类的默认成员是 private 的。这一点在写 C/C++ 混合代码时尤其致命。

另外,声明 struct 时 C++ 也不需要像 C 那么繁琐,C 版本:

```c
typedef struct Node_t{
    struct Node_t *next;
    int key;
} Node;
```

C++ 版本

```cpp
struct Node {
  Node *next;
  int key;
};
```

## const

const 在 C 中只有限定变量不能修改的功能,而在 C++ 中,由于大量新特性的出现,const 也被赋予的更多用法。C 中的 const 在 C++ 中的继任者是 constexpr,而 C++ 中的 const 的用法请参见 [常值](./const.md) 页面的说明。

## 内存分配

C++ 中新增了 `new``delete` 关键字用来在“自由存储区”上分配空间,这个自由存储区可以是堆也可以是静态存储区,他们是为了配合“类”而出现的。其中 `delete[]` 还能够直接释放动态数组的内存,非常方便。 `new``delete` 关键字会调用类型的构造函数和析构函数,相比 C 中的 `malloc()``realloc()``free()` 函数,他们对类型有更完善的支持,但是效率不如 C 中的这些函数。

简而言之,如果你需要动态分配内存的对象是基础类型或他们的数组,那么你可以使用 `malloc()` 进行更高效的内存分配;但如果你新建的对象是非基础的类型,那么建议使用 `new` 以获得安全性检查。值得注意的是尽管 `new``malloc()` 都是返回指针,但是 `new` 出来的指针 **只能**`delete` 回收,而 `malloc()` 出来的指针也只能用 `free()` 回收,否则会有内存泄漏的风险。

docs/lang/const.md

0 → 100644
+118 −0
Original line number Diff line number Diff line
C++ 定义了一套完善的只读量定义方法,被常量修饰符 `const` 修饰的对象或类型都是只读量,只读量的内存存储与一般变量没有任何区别,但是编译器会在编译期进行冲突检查,避免对只读量的修改。因此合理使用 `const` 修饰符可以增加代码健壮性。

## 常类型

在类型的名字前增加 const 修饰会将该类型的变量标记为不可变的。具体使用情况有常量和常引用(指针)两种。

### 常量

这里的常量即常变量,指的是 const 类型的变量(而不是标题里泛指的只读量)。常类型量在声明之后便不可重新赋值,也不可访问其可变成员,只能访问其常成员。常成员的定义见后文。

??? note "类型限定符"
    C++ 中类型限定符一共有三种:常量(const)、可变(mutable)和易变(volatile),其中默认情况下是可变变量,声明易变变量的情形是为了刻意避免编译器优化。

```cpp
const int a = 0;  // a 的类型为 const int

// a = 1; // 报错,不能修改常量
```

### 常引用、常指针

常引用和常指针也与常量类似,但区别在于他们是限制了访问,而没有更改原变量的类型。

```cpp
int a = 0;
const int b = 0;

int *p1 = &a;
*p1 = 1;
const int *p2 = &a;
// *p2 = 2; // 报错,不能通过常指针修改变量
// int *p3 = &b; // 报错,不能用普通指针指向 const 变量
const int *p4 = &b;

int &r1 = a;
r1 = 1;
const int &r2 = a;
// r2 = 2; // 报错,不能通过常引用修改变量
// int &p3 = b; // 报错,不能用普通引用指向 const 变量
const int &r4 = b;
```

另外需要区分开的是“常类型指针”和“常指针变量”(即常指针、指针常量),例如下列声明

```cpp
int* const p1;        // 类型为int的常指针,需要初始化
const int* p2;        // 类型为const int的指针
const int* const p3;  // 类型为const int的常指针

int (*f1)(int);  // 普通的函数指针
// int (const *f2)(int); // 指向常函数的指针,不可行
int (*const f3)(int) = some_func;  // 指向函数的常指针,需要初始化
int const* (*f4)(int);             // 指向返回常指针的函数指针
int const* (*const f5)(int) = some_func;  // 指向返回常指针的函数的常指针
```

我们把常类型指针又称 **底层指针** 、常指针变量又称 **顶层指针**

另外,C++ 中还提供了 `const_cast` 运算符来强行去掉或者增加引用或指针类型的 const 限定,不到万不得已的时候请不要使用这个关键字。

### 常参数

在函数参数里限定参数为常类型可以避免在类型里意外修改参数,该方法通常用于引用参数。此外,在类型参数中添加 const 修饰符还能增加代码可读性,能区分输入和输出参数。

```cpp
void sum(const std::vector<int> &data, int &total) {
  for (auto iter = data.begin(); iter != data.end(); ++iter)
    total += *iter;  // iter 是 const 迭代器,解引用后的类型是 const int
}
```

## 常成员

常成员指的是类型中被 const 修饰的成员,常成员可以用来限制对常对象的修改。其中,常成员变量与常量声明相同,而常成员函数声明方法为在成员函数声明的 **末尾** (参数列表的右括号的右边)添加 const 修饰符。

```cpp
// 常成员的例子
struct X {
  X();
  const int* p;  // 类型为 int* 的常成员
  int* const q;  // 类型为 const int* 的可变成员

  const int r() const;
  // 第一个 const 修饰返回值,而最后的 const 修饰的是这个成员函数。
};

X a;
*(a.p)++;  // 可行
// *(a.q)++; // 报错,不可修改 const int 类型变量

// 常成员函数的例子
const std::vector<int> c{1, 2};
// c.push_back(3); // 报错,不可访问常量的可变成员
// vector::push_back() 不是常成员
int s = c.size();  // vector::size() 是常成员,可以访问
```

## 常表达式 constexpr(C++11)

constexpr 说明符的作用是声明可以在编译时求得函数或变量的值,它的行为和 C 语言中的 const 关键字是一致的,会将变量结果直接编译到栈空间中。constexpr 还可以用来替换宏定义的常量,规避 [宏定义的风险](./basic.md#define) 。constexpr 修饰的是变量和函数,而 const 修饰的是类型。

> 实际上把 const 理解成 **"readonly"** ,而把 constexpr 理解成 **"const"** 更加直观。

```cpp
constexpr int a = 10;  // 直接定义常量

constexpr int FivePlus(int x) { return 5 + x; }

void test(const int x) {
  std::array<x> c1;            // 错误,x在编译期不可知
  std::array<FivePlus(6)> c2;  // 可行,FivePlus编译期可以推断
}
```

## 参考资料

-    [C++ 关键字——const](https://zh.cppreference.com/w/cpp/keyword/const) 
-    [C++ 关键字——constexpr](https://zh.cppreference.com/w/cpp/keyword/constexpr) 
+9 −5
Original line number Diff line number Diff line
STL 提供了大约 100 个实现算法的模版函数,基本都包含在 `<algorithm>` 之中,还有一部分包含在 `<numeric>``<functional>`
STL 提供了大约 100 个实现算法的模版函数,基本都包含在 `<algorithm>` 之中,还有一部分包含在 `<numeric>``<functional>`完备的函数列表请 [参见参考手册](https://zh.cppreference.com/w/cpp/algorithm) ,排序相关的可以参考 [排序内容的对应页面](../../basic/stl-sort.md)

常用函数:

-    `sort` :排序。 `sort(v.begin(), v.end(), cmp)``sort(a + begin, a + end, cmp)` ,其中 `end` 是排序的数组最后一个元素的后一位, `cmp` 为自定义的比较函数。
-    `find` :顺序查找。 `find(v.begin(), v.end(), value)` ,其中 `value` 为需要查找的值。
-    `find_end` :逆序查找。 `find_end(v.begin(), v.end(), value)`
-    `reverse` :翻转数组、字符串。 `reverse(v.begin(), v.end())``reverse(a + begin, a + end)`
-    `nth_element` :按指定范围进行分类,即找出序列中第 $n$ 大的元素,使其左边均为小于它的数,右边均为大于它的数。 `nth_element(v.begin(), v.begin() + mid, v.end(), cmp)``nth_element(a + begin, a + begin + mid, a + end, cmp)` 。复杂度 $O(n)$ 
-    `unique` :去除容器中相邻的重复元素。 `unique(ForwardIterator first, ForwardIterator last)` ,返回值为指向 **去重后** 容器结尾的迭代器,原容器大小不变。与 `sort` 结合使用可以实现完整容器去重
-    `random_shuffle` :随机地打乱数组。 `random_shuffle(v.begin(), v.end())``random_shuffle(v + begin, v + end)`
-    `sort` :排序。 `sort(v.begin(), v.end(), cmp)``sort(a + begin, a + end, cmp)` ,其中 `end` 是排序的数组最后一个元素的后一位, `cmp` 为自定义的比较函数。
-    `stable_sort` :稳定排序,用法同 `sort()`
-    `nth_element` :按指定范围进行分类,即找出序列中第 $n$ 大的元素,使其左边均为小于它的数,右边均为大于它的数。 `nth_element(v.begin(), v.begin() + mid, v.end(), cmp)``nth_element(a + begin, a + begin + mid, a + end, cmp)`
-    `binary_search` :二分查找。 `binary_search(v.begin(), v.end(), value)` ,其中 `value` 为需要查找的值。
-    `merge` :将两个(已排序的)序列合并。 `merge(v1.begin(), v1.end(), v2.begin(), v2.end())`
Loading