陣列

將同資料型態的值存在一起

宣告

和變數很類似

要在宣告同時設定陣列大小

也能預設值

#include <iostream>
using namespace std;
int main() {
	int a[100];
	int b[5] = {1, 5, 20, 14, 30};
}

使用

在要使用的陣列名稱後加索引值(index)

程式語言都是從0開始

索引值可以是變數

#include <iostream>
using namespace std;
int main() {
	int a[5] = {1, 5, 20, 14, 30};
	cout << a[0] << '\n'; //輸出1 
	cout << a[3] << '\n'; //輸出14
    
	for(int i = 0; i < 5; i++){
		cout << a[i] << " ";
	}
}

輸入

通常搭配for迴圈來輸入

#include <iostream>
using namespace std;
int main() {
	int a[5];
	for(int i = 0; i < 5; i++){
		cin >> a[i];
	}
	for(int i = 0; i < 5; i++){
		cout << a[i] << " ";
	}
}

改值

#include <iostream>
using namespace std;
int main() {
	int a[5] = {2, 12, 15, 52, 17};
	a[0] = 26;
	a[1] = 78;
	for(int i = 0; i < 5; i++){
		cout << a[i] << " ";
	}
}

和陣列的使用非常類似

例題

zerojudge g595

zerojudge d587

zerojudge d166

多維陣列

陣列裡放陣列(?

宣告

幾維就打幾個陣列大小

幾乎跟一維的宣告一模一樣

#include <iostream>
using namespace std;
int main() {
	int a[1000][100];
	int b[3][2] = {{1, 4}, {2, 4}, {14, 14}};
}

使用

和一維的一模一樣

再次提醒程式的index都是從0開始

#include <iostream>
using namespace std;
int main() {
	int a[3][2] = {{1, 4}, {3, 7}, {17, 14}};
	cout << a[0][0] << '\n'; //輸出1
	cout << a[2][1] << '\n'; //輸出14
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 2; j++){
			cout << a[i][j] << " ";
		}
		cout << '\n';
	}
}

輸入and改值

跟一維的一模一樣

小提醒

陣列的大小是有限的

一維大概只到4*10^8

二維大概只到2*10^4

陣列宣告的地方會影響到最大的容量

如果你需要用到算大的空間

請宣告成全域

#include <iostream>
using namespace std;
int a[100000005];
int main() {
	cout << "Hello world!";
}
#include <iostream>
using namespace std;
int main() {
	int a[100000005];
	cout << "Hello world!";
}

全域宣告,能順利執行

區域宣告,無法順利執行

例題

zerojudge a015

zerojudge e974

zerojudge b965

函式

自定義功能的東東

宣告

要宣告在main函式外

前面放回傳的資料型態

後面放函式的名稱

小括號記得打

大括號裡放要執行的程式

#include <iostream>
using namespace std;
//格式如下
//回傳的資料型態 名稱(){
//	執行的程式 
//}
int hello(){ //其實這是不太正確的寫法
	cout << "Hello World!";
}
int main() {
	hello();
}

回傳return

會回傳一個數值並結束整個函式

資料型態為函式宣告的

#include <iostream>
using namespace std;
//格式如下
//回傳的資料型態 名稱(){
//	執行的程式 
// return 數值 
//}
int year(){
	return 2022;
}
string hello(){
	return "Hello World!";
}
int main(){
	cout << year() << '\n';
	cout << hello() << '\n';
}

參數

小括號裡可以放多個參數

參數只會在函式裡生效

#include <iostream>
using namespace std;
//格式如下
//回傳的資料型態 名稱(參數1, 參數2){
//	執行的程式 
// return 數值 
//}
int add(int a, int b){
	return a + b; 
}
bool equal(int a, int b){
	if(a == b)
		return true;
	return false;
}
int main(){
	cout << add(5, 10) << '\n';
	if(equal(10, 1))
		cout << "兩數相等" << '\n';
	else
		cout << "兩數不相等" << '\n';
	//cout << a; //會報錯 
}

如果參數有預設值可以不用傳入

