永遠寫不出 pD 的那個人

aka Repkironca

大社課 - 10

STL introduction、vector、deque

ㄟ這個模板看起來好酷喔

好圓好圓的 Content

01.

What Is Data Structure

01.

What Is Data Structure

What Is Data Structure

In computer science, a data structure is a data organization, management, and storage format that enables efficient access and modification

:什麼鬼啦,講人話,在官腔幾點ㄉ,你是資訊之芽嗎

  • 一種 有系統 的資料儲存、組織 方法 / 策略
  • 大多是靠最基本的變數型態和語法刻出來的
  • 內建許多功能(function),方便我們對其操作
  • 能夠 節省時間、縮小空間

舉例來說,array 是一種 Data Structure

2 4 6 8 10 12 14 16 18 20
0x25
0x26
0x27
0x28
0x29
0x2A
0x2B
0x2C
0x2D
0x2E
int arr[10];
for (int i = 1; i <= 10; i++) arr[i] = 2*i;

如果你有乖乖上小社,linked_list 也是一種 Data Structure

struct node{
  long long value;
  node *next = nullptr;
};

struct linked_list{
  unsigned int length = 0;
  node *root = nullptr;
  node *end = nullptr;
  bool isempty = true;

  bool empty(){
    return isempty;
  }

  unsigned int size(){
    return length;
  }

  void push_front (long long num){
    node *tmp = new node;
    tmp->value = num;
    if (!isempty) tmp->next = root; //root 被往後推一格
    if (length == 0) end = tmp; //什麼都沒有,這點是 root 加 end
    else if (length == 1) end = root; //root 要變成 end 了
    root = tmp;
    length++;
    isempty = false;
  }

  void push_back(int tar){
    node *tmp = new node;
    tmp->value = tar;
    length++;
    if (isempty){
      root = tmp;
      end = tmp;
      isempty = false;
      return;
    }
    end->next = tmp;
    end = tmp;
  }

  void print_list (){
    if (!isempty){
      node *now = new node;
      now = root;
      cout << now->value << ' ';
      while (now->next != nullptr){
        now = now->next;
        cout << now->value << ' ';
      }
      delete now;
    }
  }

  node *find_node(int loc){
    if (loc == 0) return root;
    if (loc == size()-1) return end;
    node *tmp = root;
    for (int i = 0; i < loc && i < size(); i++) tmp = tmp->next;
    return tmp;
  }

  void insert (int loc, long long tar){
    node *now = new node;
    now->value = tar;
    length++;
    if (empty()){
      root = now;
      end = now;
      isempty = false;
    }else if (loc == 0){
      now->next = root;
      root = now;
    }else if (loc == size()-1){
      end->next = now;
      end = now;
    }else{
      now->next = find_node(loc)->next;
      find_node(loc)->next = now;
    }
  }

  void erase_by_location (int loc){
    if (loc == 0) root = root->next;
    else R_erase_by_location(find_node(loc-1), loc);
  }
  void R_erase_by_location (node *last, int loc){
    if (loc == size()-1){
      end = last;
      last->next = nullptr;
    }else{
      last->next = last->next->next;
    }
    length--;
    if (length == 0) isempty = true;
  }
};

root

5

17

3

end

之前搞我搞得很開心的二元搜尋樹,亦為 Data Sturcture

〞

蛤真的假的,所以我們每個

Data Sturcture 都要用手刻嗎

– 現在為你介紹 C++ 最偉大的發明之一

02.

What Is STL

:斯顛大得天普類特賴不噁瑞

STL

  • Standard Template Library,標準模板庫

  • 主要包含下面四種東西:

-演算法 Algorithm,e.g. sort()、swap()

-容器 Containers,e.g. vector、queue

-函式 Functions,function Object,去問 Aaw cuz 我不會

-迭代器 Iterator,嗯對,就是 iterator

STL

-演算法 Algorithm,e.g. sort()、swap()

-容器 Containers,e.g. vector、queue

-函式 Functions,老實說我也不知道包含哪些

-迭代器 Iterator,嗯對,就是 iterator

-演算法 Algorithm

-容器 Containers

-函式 Functions

-迭代器 Iterator

整個 STL 裡的精華

11/18,今天

12/2,二段後

12/16,大社賽前

  • vector
  • deque
  • stack
  • list
  • queue

自我鞭屍時間

容器是 STL 的精華,或著說 STL 大多是由 Data Structure 組成的

BUT

STL 跟 Data Structure 並不等價

簡報製作者是白癡,他想說 "手刻 Data Structure"

03.

