暑假資讀[3]

王政凱

講師介紹

  • 227王政凱
  • ck_platypus
  • 建中資訊 學術兼外交
  • 地科讀書會講師
  • 我不會資訊
  • FB:王政凱
  • IG:@kennywang2017

基礎資料結構

What is 資料結構?

Data Structure,是電腦中儲存、組織資料的方式。

「陣列」即是一種最簡單的資料結構

1 10 2 4 19 22 22 5 7 11

資料結構+演算法=程式

一位偉大的人曾經說過

Standard Template Library

  • c++標準模板庫
  • 簡稱STL
  • 裡面有一大堆寫好的函式、容器
  • 要用之前要先引入
  • #include <你要的函式庫>
  • 大家可以去c++.com尋寶

你的程式碼可能會長這樣

#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <utility>
#include <bitset>
#include <climits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;

int main(){
  return 0;
}

但也可以長這樣

#include <bits/stdc++.h>
using namespace std;

int main(){
  return 0;
}

在開始講資料結構之前

iterator

  • 迭代器
  • 一種資料型態
  • 儲存的是記憶體位置
  • 和pointer十分相像
  • 指向STL容器中的物件
  • prev(it), it--
  • next(it), it++

vector

\(\overrightarrow{v}=(x, y)\)

vector

又稱dynamic array,可以動態開記憶體

使用時機:

       1.當你的二維陣列每個陣列長度不同

       2.當你要將陣列傳進函式但你不會指標(我)

       3.想讓程式碼色彩鮮豔

       4.任何時候

宣告

vector<int> v1;
vector<int> v2(10);
vector<int> v3(1989, 64);
vector<int> v4={7, 1, 2, 2};
vector<vector<int> > vv[100]

引入

#include <vector>
#include <vector>
using namespace std;

int main(){
  vector<int> v;
  v.size();
  bool emp=v.empty();
  v.resize(n);
  v[i] = x;
  v.push_back(x);
  v.emplace_back(x);
  v.pop_back(x);
  v.clear();
  fill(v.begin(), v.end(), x);
  sort(v.begin(), v.end());
  int lb = lower_bound(v.begin(), v.end(), x)-v.begin();
  int ub = upper_bound(v.begin(), v.end(), x)-v.begin();
  return 0;
}

vector扣的

lower_bound

在一個已排序好的陣列(vector)裡面,

找到大於等於某數的最小元素的迭代器,

若不存在則回傳末位置之迭代器

upper_bound

在一個已排序好的陣列(vector)裡面,

找到大於某數的最小元素的迭代器,

若不存在則回傳末位置之迭代器

蛤~

怎麼做

二分搜

把陣列二等分,並判斷目標物應該在前半段還是後半段

1 3 4 6 8 10 12 13
1 3 4 6
8 10 12 13
1 3
4 6
8 10
12 13

1

3

4

6

8

10

12

13

二分搜

使用時機:

    若有某性質arr[i]符合則arr[j];j>=i也符合,

    可以用二分搜快速找到符合此性質的第一個元素。

#include <vector>
using namespace std;

int main(){
  vector<int> v={1,3,4,6,8,10,12,13};
  int l=0, r=8, target=9;
  while(l!=r){
    int mid=(l+r)/2;
    if(v[mid]>=target) r=mid;
    else l=mid+1;
  }
  return 0;
}

二分搜扣的

例題

可以回去找之前陣列的例題自己玩玩看vector

先不要用lower_bound,大家自己寫寫看二分搜吧

沒那麼直覺的二分搜

沒那麼直覺的二分搜_2

pair

pair

就只是把兩個東西包起來

使用時機:

       1.儲存平面坐標系上的點、向量

       2.只有兩個東西寫struct很浪費

宣告

pair<int, int> p1;
pair<string, int> p2=make_pair("hsu", 69);
pair<int, int> p3={1911, 1010}
pair<pair<int, int>, int> p4=make_pair({1,2}, 3)

引入

#include <utility>
#include <utility>
#include <vector>
using namespace std;

