C++語法

怎麼寫C++?

IDE

Dev-C++

codeblocks

Hello, world!

#include <iostream>
using namespace std;
int main(){
    cout << "Hello, world!\n";
}

建議全部自己打一次

#include<iostream>

引入已經寫好的程式 像cout

using namespace std;

把std::cout變成cout

int main()

程式一開始進入的地方

變數

儲存資料的東西

型別

int

整數

範圍:

-2^{31}
2^{31}-1

~

佔用空間: 4 Bytes

float

浮點數

精準至小數點後七位

佔用空間: 4 Bytes

char

字元

佔用空間: 1 Bytes

用ASCII碼儲存

'   '表示一個字元

型別

int

整數

範圍:

-2^{31}
2^{31}-1

~

佔用空間: 4 Bytes

float

浮點數

精準至小數點後七位

佔用空間: 4 Bytes

char

字元

佔用空間: 1 Bytes

用ASCII碼儲存

'   '表示一個字元

string

字串

可以儲存多個字元

"   "表示一個字串

bool

布林(真假)值

儲存true(1)和false(0)

佔用空間: 1 Bytes

宣告

//變數型別 變數名稱;
int x = 0;
float y = 1.5;
char c = 'c';
bool b = 1;
string s = "Hello, world!";

輸入輸出

#inculde<iostream>
using namespace std;
int main(){
    int a, b;
    cin>>a>>b;
    cout<<"a:"<<a<<" b:"<<b<<'\n';
}

運算子

int x;
x = 3;
x = 2 + 5;//x = 7
x = x - 1;//x = 6
x = 3 * x;//x = 18
x = x / 5;//x = 3
x = x % 3;//x = 0

+

- 減

*

% 取餘

/ 除

整數/整數是取商

= 指定

()括號

運算子

int x;
x = 3;
cout<<x++<<'\n';//cout 3, x = 4
cout<<++x<<'\n';//cout 5, x = 5
x -= 1;
x *= 3;
x %= 2;

++ 遞增

-- 遞

運算後指定

BMI計算機

輸入身高(公分)、體重(公斤),計算出BMI

BMI=體重(kg) \div 身高^2(m)

Sample Input

180 70

Sample output

21.6049

型別轉換

時間轉換

輸入秒,將秒轉換成 小時:分鐘:秒 的格式輸出

Sample Input

350

3601

19855

 

Sample output

0:5:50

1:0:1

5:30:55

邏輯運算子

< 小於

> 大於

<= 小於等於

>= 大於等於

==相等

(注意不是=)

!=不相等

IF

if(條件){
    你要執行的東西
}
例如:
int a = 5, b = 4;
if(a > b){
   cout<<"a > b\n";
}

邏輯運算子

&& 邏輯AND

|| 邏輯OR

! 邏輯NOT

AND和OR可以用來連接兩個條件

   A&&B B = TRUE B = FALSE
A = TRUE     TRUE    FALSE
A = FALSE    FALSE    FALSE
    A||B B = TRUE B = FALSE
A = TRUE     TRUE     TRUE
A = FALSE     TRUE    FALSE
         -  A = TRUE  A = FALSE
       !A false    true

邏輯運算子

int a;
cin>>a;
if(4 <= a && a < 7){
    cout<<"4 <= a < 7\n";
}
if(4 <= a < 7){
	cout<<"4 <= a < 7\n";
}

bool結果只有 1 or 0

else and else if

/*當上方的if(else if)的條件判斷是false時
才會判斷(執行)下面的else if(else)*/
int a, b;
cin>>a>>b;
if(a>b){
    cout<<"a>b\n";
}
else if(a<b){
    cout<<"a<b\n";
}
else{
    cout<<"a==b\n";
}

成績等第

輸入一個正整數\ x \ 代表此學生的成績\\然後有四個正整數a, b,c,d代表判斷標準\\運用下表將成績轉換成等第
x\ge a\ 優\\ a>x\ge b\ 甲\\ b>x\ge c\ 乙\\ c>x\ge d\ 丙\\ x< d \ 丁\\ a>b>c>d

INPUT

OUTPUT

75 90 80 70 60

66 80 68 67 66

99 100 98 50 40

迴圈

讓程式重複執行

while

int i,n;
cin>>n;
i=0;
while(i<n){
    cout<<i<<' ';
    i++;
}
while(條件){
    要執行的東西;
}

for迴圈

int n;
cin>>n;
for(int i=0;i<n;i++){
    cout<<i<<' ';
}
for(第一次進入;條件;每次結束){

}

1

3

2

4

5

break

int n;
cin>>n;
while(1){
    cout<<i++<<' ';
    if(i>=n) break;
}

跳出迴圈

最大最小值

輸入一個長度為n的數列A\\輸出A中的最大值與最小值
輸入 \\第一行有一正整數n代表A的長度\\第二行有n個整數,第i個整數代表A[i]的數值
輸出\\A中的最大值\ 最小值

5

 10 -1 25 33 -20 

2

1 1

33 -20


1 1

3n+1猜想

輸入

n