Vector

  • 中文叫他 向量

這是 vector

  • 我唬爛的中文是 伸縮陣列

這也是 vector

  • 符號的話,大概會長這樣$$\overrightarrow{AB}$$
  • 有起點與終點,具方向
  • 常見的表示法長這樣
vector <int> vec;
  • 有 begin() 跟 end()
  • 這才是我今天要講的

Vector

  • 功能類似 array,不過其 長度是可變的
int arr[MAXN]; // 一旦宣告完就不能變,只有 MAXN 格
vector <int> vec; // 可以不設定長度,隨時能夠改變
  • 本身是一個 物件,而非指標
  • 除非你是直接砸萬用標頭檔,否則要記得 include 進來
#include <vector>
#include <bits/stdc++.h>

萬用標頭檔,但建中電腦會爛

最安全不會爛掉的用法

Vector 宣告

vector <變數型態> 命名;

vector <int> vec;
// 一個存 int 的 vector,命名為 vec
vector <bool> judge;
// 一個存 bool 的 vector,命名為 judge

那我可以開多維 vector 嗎?

vector <vector <int> > graph;
// 一個vector,裡面存很多個 vector <int>

我哪有差

你開心就好

把 x 加進 vector 尾端

vector 名稱.push_back(x)

vector <int> vec;
vec.push_back(5);

\(\leftarrow\) 頭

 尾 \(\rightarrow\) 

vec.push_back(3);
vec.push_back(7);
vec.push_back(9);

5

vec[0]

3

vec[1]

7

vec[2]

9

vec[3]

對 vector 取值

vector 名稱[index]

\(\leftarrow\) 頭

 尾 \(\rightarrow\) 

5

vec[0]

3

vec[1]

7

vec[2]

9

vec[3]

你在 array 中怎麼做,在 vector 中就怎麼做

cout << vec[1] << '\n';
cout << vec[0] << '\n';
cout << vec[4] << '\n';

5

Runtime Error!

3

把尾端元素踢掉

vector 名稱.pop_back();

\(\leftarrow\) 頭

 尾 \(\rightarrow\) 

5

vec[0]

3

vec[1]

7

vec[2]

9

vec[3]

for (int i = 0; i < 4; i++) vec.pop_back();

把尾端元素踢掉

vector 名稱.pop_back();

\(\leftarrow\) 頭

 尾 \(\rightarrow\) 

5

vec[0]

3

vec[1]

7

vec[2]

for (int i = 0; i < 4; i++) vec.pop_back();

把尾端元素踢掉

vector 名稱.pop_back();

\(\leftarrow\) 頭

 尾 \(\rightarrow\) 

5

vec[0]

3

vec[1]

for (int i = 0; i < 4; i++) vec.pop_back();

把尾端元素踢掉

vector 名稱.pop_back();

\(\leftarrow\) 頭

 尾 \(\rightarrow\) 

5

vec[0]

for (int i = 0; i < 4; i++) vec.pop_back();

把尾端元素踢掉

vector 名稱.pop_back();

\(\leftarrow\) 頭

 尾 \(\rightarrow\) 

for (int i = 0; i < 4; i++) vec.pop_back();
vec.pop_back();

空的,Runtime Error!

訪問尾端元素

vector <int> vec;
for (int i = 0; i < 10; i++) vec.push_back(i);

while (!vec.empty()){
  cout << vec.back() << " out of this vector\n";
  vec.pop_back();
}
vector <int> vec;
vec.push_back(8);
cout << vec.back() << '\n'; // 8

vector 名稱.back()

直接回傳該元素

檢測 vector 是否為空

vector 名稱.empty();

回傳一個 bool,若為 true 表示 vector 中沒東西

vector <int> vec;
cout << vec.empty() << '\n'; // 1
vec.push_back(6);
cout << vec.empty() << '\n'; // 0
vec.pop_back();
cout << vec.empty() << '\n'; // 1

檢測 vector 長度

vector 名稱.size();

回傳一個 size_t,反正就是 unsigned int 的一種

vector <int> vec;
cout << vec.size() << '\n'; // 0
for (int i = 0; i < 10; i++) vec.push_back(i);
cout << vec.size() << '\n'; // 10
for (int i = 0; i < 5; i++) vec.pop_back();
cout << vec.size() << '\n'; // 5

快速初始化

  • vector <變數型別> 命名(初始大小, 統一填入什麼);
vector <vector <int> > vec(MAXN, vector <int>(MAXN, 5));

// 一個 vector,裡面裝著 MAXN 個 vector <int>
// 其中每個裡面的 vector <int>,大小皆為 MAXN,初始值為 5
  • 同 array,直接用大括號列出初始元素