int main(){
  pair<int, int> p;
  p.first = 1;
  p.second = 2;
  vector<pair<int, int> > v;
  v.push_back(make_pair(1, 2));
  v.push_back({3, 4});
  v.emplace_back(5, 6);
  return 0;
}

扣的

#include <utility>
using namespace std;

pair<int, int> operator+ (pair<int, int> a, pair<int, int> b){
  return make_pair(a.first+b.first, a.second+b.second);
}
int main(){
  pair<int, int> a=make_pair(1,2);
  pair<int, int> b=make_pair(3,5);
  cout << (a+b).first << " " << (a+b).second << endl;
  //4 7
  return 0;
}

自定義運算子扣的

例題

好像沒有只有pair的例題

No judge

請用運算子重載做出以下兩種運算

1.平面向量的內積

2.平面向量的外積

stack, queue, deque

stack, queue, deque

stack(堆疊):first_in_last_out

 

 

queue(佇列):first_in_first_out

 

 

deque(雙向佇列):顧名思義

宣告

stack<int> st;
queue<int> qu;
deque<int> dq;

引入

#include <stack>
#include <queue>
#include <deque>
#include <stack>
using namespace std;

int main(){
  stack<int> st;
  st.push(1);
  int stt = st.top();
  st.pop();
  int stsz = st.size();
  bool ste = st.empty();
  return 0;
}

stack扣的

#include <stack>
using namespace std;

int main(){
  int st[100], top = 0;
  st[top++] = 1;
  int stt = st[top-1];
  top--;
  int stsz = top;
  bool stemp = (top==0);
  return 0;
}

另一種stack扣的

#include <queue>
using namespace std;

int main(){
  queue<int> qu;
  qu.push(1);
  int quf = qu.front();
  int qub = qu.back();
  qu.pop();
  int qusz = qu.size();
  bool stemp = qu.empty();
  return 0;
}

queue扣的

#include <deque>
using namespace std;

int main(){
  deque<int> dq;
  dq.push_front(1);
  dq.push_back(2);
  int dqf = dq.front();
  int dqb = dq.back();
  dq.pop_front();
  dq.pop_back();
  int dqsz = dq.size();
  bool stemp = dq.empty();
  return 0;
}

deque扣的

例題

set

戰爭之神、風暴之神

set

集合,但STL中的set與數學上不同之處為其是有序的

支援的操作:

       1.把元素丟進去集合(不重複)

       2.尋找集合中大於等於某元素的最小元素

set

以上操作如果用陣列做,複雜度可做到以下兩種:

    O(1)插入、O(n)查詢

    O(n)插入、O(log n)查詢

好像不是很快

自己去查 Binary Search Tree

STL中的set可以做到O(log n)插入、O(log n)查詢

宣告

set<int> s;
multiset<int> ms

引入

#include <set>
#include <set>
using namespace std;

int main(){
  set<int> s;
  s.insert(1);
  set<int>::iterator it=s.find(1);
  int scnt = s.count(1);
  s.erase(1);
  s.erase(it);
  for(int i:s){};
  for(auto it=s.begin();it!=s.end();it++){};
  int smin = s.begin();
  int smax = s.rbegin();
  int slb = s.lower_bound(1);
  int sub = s.upper_bound(1);
  int ssz = s.size();
  bool semp = s.empty();
  return 0;
}

set扣的

#include <set>
using namespace std;

int main(){
  multiset<int> ms;
  ms.insert(1);
  ms.insert(1);
  ms.insert(1);
  int scnt = ms.count(1);
  multiset<int>::iterator it=ms.find(1);
  ms.erase(it);
  ms.erase(1);
  return 0;
}

multiset扣的

例題

map

map

跟set很像,但是每個元素為pair型態,

且find、erase、lower_bound等函式僅針對pair.first

可以把map想成是一對一映射的加強版set

宣告

map<int, int> m;

引入

#include <map>
#include <map>
using namespace std;

int main(){
  map<int, int> m;
  m.insert(1,2);
  m[1]=2;
  for(auto it=m.begin();it!=m.end();it++){
    pair<int, int> = make_pair(it->first, it->second);
  }
  return 0;
}