#include <iostream>
using namespace std;
//格式如下
//回傳的資料型態 名稱(參數1, 參數2){
//	執行的程式 
// return 數值 
//}
int multiply(int a, int b, int c = 1){
	return a * b * c;
}
int main(){
	cout << multiply(2, 3);
}

無回傳函式

資料型態的位置打void

return後面直接打分號就好

#include <iostream>
using namespace std;
void hello(){
	cout << "Hello world!\n";
	return;
}
void add(int a, int b){
	cout << a + b << '\n';
	return;
}
int main() {
	hello();
	add(3, 6);
}

補充:遞迴

讓函式自己呼叫自己

ex:費式數列

練習

zerojudge i399

zerojudge f579

zerojudge f313

struct

自定義資料型態

宣告

struct後面放名稱

大括號裡放要的變數

大括號後記得加分號

也可以預設值

#include <iostream>
using namespace std;
int main() {
	struct struct1{
		int x, y;
	};
	struct1 a, b = {5, 10};
	cin >> a.x >> a.y;
	cout << a.x << " " << a.y << '\n';
	cout << b.x << " " << b.y << '\n';
}

可以在分號前宣告

#include <iostream>
using namespace std;
int main() {
	struct struct1{
		int x, y;
	}a, b = {5, 10};
	cin >> a.x >> a.y;
	cout << a.x << " " << a.y << '\n';
	cout << b.x << " " << b.y << '\n';
}

struct內也能放函式

跟一般函式的宣告和使用方法一樣

#include <iostream>
using namespace std;
int main() {
	struct struct1{
		int x, y;
		int f(int z){
			return (x + y) * z;
		}
	}a;
	int tmp;
	cin >> a.x >> a.y;
	cin >> tmp;
	cout << a.f(tmp);
}

解題思維

僅供參考

加碼!!!

1.看懂題目

一定要完全懂題目要幹嘛

建議推導一遍範例輸入輸出

ex: zerojudge b266

2.拆解問題

將題目要做的事情一件一件拆開

每件事情分開思考怎麼做

最後再合在一起

ex: zerojudge h082

3.開始實作

實作剛剛拆解完的問題

可以分成很多函式來做

出問題的時候可以針對函式debug

練習

zerojudge e622

zerojudge c462

STL

好用的模板庫

vector

不用宣告大小的陣列

支援index查詢

能夠一直往後延伸或從後面刪除

需要引入函式庫<vector>

vector宣告

要預設大小在後面加(),裡面打數字

要再預設值的在大小後再打數字

格式如下

#include <iostream>
#include <vector> 
using namespace std;
int main() {
	//vector <資料型態> 名稱(預設大小,預設值) 
	vector <int> a;
	vector <int> b(100); //預設大小為100
	b[5] = 5;
	cout << b[5] << '\n';
	vector <int> c(100, 3); //預設大小為100且全部預設值為3
	c[20] = 20;
	cout << c[10] << " " << c[20] << '\n'; 
}

vector新增和刪除

push_back()為在尾端新增,在()裡打要新增的值

pop_back()為刪除尾端的值,括號裡不用放東西

back()為回傳尾端的值,括號裡不用放東西

#include <iostream>
#include <vector> 
using namespace std;
int main() {
	vector <int> a;
	a.push_back(2);
	a.push_back(5);
	cout << a.back() << '\n';
	a.pop_back();
	cout << a.back() << '\n';
	a.push_back(10);
	a.push_back(7);
	cout << a[0] << " " << a[1] << " " << a[2] << '\n';
}

vector長度

size()為回傳vector的長度

但回傳的東西不是int或long long

要先轉型態

#include <iostream>
#include <vector> 
using namespace std;
int main() {
	vector <int> a;
	a.push_back(2);
	a.push_back(5);
	cout << (int)a.size() << '\n';
	a.push_back(4);
	a.pop_back();
	a.push_back(17);
	cout << (int)a.size() << '\n';
}

stack

跟vector的概念幾乎一樣

只是少了index查詢

函式的名稱稍微不同

要引入函式庫<stack>

stack宣告

跟vector一樣

但無法預設大小和值

