核心思想:相鄰元素兩兩比較,大者後移(沉底),小者前移(上浮),每輪將最大/最小元素移至端點。
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n-1; ++i) {
bool swapped = false;
for (int j = 0; j < n-1-i; ++j) {
if (arr[j] > arr[j+1]) {
std::swap(arr[j], arr[j+1]);
swapped = true;
}
}
if (!swapped) break; // 優化:已有序提前結束
}
}
核心思想:每輪從無序區選出最小元素,與無序區首位交換。
void selectionSort(int arr[], int n) {
for (int i = 0; i < n-1; ++i) {
int minIdx = i;
for (int j = i+1; j < n; ++j)
if (arr[j] < arr[minIdx]) minIdx = j;
if (minIdx != i) std::swap(arr[i], arr[minIdx]);
}
}
#include <algorithm>
#include <vector>
std::vector vec = {5, 2, 8, 1, 9};
std::sort(vec.begin(), vec.end()); // Introsort:快速+堆+插入,O(n log n) 保證
std::stable_sort(vec.begin(), vec.end()); // 歸併排序,保持相等元素順序
// 自定義比較
std::sort(vec.begin(), vec.end(), [](int a, int b){ return a > b; }); // 降序
原則:生產代碼直接使用 std::sort/std::stable_sort,除非教學/極端受限環境/特殊演算法研究。
適用無序序列,逐個比對,時間 O(n)。
int linearSearch(const int arr[], int n, int key) {
for (int i = 0; i < n; ++i)
if (arr[i] == key) return i;
return -1;
}
前提:序列已排序(升序)。每次排除一半區間,時間 O(log n)。
// 迭代版:推薦,無棧溢出風險
int binarySearch(const int arr[], int n, int key) {
int left = 0, right = n - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 防溢出
if (arr[mid] == key) return mid;
else if (arr[mid] < key) left = mid + 1;
else right = mid - 1;
}
return -1; // 未找到
}
// 標準庫:返回迭代器,配合 lower_bound/upper_bound 獲取範圍
auto it = std::binary_search(vec.begin(), vec.end(), key); // bool
auto range = std::equal_range(vec.begin(), vec.end(), key); // pair
ptr+1 移動 sizeof(T) 字節)。| 模式 | 成因 | 後果 | 防範 |
|---|---|---|---|
| 懸垂指針 | 對象銷毀後指針仍持有地址(delete ptr; // ptr 成懸垂) | UB:讀寫已釋放內存 | 智能指針、delete 後置空、所有權語義明確 |
| 野指針 | 未初始化指針 | UB:隨機地址讀寫 | 定義即初始化(nullptr)、auto ptr = std::make_unique<T>() |
| 越界訪問 | 指針算術超出分配範圍 | UB:緩衝區溢出 | 容器 at()/迭代器、span (C++20)、靜態分析 |
const 與指針的四種組合
int value = 42;
const int cvalue = 100;
int* p1 = &value; // 可讀寫指向可讀寫對象
const int* p2 = &cvalue; // 只讀指針 → 可讀寫/只讀對象(指向 const)
int* const p3 = &value; // 常量指針 → 指針本身不可改,對象可讀寫
const int* const p4 = &cvalue; // 常量指針 → 指向 const 對象
// 規則:const 修飾右側實體
// const int* == int const* : 指向 const int
// int* const : const 指針 (指針本身不可改)
實務慣例:函數參數優先 const T*/const T& 表達只讀意圖;需修改用 T*/T&;避免 T* const 參數(無意義,形參本身即副本)。
// 輸出參數模式
bool divide(int a, int b, int* quotient, int* remainder) {
if (b == 0) return false;
if (quotient) *quotient = a / b;
if (remainder) *remainder = a % b;
return true;
}
// 現代替代:結構體返回值(C++17 結構化綁定)
struct DivResult { int q, r; };
DivResult divide(int a, int b) { return {a/b, a%b}; }
auto [q, r] = divide(10, 3); // 清晰、無副作用、可優化
void process(int arr[]) { } // 等價 void process(int* arr)
void process(int arr[10]) { } // 等價 void process(int* arr),10 被忽略!
// 正確傳遞尺寸:模板推導數組引用
template <size_t N>
void process(int (&arr)[N]) { /* N 為編譯期常量 */ }
// 或使用 std::array / std::vector / std::span (C++20)
void process(std::span<int> arr); // 非擁有視圖,攜帶尺寸
int matrix[3][4]; // 連續內存:3 行 4 列
int (*p)[4] = matrix; // 指向「含 4 個 int 的數組」的指針
// p[i][j] 等價 *(*(p+i)+j)
\0 結尾的 char*/char[]。for (const char* p = str; *p; ++p)。strlen, strcpy, strcmp, strstr 等(需手動管理緩衝區安全)。
#include <string>
#include <string_view> // C++17 輕量只讀視圖
std::string s = "Hello";
s += " World"; // 自動擴容
std::string_view sv = s; // 零拷貝視圖
void print(std::string_view sv); // 接受字面量/string/string_view,統一接口
原則:內部存儲/構建用 std::string;函數參數/只讀處理用 std::string_view;禁用裸 char* 管理字符串生命週期。
<algorithm>, <ranges> C++20)。std::array (固定) / std::vector (動態) / std::span (視圖),告別 C 風格數組退化陷阱。std::string/std::string_view,編碼統一 UTF-8,跨平台無亂碼。-Wall -Wextra -Wpedantic -Wshadow -Wconversion),靜態分析(Clang-Tidy, Cppcheck)常態化。