map扣的(set有的map都有)

priority queue

priority queue

優先佇列,但事實上和queue沒啥關係

支援的操作:

       1.把元素丟進去集合

       2.尋找集合中最(大)值

       3.刪除集合中最(大)值

()內判斷條件可自定義

priority queue

這些事好像set也做得到。

但是......

O(1)查詢、O(log n)插入、O(log n)刪除

內部實作 heap

heap原理

構造一個完全二元樹,並保證父節點必(大)於子節點

21

20

18

11

9

7

4

5

2

13

6

3

heap原理(加入

從完全二元樹的末端插入元素,判斷是否(大)於父節點並交換

21

20

18

11

9

7

4

5

2

13

6

3

19

heap原理(加入

從完全二元樹的末端插入元素,判斷是否(大)於父節點並交換

21

20

18

11

9

7

4

5

2

19

6

3

13

heap原理(加入

從完全二元樹的末端插入元素,判斷是否(大)於父節點並交換

21

20

18

11

9

7

4

5

2

19

6

3

13

heap原理(加入

從完全二元樹的末端插入元素,判斷是否(大)於父節點並交換

21

20

18

11

9

7

4

5

2

19

6

3

13

heap原理(刪除

刪除根節點,並以最末位節點代替其位置,並往下重新調整

21

20

18

11

9

7

4

5

2

19

6

3

13

heap原理(刪除

刪除根節點,並以最末位節點代替其位置,並往下重新調整

20

18

11

9

7

4

5

2

19

6

3

13

heap原理(刪除

刪除根節點,並以最末位節點代替其位置,並往下重新調整

13

20

18

11

9

7

4

5

2

19

6

3

heap原理(刪除

刪除根節點,並以最末位節點代替其位置,並往下重新調整

13

20

18

11

9

7

4

5

2

19

6

3

#include <queue>
using namespace std;

struct cmp{
  bool operator()(int a, int b){
    return a<b;
  }
};
int main(){
  priority_queue<int> pq;
  pq.push(1);
  int pqt = pq.top();
  pq.pop();
  priority_queue<int, vector<int>, cmp> pq2;
  return 0;
}

priority_queue扣的

例題

實作時間

C++標準模板庫

#include <algorithm>
using namespace std;

int main(){
  int arr[10]={1,2,3,4,5,6,7,8,9,10};
  swap(arr[1], arr[8]);
  sort(arr, arr+10);
  fill(arr, arr+10, 1);
  int* lb = lower_bound(arr, arr+10, 1);
  int* ub = upper_bound(arr, arr+10, 1);
  int* maxx = max_element(arr, arr+10);
  return 0;
}

#include<algorithm>

#include <cmath>
using namespace std;

int main(){
  double a = abs(-5);
  double b = ceil(3.4);
  double c = floor(2.9);
  double d = round(4.5);
  double e = log(7122);
  double f = log2(2147483648);//log(2147483648)/log(2);
  double g = pow(2, 10);
  double h = sqrt(7122);//pow(7122, 0.5);
  double i = sin(2);
  double j = cos(1);
  double k = tan(3);
  double l = asin(0.5);
  double m = acos(-1);
  double n = atan(-3);
  double o = tgamma(10);//(n-1)!
  return 0;
}

#include<cmath>

#include <complex>
using namespace std;

int main(){
  complex<double> a(3, -4);
  complex<double> b(-0.5, pow(3, 0.5)/2);
  complex<double> c = a*b;
  double d = real(c);
  double e = imag(c);
  double f = abs(c);
  double g = arg(c);
  return 0;
}

#include<complex>

#include <climits>
using namespace std;

int main(){
  int int_min = INT_MIN;
  int int_max = INT_MAX;
  int unsigned_int_max = UINT_MAX;
  long long int long_long_int_min = LLONG_MIN;
  long long int long_long_int_max = LLONG_MAX;
  long long int unsigned_long_long_int_max = ULLONG_MAX;
  return 0;
}

#include<climits>

Made with Slides.com