格式如下

#include <iostream>
#include <stack> 
using namespace std;
int main() {
	//stack <資料型態> 名稱
	stack <int> a;
}

stack新增和刪除

push()為在頂端新增,在()裡打要新增的值

pop()為刪除頂端的值,括號裡不用放東西

top()為回傳頂端的值,括號裡不用放東西

#include <iostream>
#include <stack> 
using namespace std;
int main() {
	//stack <資料型態> 名稱
	stack <int> a;
	a.push(12);
	a.push(4);
	cout << a.top() << '\n';
	a.pop();
	cout << a.top() << '\n';
}

stack長度

跟vector一模一樣

STL的資結幾乎都長這樣

#include <iostream>
#include <stack> 
using namespace std;
int main() {
	//stack <資料型態> 名稱
	stack <int> a;
	a.push(12);
	a.push(4);
	cout << a.top() << '\n';
	a.pop();
	cout << a.top() << '\n';
	cout << (int)a.size() << '\n';
}

例題

zerojudge i213

zerojudge c123

zerojudge i706(不在本班範圍)

queue

先進先出

像排隊一樣

需引入函式庫<queue>

queue宣告

跟其他stl幾乎一樣

格式如下

#include <iostream>
#include <queue> 
using namespace std;
int main() {
	//queue <資料型態> 名稱
	queue <int> a;
}

queue新增和刪除

push()為在後端新增,在()裡打要新增的值

pop()為刪除前端的值,括號裡不用放東西

front()為回傳前端的值,括號裡不用放東西

#include <iostream>
#include <stack> 
using namespace std;
int main() {
	//stack <資料型態> 名稱
	stack <int> a;
	a.push(12);
	a.push(4);
	cout << a.top() << '\n';
	a.pop();
	cout << a.top() << '\n';
}

queue長度

跟前面一模一樣

#include <iostream>
#include <queue> 
using namespace std;
int main() {
	//queue <資料型態> 名稱
	queue <int> a;
	a.push(12);
	a.push(4);
	cout << a.front() << '\n';
	a.pop();
	cout << a.front() << '\n';
	cout << (int)a.size() << '\n';
}

deque

雙向的queue

可以在前端新增也能在後端新增

刪除也是

需引入函式庫<deque>

deque宣告

沒什麼好說的

格式如下

#include <iostream>
#include <deque> 
using namespace std;
int main() {
	//deque <資料型態> 名稱
	deque <int> a;
}

deque新增和刪除

push_back()為在後端新增,在()裡打要新增的值

push_front()為在前端新增,在()裡打要新增的值

pop_back()為刪除後端的值,括號裡不用放東西

pop_front()為刪除前端的值,括號裡不用放東西

front()為回傳前端的值,括號裡不用放東西

back()為回傳後端的值,括號裡不用放東西

例題

zerojudge e447

zerojudge h082

CGOJ c1013

set

儲存不重複的資料

會自動排序

結構為紅黑樹(二元搜尋樹)

需引入函式庫<set>

set宣告

一樣沒什麼好說的

格式如下

#include <iostream>
#include <set> 
using namespace std;
int main() {
	//set <資料型態> 名稱
	set <int> a;
}

set使用

insert()為新增,在()裡打要新增的值

erase()為刪除,在()裡打要刪除的值

count()會回傳()裡的值是否在set裡

#include <iostream>
#include <set> 
using namespace std;
int main() {
	//set <資料型態> 名稱
	set <int> a;
	a.insert(1);
	a.insert(2);
	if(a.count(2))
		cout << "2 in set\n";
	else 
		cout << "2 not in set\n";
	if(a.count(5))
		cout << "5 in set\n";
	else
		cout << "5 not in set\n";
	a.erase(2);
	if(a.count(2))
		cout << "2 in set\n";
	else 
		cout << "2 not in set\n";
}

set遍歷

用for(auto :)達成

在遍歷時盡量不要修改set的資料

範例如下

#include <iostream>
#include <set> 
using namespace std;
int main() {
	set <int> a;
	a.insert(5);
	a.insert(2);
	a.insert(14);
	a.insert(2);
	for(auto i : a){
		cout << i << '\n';
		//a.erase(2); 這行會爛掉 
	}
}