vector <int> vec = {0, 2, 4, 6, 8, 10, 12, 14};
vector <int> vec(MAXN);

=

int arr[MAXN];
vector <int> vec(MAXN, 5);

=

int arr[MAXN];
for (int i = 0; i < MAXN; i++) arr[i] = 5;

食酢

可能有用的提示 (1):

這題的輸入很無聊,要用這個方法吃

char tmp;
while (cin >> tmp && !cin.eof()){

}

可能有用的提示 (2):

vector 名稱.clear(); 能快速清空整個 vector

vec.clear();

AC CODE 可以點我

#include <bits/stdc++.h>
#define icisc ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
using namespace std;

int main (){
  icisc
  char tmp;
  vector <char> T, F;
  while (cin >> tmp && !cin.eof()){
    if (tmp == '*'){
      if (T.size() >= F.size()) for (auto to:T) cout << to << ' ';
      else for (auto to:F) cout << to << ' ';
      cout << '\n';
      T.clear(); // 清空 T
      F.clear(); // 清空 F
    }else{
      if (tmp >= '0' && tmp <= '9') T.push_back(tmp);
      else F.push_back(tmp);
    }
  }
}

AC CODE

那我可以也用 array 做啊,題目都會給 MAXN 

我哪有差

我哪次有差

我怎麼可能有差

你開心就好

BUT 你會被我傳教

vector 教榮光不滅

為何 Vector > Array

  • Vector 是可伸縮的,彈性較大、省空間
  • 大部分操作都能在 O(1) 內完成

[ 官方一點的理由 ]

為何 Vector > Array

  • Vector 本身是 物件,可以達成各種 Array 不能的操作,超級爽

[ 正常一點的理由 ]

vector <int> vec_1, vec_2;
for (int i  = 0; i < 10; i++) vec_1.push_back(i*2);
vec_2 = vec_1;

直接砸等號

vector <int> func(vector <int> vec){

}

直接作為

參數 / 回傳

直接做比較

if (vec_1 != vec_2){

}

為何 Vector > Array

  • 跟 Array 比起來,初始化超級快

[ 正常一點的理由 ]

[創造一個大小為 MAXN 的二維布林陣列,初始化為 true]

vector <vector <bool> > visited(MAXN, vector <bool>(MAXN, true));
bool graph[MAXN][MAXN];
for (int i = 0; i < MAXN; i++)
  for (int j = 0; j < MAXN; j++)
    graph[i][j] = true;
  • 裡面什麼都可以塞,自由度很高
vector <set <int> > vec(MAXN, set <int>());

為何 Vector > Array

  • 因為初始化可以壓成一行,特別帥

[ 超級奇怪的理由 ]

  • 因為可以砸 iterator,iterator 打起來很爽
  • 因為他很有魅力
#define pbpii pair <bool, pair <int, int>>
vector <pbpii> judge(MAXN, {false, {0, 0}});
for (vector <int> ::iterator to = vec.begin(); to != vec.end; to++){}
// 或
for (auto to:vec){}

04.

Deque

Deque

  • Double Ended QUEue,中文是 雙向佇列
  • 念法同 deck,雖然你要唸 de-queue 我也不會阻止你

不過 dequeue 是 Java 的東西

  • 可以想像成對頭尾都能 O(1) 操作的 vector
  • 天底下哪有這麼好的事,雖然我寫 O(1),但它的 常數比 vector 大

\(註_2\):常數的話,可以想像成 這個東西本身運行 需要的時間

Deque 宣告

deque <變數型態> 命名;

vector <bool> deq;
// 一個存 bool 的 deque,命名為 deq
deque <vector <int>> devec;
deque <deque <int>> dedeque;

當然

如果你想

這些奇怪事情都能達到

我懶得教的部分

  • 取值
  • 小括號初始化
  • .size()
  • .empty()

做法都跟 vector 一樣,我要直接跳過

對元素做操作

.push_back(x)

.push_front(x)

.pop_back(x)

.pop_front(x)

把 x 插進尾端

把 x 插進前端

把尾端元素踢除

把前端元素踢除

deque <int> deq(2, 0);
deq[1] = 1; // {0, 1}
deq.push_back(2); // {0, 1, 2}
deq.push_front(1); // {2, 0, 1}
deq.pop_back(); // {0}
deq.front(); // {1}

Jan. 29. 2023 ~ Feb. 3. 2023

Coming Soon...

The End.

不過幫我投票一下

Made with Slides.com