# Structure
structure 結構
是可以自訂義資料"結構"的方式
基本的宣告方式為:
```cpp=
#include<bits/stdc++.h>
using namespace std;
struct str{
//type anything you want here
}; //注意分號
int main(){
str var;//宣告變數
}
```
以上自訂義出的"str"為<font color="#FA0606">一種資料型態,並不是變數名稱</font>,所以定義變數時先打型態再打變數名稱。
:::info
:bulb: 大括號後面記得打分號
:::
## Member
成員
分為成員變數與成員函數,利用"."來進行呼叫
```cpp=
#include<bits/stdc++.h>
using namespace std;
struct node{
int x, y;//兩名型態為int的成員變數
void print(){ //一名回傳void的成員函數
cout << "HI!" << endl;
}
node dot(node a){ //一名回傳node的成員函數
node ans;
ans.x = x*a.x;
ans.y = y*a.y;
return ans;
}
};
int main(){
node var;
var.x = 1;
var.y = 2;
var.print();
}
```
要注意struct的成員變數的型態不能跟原本同名(node),會無法編譯。
在main定義變數後,使用 . 來進行呼叫
#### 與指標連用
當想要使用指標來呼叫成員時,有其他的寫法。
包含
struct(自定義結構)指標呼叫成員
map、pair 指標呼叫first,second
```cpp=
#include<bits/stdc++.h>
using namespace std;
struct node{
int x, y;//兩名型態為int的成員變數
void print(){ //一名回傳void的成員函數
cout << "HI!" << endl;
}
};
int main(){
node *var;//創建一名為node指標的變數
vector<pair<int, int>> arr(10);//pair陣列
map<int, int> mp;
var->x = 3;
var->y = 5;
var->print();
for(auto it = arr.begin(); it != arr.end(); it++){
cin >> it->first >> it->second;
}
for(auto it = mp.begin(); it != mp.end(); it++){
cout << it->first << it->second;
}
}
```
## Constructor
建構式
是用來快速建構變數(初始化)的工具,可以在宣告變數的同時設定好成員的狀態。
```cpp=
#include<bits/stdc++.h>
using namespace std;
struct node{
int x, y;
node(int a, int b){ //Constructor
x = a;
y = b;
}
void print(){
cout << x << " " << y << endl;
}
};
int main(){
int n = 10;
node var = node(3, 5);
vector<node> arr;
for(int i = 0; i < n; i++){
arr.push_back(node(i, i+3));
}
var.print();
for(int i = 0; i < n; i++){
arr[i].print();
}
}
```
建構式的名稱一定要與資料名稱同名,且建構式不一定只能有一個。
建構式也有另一種打法:
```cpp=
#include<bits/stdc++.h>
using namespace std;
struct node{
int x, y;
node(){} //???
// node() = default;
node(int a, int b): x(a), y(b){}//Constructor
void print(){
cout << x << " " << y << endl;
}
};
int main(){
int n = 10;
node var = node(3, 5);
vector<node> arr(n); //n項node,長什麼樣子?
for(int i = 0; i < n; i++){
arr[i] = node(i, i+3);
}
var.print();
for(int i = 0; i < n; i++){
arr[i].print();
}
}
```
要注意空建構式有時也是不可被省略的
## Operator
用來定義運算子,當自訂義資料結構要與其他變數(無論類型)做運算時,需要對運算子定義出詳細的運算規則。
概念: a+b的過程
```cpp=
#include<bits/stdc++.h>
using namespace std;
struct node{
int x, y;
node(){}
node(int a, int b): x(a), y(b){}
node operator*(const node &b) const {
return node(x*b.x, y*b.y);
}
void print(){
cout << x << " " << y << endl;
}
};
int main(){
node a(3,5), b(4,6);
node c = a*b;
c.print();
}
```
# Lambda
就是函數,一個酷酷的語法糖
## 語法
```cpp=
[](int i){
return i + 1;
}
```
其中的[]裡面可以放=或&這兩種,=代表的是pass by value,&代表的是pass by reference。
如果這樣打的話就是全部pass by reference
```cpp=
[&](int i){
return i + 1;
}
```
如果這樣打的話就是全部pass by value
```cpp=
[=](int i){
return i + 1;
}
```
也可以限定只要pass by reference(value)某些東西,像是下面的就是只reference a和b兩個變數,c用pass by value
```cpp=
[&a, &b, c](int i){
return i + 1;
}
```
常用範例 :
像是你要按照某個特定的順序排序的時候
```cpp=
vector<int> a, b;
sort(a.begin(), a.end(), [](int i, int j){
return i > j;
});
sort(a.begin(), a.end(), [&](int i, int j){
return b[i] > b[j];
});
```
## 賦值
```cpp=
auto foo = [&](int i){
return i + 1;
};
cout << foo(1);
```
可以打一個auto然後打一個變數代表這個函數,這樣這個變數就代表一個lambda function
:::info
:bulb: 大括號後面記得打分號
:::
因為真正的變數型態很長,所以通常都會打auto,後面會提到不能打auto的情況
## 指定回傳
```cpp=
auto foo = [&](int i) -> int {
return i + 1;
};
cout << foo(1);
```
像這樣在後面打一個箭頭,然後再打回傳型態就可以指定要回傳什麼,上面的範例為回傳int
常用範例 :
像是遇到條件很長的時候
```cpp=
auto bound = [&](int i, int j) -> bool {
return 0 <= i && i < n && 0 <= j && j < m;
};
```
## 資料型態
```cpp=
function<void(int)>
```
function<> 代表你要宣告一個lambda function,裡面放的是資料型態,void代表這是一個void function,()裡面放的是你要傳入的變數型態,像是void(int)代表一個void的函數,然後要傳入一個變數int
## 遞迴
不能使用auto的情況來了
如果你要函數遞迴的話,因為編譯器不知道函數會回傳什麼,所以要先給那個函數一個型態才能使用
```cpp=
function<void(int)> foo = [&foo](int i){
if (i > 10){return;}
cout << i << endl;
foo(i + 1);
};
```
**程式碼範例變數名稱常用foo 跟bar
根本是父權遺毒
應該要用
mu 跟ma**
常用範例 :
如果要做dfs的時候
```cpp=
function<void(int)> dfs = [&](int p){
vis[p] = true;
for (int x: g[p]){
if (vis[x]){continue;}
dfs(x);
}
};
```