# 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); } }; ```