pair

由兩個資料型態加起來的STL

有順序之分

pair宣告

和前面的STL宣告很類似

要注意有兩種資料型態

#include <iostream>
using namespace std;
int main() {
	//pair <資料型態1, 資料型態2> 名稱
	pair <int, string> a; 
}

pair使用

first為第一種資料型態,second為第二種

#include <iostream>
using namespace std;
int main() {
	//pair <資料型態1, 資料型態2> 名稱
	pair <int, string> a;
	cin >> a.first >> a.second;
	cout << a.first << " " << a.second << '\n';
	a.first += 5;
	a.second = "Hi";
	cout << a.first << " " << a.second << '\n';
}

pair也可以宣告成陣列

範例如下

#include <iostream>
using namespace std;
int main() {
	pair <int, string> a[3];
	for(int i = 0; i < 3; i++){
		cin >> a[i].first >> a[i].second;
	}
	a[0].first += 10;
	a[1].first *= 2;
	a[2].second = "good";
	for(int i = 0; i < 3; i++){
		cout << a[i].first << " " << a[i].second << '\n';
	}
}

例題

zerojudge d478

TCIRC d015

TCIRC d056(慎入)

map

由一個關鍵字(key)對應到一個值(value)

會依照key自動排序

可以理解成set的pair版

需引入函式庫<map>

map宣告

須分別宣告key跟value的資料型態

跟pair一樣

#include <iostream>
#include <map>
using namespace std;
int main() {
	//map <key資料型態, value資料型態> 名稱
	map <string, int> a;
}

map使用

可以直接在[]內打key

然後用=賦值

#include <iostream>
#include <map>
using namespace std;
int main() {
	//map <key資料型態, value資料型態> 名稱
	map <string, int> a;
	a["aaa"] = 10;
	a["abc"] = 15;
	a["cjsj"] = 1;
	cout << a["aaa"] << " " << a["abc"] << '\n';
	//cout << a[1] << '\n';
	//cout << a["adad"] << '\n'; 
}

map遍歷

跟set一樣用for(auto :)達成

但auto出的資料型態是pair

範例如下

#include <iostream>
#include <map>
using namespace std;
int main() {
	//map <key資料型態, value資料型態> 名稱
	map <int, char> a;
	a[14] = 'A';
	a[20] = 'c';
	a[4] = 'V';
	a[78] = 'l';
	for(auto i : a){
		cout << i.first << " " << i.second << '\n';
	}
}

priority_queue

優先度最高的會在頂端

預設為最大值

結構為heap(堆疊)

需引入函式庫<queue>

priority_queue宣告

跟前面的stl一模一樣

範例如下

#include <iostream>
#include <queue>
using namespace std;
int main() {
	//priority_queue <資料型態> 名稱;
	priority_queue <int> a;
}

priority_queue使用

push()為放入()中的值

pop()為刪除頂端的值

top()會回傳頂端的值

#include <iostream>
#include <queue>
using namespace std;
int main() {
	//priority_queue <資料型態> 名稱;
	priority_queue <int> a;
	a.push(5);
	a.push(21);
	cout << a.top() << '\n';
	a.pop();
	a.push(2);
	cout << a.top() << '\n';
}

如果要最小值在頂端?

1.把push的值加個負號,拿出來時再加回去

2.在宣告時加點東西,範例如下

#include <iostream>
#include <queue>
using namespace std;
int main() {
	//priority_queue <資料型態, vector<資料型態>, greater<資料型態>> 名稱;
	priority_queue <int, vector<int>, greater<int>> a;
	a.push(5);
	a.push(21);
	cout << a.top() << '\n';
	a.pop();
	a.push(2);
	cout << a.top() << '\n';
}

例題

zerojudge i791

zerojudge d566

zerojudge b606

期末練習題

zerojudge a059

zerojudge d563

zerojudge a565

zerojudge e908

zerojudge b162

C++語法2

By patrickh

C++語法2

  • 468