如果   是奇數

n
n=3n+1

如果   是偶數

n
n=n\div2
n

輸出過程中   的數值直到

n=1

INPUT

3

4

OUTPUT

3 10 5 16 8 4 2 1

4 2 1

階梯

輸入                 印出    階寬度   高度   的階梯

n,\ x,\ y
n
x
y
----
----
    ----
    ----
        ----
        ----
n=3,x=4,y=2
--
  --
    --
      --
        --
          --
n=6,x=2,y=1

雪花

輸入    依照範例輸出印出大小             的圖形

n\times n
n

為奇數

...
...
...
.#.#.
#...#
.....
#...#
.#.#.
.##.##.
#.#.#.#
##...##
.......
##...##
#.#.#.#
.##.##.
n=3
n=5
n=7
n

陣列

可以儲存很多變數的東西

string 是一種陣列

宣告

其實就是加個中括號

變數型別 變數名稱[陣列大小];
int a[100];
string s[100];
char c[10000];
bool b[10];

宣告

int a[5]={0,1,2,3,4};
string s[2]={"Hello","ABC"};

指定預設值

在函數內沒指定值時會爛掉

但放全域會幫你設預設值

放函數內約可開幾百萬

放全域可以開到千萬

使用

int a[100];
for(int i=0;i<100;i++){
    cin>>a[i];
}
for(int i=0;i<100;i++){
    cout<<a[i]<<' ';
}

陣列的索引從0開始

所以如果陣列大小是n,可用範圍就是0~n-1

多維陣列

int a[100][100];
char c[50][50][50];

交換

INPUT

第一行有兩個正整數n q

第二行有n個整數代表數列A的值

接下來有q行,每一行有兩個正整數i j

代表要交換的數的編號

編號從1開始

OUTPUT

輸出操作後的數列

給一個數列A,接著有q個操作每次操作會交換數列裡的兩個編號的數,在最後輸出操作後的數列

n < 10^6 ,\ q< 10^6

5 4

5 4 2 3 1

1 3

1 2

3 4

1 5

1 2 3 5 4

加密

給定一個字串S與一個正整數k,將字串的每個字變成該英文字母的後k個,如果字母順序+k>z,從a繼續。

INPUT

第一行一個n代表字串長度與一個k

第二行有一個字串,保證每個字元皆為小寫英文字母

OUTPUT

輸出加密文字

5 2

abcde

6 5

abcxyz

cdefg

 

fghcde

眾數

眾數的定義是在一個數列出現次數最多的數

給定一個數列並找出它的眾數

INPUT

第一行一個正整數n代表數列長度

第二行有n個數,代表數列的值

OUTPUT

輸出眾數

5

3 2 2 2 1

10

9 9 8 3 4 7 1 3 4 9

2

 

9

函式

回傳類型 函數名稱(參數類別 參數名稱,...){
    return 要回傳的東西;
}

int add(int a,int b){
    return a+b;
}

struct

#include<iostream>
#include<cmath>
struct Point{
    int x,y;
    double length(){
        return sqrt(x*x+y*y); 
    }
};
int main(){
    Point a;
    cin>>a.x>>a.y;
    cout<<a.length()<<'\n';
}

遞迴

自己呼叫自己

像這樣

int f(int n){
    if(n==1||n==2) return 1;
    return f(n-1)+f(n-2);
}

要記得加終止條件

遞迴枚舉(爆搜)

先看例題

tcirc d007

枚舉所有的子集的和

執行次數(時間複雜度)

O(2^n)

堆疊stack

先進後出

堆疊stack

佇列queue

先進先出

二分搜

每次把區間切半

二分搜

bool f(int l,int r,int x){
    while(l<r){
    	int m=(l+r)/2;
        if(a[m]==x) return 1;
        if(a[m]<x) l=m+1;
        else r=m-1;
    }
    return 0;
}

#include<algorithm>

很多好用的內建函式

min()、max()、sort()、lower_bound()

指標*

儲存變數位址的變數

宣告方法

int* a;
char *c;

使用

int a=5;
int* p=&a;
cout<<*p;//5
(*p)++;
cout<<*p;//6

動態分配記憶體

分配記憶體給指標

int *p=new int;
char* c=new char;

指標陣列

int *a=new int[100];

delete

int *p=new int;
delete p;

參考&

取別的變數名

int a=5;
int& b=a;
cout<<b;//5
b++;
cout<<a;//6

貪心演算法

greedy

換錢問題

將n塊錢換成面額 1、5、10、50的硬幣

最少換到的硬幣數

排序後greedy

priority_queue

宣告:priority_queue<int> 取最大值

priority_queue<int,vector<int>,greater<int>> 取最小值

top() 裡面的最大(小)值

pop() 刪除最大(小)值

可以取最大值的東西

#include<queue>

#include<iostream>
#include<queue>
using namespace std;
int main(){
    priority_queue<int> pq;
    pq.push(1);
    pq.push(3);
    cout<<pq.top()<<'\n';//3
    pq.pop();
    cout<<pq.top()<<'\n';//1
}

priority_queue

題目

比較難的greedy

分治

分成小問題解決

再合併

快速冪

x^p

int POW(int x,int p){
    int ans=1;
    for(int i=0;i<p;i++) ans*=x;
    return ans;
}
O(p)

快速冪

x^p

x^p=x^{\smash{p/2}}\times x^{\smash{p/2}}

把p分成兩半

如果p為奇數再乘x

int fpow(int x,int p){
    if(p==1) return x;
    if(p==0) return 1;
    int res=fpow(x,p/2);
    res*=res;
    if(p%2==1) res*=x;
    return res;
}
O(\log p)

題目

合併排序

把一個數列切成兩半

然後合併

int a[N],t[N];
void m_sort(int l,int r){
    if(l==r) return;
    int m=(l+r)/2,i,j,cnt;
    m_sort(l,m),m_sort(m+1,r);
    for(i=l,j=m+1,cnt=0;i<=m&&j<=r;){
    	if(i<=m&&(j>r||a[i]<=a[j])) t[cnt]=a[i],i++,cnt++;
	if(j<=r&&(i>m||a[j]<=a[i])) t[cnt]=a[j],j++,cnt++;
    }
    for(i=l;i<=r;i++)
    	a[i]=t[i-l];
}

題目

dp

費式數列

f(n)=f(n-1)+f(n-2)

dp

定義狀態

轉移

f(n),f(1)=1,f(2)=1

f(n)=f(n-1)+f(n-2)

例題

圖論

建圖

鄰接矩陣

vector

如果i有一條邊連向j

a[i][j]=1

否則

a[i][j]=0

把跟點i相鄰的點放進a[i]

dfs

vector<int>adj[N];
bool vis[N];
void dfs(int v){
    vis[v]=1;
    for(int u:adj[v])
    	if(!vis[u]) dfs(u);
}

例題

最短路徑

給你一個圖,邊的長度皆為1,求起點s到終點t的最短距離

bfs

vector<int>adj[N];
int dis[N];
bool vis[N];
void bfs(int s){
    queue<int> q;
    dis[s]=0,vis[s]=1;
    while(!q.empty()){
    	int v=q.front();
        q.pop();
        for(int u:adj[v]){
            if(vis[u]) continue;
            vis[u]=1;
            dis[u]=dis[v]+1;
            q.push(u);
        }
    }
}

例題

無負權單點源最短路dijkstra

記得BFS嗎

A

B

C

D

F

E

G

20

1

7

4

5

1

3

5

3

A

B

C

D

F

E

G

+1

+7

+7

+7

+5

+8

code

bool vis[200010];
vector<pair<int,int> > adj[200010];
void dijkstra(int s){
    priority_queue<pair<int,int> >pq;
    pq.push({0,s});
    while(!pq.empty()){
	int w=pq.top().first,v=pq.top().second;
	pq.pop();
	if(vis[v]) continue;
	vis[v]=1;
	dis[v]=-w;
	for(auto u:adj[v]){
    	    pq.push({w-u.second,u.first});
	}
    }
}

例題

二著色問題

B

D

C

E

F

A

令所有點塗上紅或綠色

判斷有沒有存在所有相鄰點對(u,v)的顏色皆不同的塗法

二著色問題

A

A

B

D

E

F

C

B

D

C

E

F

例題

A

B

C

D

F

E

H

20

1

7

4

5

1

3

5

3

A

B

C

D

F

E

H

A

B

C

D

F

E

H

A

B

C

D

F

E

H

最小生成樹

選一些邊讓圖連通且權重和最小

prim algorithm

A

B

C

D

F

E

H

20

1

7

4

5

1

3

5

3

A

B

C

D

F

E

H

另一種方法

A

B

C

D

F

E

1

3

4

5

2

7

6

並查集

A

B

C

D

F

E

並查集

A

B

C

D

F

E

啟發式合併

F

A

B

C

D

E

A

F

啟發式合併

F

A

B

C

D

E

F

A

B

C

D

E

or

F

A

路徑壓縮

=>

A

B

C

D

E

A

B

C

D

E

int sz[N],top[N];
int find(int x){
    if(top[x]==-1) return x;
    top[x]=find(top[x]);//路徑壓縮
    return top[x];
}
void Union(int u,int v){
    u=find(u),v=find(v);
    if(u==v)return;
    if(sz[u]>sz[v]) swap(u,v);//啟發式合併
    top[u]=v;
    sz[v]+=sz[u];
}

code

例題

有向無環圖

DAG

A

C

B

D

E

F

性質

DAG一定存在拓樸排序

A

C

B

D

E

F

拓樸排序定義:有一點集 \{u_1,u_2,...,u_n\} \\ 對任意i \leq j 不存在點u_j 到u_i的路徑

100

200

400

50

例題

為連通圖且邊數+1=點數

root

深度depth

1

 

 

2

 

 

3

葉節點

父節點

子節點

樹上dfs

樹dp

2021成功電研C++語法社課簡報

By chenyanjun

2021成功電研C++語法社課簡報

  • 304