---
# System prepended metadata

title: 12/9 圖文編輯
tags: [校外服學]

---

# 主題
* os
* csv
* sorting algorithm
* searching algorithm




# 責編的話
* 內容先以補充為主，之後再濃縮
* 主要是介紹，可參考reference
[TOC]

# 工作
- [ ] 完成前三個的模板(不含optional)

# os

- [x] **學習目標**
    * 理解 Python `os` 模組的基本功能和用途。
    * 掌握使用 `os` 模組進行檔案和目錄操作的方法。
    * 能夠編寫腳本來自動化系統管理任務。

- [x] **知識點**
    本文將詳細介紹 Python 的 `os` 模組，幫助你了解如何使用這個模組來與操作系統進行互動，包括檔案操作、目錄管理、環境變量處理等。

---

## **1. 什麼是 os 模組？為什麼要使用 os 模組？**

### 什麼是 os 模組？
`os` 模組是 Python 的標準庫之一，提供了與操作系統互動的功能。它允許 Python 程式訪問系統功能，如檔案和目錄操作、環境變量、進程管理等。

### 為什麼使用 os 模組？
- **跨平台**：`os` 模組提供的功能在不同操作系統（如 Windows、Linux、macOS）上具有一致的介面，便於編寫跨平台的程式。
- **功能豐富**：`os` 模組涵蓋了廣泛的系統操作，如檔案讀寫、目錄遍歷、環境變量管理等。
- **自動化**：利用 `os` 模組，可以編寫腳本來自動化日常的系統管理任務，提高效率。

### 範例
```python
import os

# 獲取當前工作目錄
current_dir = os.getcwd()
print("當前工作目錄:", current_dir)
```

輸出：
![image](https://hackmd.io/_uploads/HyJQjFSEyx.png)


這段程式使用 `os.getcwd()` 函數獲取並打印當前的工作目錄。

---

## **2. 檔案和目錄操作**

`os` 模組提供了多種方法來操作檔案和目錄，包括創建、刪除、重命名和遍歷等。

### 創建目錄
```python
import os

# 創建單層目錄
os.mkdir('new_folder')

# 創建多層目錄
os.makedirs('parent_folder/child_folder')
```

### 刪除目錄
```python
import os

# 刪除單層目錄
os.rmdir('new_folder')

# 刪除多層目錄
os.removedirs('parent_folder/child_folder')
```

### 重命名檔案或目錄
```python
import os

# 重命名檔案
os.rename('old_name.txt', 'new_name.txt')

# 重命名目錄
os.rename('old_folder', 'new_folder')
```

### 列出目錄內容
```python
import os

# 列出當前目錄的所有檔案和資料夾
contents = os.listdir('.')
print(contents)
```

輸出：
```
['file1.txt', 'file2.py', 'new_folder']
```

---

## **3. 路徑操作**

處理檔案路徑是系統操作中常見的任務，`os.path` 模組提供了多種方法來操作和處理路徑。

### 獲取檔案的絕對路徑
```python
import os

# 獲取檔案的絕對路徑
absolute_path = os.path.abspath('file1.txt')
print("絕對路徑:", absolute_path)
```

### 分離檔案路徑
```python
import os

# 分離路徑和檔名
path, filename = os.path.split('/path/to/file1.txt')
print("路徑:", path)
print("檔名:", filename)
```

輸出：
```
路徑: /path/to
檔名: file1.txt
```

### 獲取檔案擴展名
```python
import os

# 獲取檔案擴展名
root, ext = os.path.splitext('file1.txt')
print("檔案根:", root)
print("擴展名:", ext)
```

輸出：
```
檔案根: file1
擴展名: .txt
```

---

## **4. 環境變量管理**

`os` 模組允許你讀取和設置系統的環境變量，這在配置應用程式和管理系統設定時非常有用。

### 獲取環境變量
```python
import os

# 獲取特定的環境變量
home_dir = os.getenv('HOME')
print("使用者主目錄:", home_dir)

# 獲取所有環境變量
env_vars = os.environ
print(env_vars)
```
![image](https://hackmd.io/_uploads/rk-A5tHNJx.png)

### 設置環境變量
```python
import os

# 設置環境變量
os.environ['MY_VARIABLE'] = 'value'
print(os.getenv('MY_VARIABLE'))  # 輸出: value
```
![image](https://hackmd.io/_uploads/BJM95KH41x.png)

---

## **5. 進階應用：執行系統命令**

`os` 模組允許你從 Python 程式中執行系統命令，這對於自動化任務和與系統進行互動非常有用。

### 使用 `os.system()`
```python
import os

# 執行一個簡單的系統命令
os.system('echo "Hello, World!"')
```
![image](https://hackmd.io/_uploads/HkDHFYBEJg.png)

### 使用 `os.popen()`
```python
import os

# 執行系統命令並獲取輸出
stream = os.popen('ls') //列出該file下檔案名或資料夾名
output = stream.read()
print(output)
```

輸出：
```
file1.txt
file2.py
new_folder
```

---

---

# csv (optional)

- [x] **學習目標**
    * 理解 Python `csv` 模組的基本功能和用途。
    * 掌握使用 `csv` 模組讀寫 CSV 檔案的方法。
    * 能夠處理和解析結構化的表格資料，並進行資料分析。

- [x] **知識點**
    本文將介紹 Python 的 `csv` 模組，幫助你了解如何使用這個模組來讀取和寫入 CSV 檔案，並處理結構化的表格資料。

---

## **1. 什麼是 csv 模組？為什麼要使用 csv 模組？**

### 什麼是 csv 模組？
`csv` 模組是 Python 的標準庫之一，用於讀取和寫入 CSV（逗號分隔值）格式的檔案。CSV 格式是一種常見的表格資料交換格式，廣泛應用於資料分析和數據存儲。

### 為什麼使用 csv 模組？
- **簡單易用**：`csv` 模組提供了簡單直觀的介面，便於快速讀取和寫入 CSV 檔案。
- **標準化**：CSV 是一種標準的資料交換格式，幾乎所有的資料處理工具都支持 CSV 格式。
- **靈活性高**：`csv` 模組支持多種分隔符和引用方式，適應不同的 CSV 格式需求。

### 範例
```python
import csv

# 創建一個 CSV 檔案並寫入數據
with open('example.csv', mode='w', newline='') as file:
    writer = csv.writer(file)
    writer.writerow(['Name', 'Age', 'City'])
    writer.writerow(['Alice', 30, 'New York'])
    writer.writerow(['Bob', 25, 'Los Angeles'])
```

這段程式使用 `csv.writer` 創建一個 CSV 檔案，並寫入表頭和兩行數據。

---

## **2. 讀取 CSV 檔案**

### 使用 `csv.reader()`
```python
import csv

# 讀取 CSV 檔案
with open('example.csv', mode='r', newline='') as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)
```

輸出：
```
['Name', 'Age', 'City']
['Alice', '30', 'New York']
['Bob', '25', 'Los Angeles']
```

### 使用 `csv.DictReader()`
`DictReader` 會將每一行資料轉換為字典，方便根據欄位名稱存取資料。

```python
import csv

# 使用 DictReader 讀取 CSV 檔案
with open('example.csv', mode='r', newline='') as file:
    reader = csv.DictReader(file)
    for row in reader:
        print(row['Name'], row['Age'], row['City'])
```

輸出：
```
Alice 30 New York
Bob 25 Los Angeles
```

---

## **3. 寫入 CSV 檔案**

### 使用 `csv.writer()`
```python
import csv

# 寫入 CSV 檔案
with open('output.csv', mode='w', newline='') as file:
    writer = csv.writer(file)
    writer.writerow(['Product', 'Price', 'Quantity'])
    writer.writerow(['Apple', 1.2, 10])
    writer.writerow(['Banana', 0.5, 20])
```

### 使用 `csv.DictWriter()`
`DictWriter` 允許使用字典格式來寫入 CSV 檔案。

```python
import csv

# 使用 DictWriter 寫入 CSV 檔案
with open('output_dict.csv', mode='w', newline='') as file:
    fieldnames = ['Product', 'Price', 'Quantity']
    writer = csv.DictWriter(file, fieldnames=fieldnames)
    
    writer.writeheader()
    writer.writerow({'Product': 'Apple', 'Price': 1.2, 'Quantity': 10})
    writer.writerow({'Product': 'Banana', 'Price': 0.5, 'Quantity': 20})
```

---

## **4. 進階應用：處理不同的分隔符**

有些 CSV 檔案使用不同的分隔符，如分號或制表符，`csv` 模組可以靈活處理這些情況。

### 使用分號分隔符
```python
import csv

# 使用分號作為分隔符讀取 CSV 檔案
with open('semicolon_separated.csv', mode='r', newline='') as file:
    reader = csv.reader(file, delimiter=';')
    for row in reader:
        print(row)
```

### 使用制表符分隔符
```python
import csv

# 使用制表符作為分隔符寫入 CSV 檔案
with open('tab_separated.csv', mode='w', newline='') as file:
    writer = csv.writer(file, delimiter='\t')
    writer.writerow(['Name', 'Age', 'City'])
    writer.writerow(['Alice', 30, 'New York'])
    writer.writerow(['Bob', 25, 'Los Angeles'])
```

---

---

# sorting algorithm

- [x] **學習目標**
    * 理解常見的排序演算法及其運作原理。
    * 能夠實現各種排序演算法的 Python 程式碼。
    * 掌握選擇合適的排序演算法來解決不同的問題。

- [x] **知識點**
    本文將介紹幾種常見的排序演算法，包括冒泡排序、選擇排序、插入排序、快速排序和合併排序。通過程式碼範例，幫助你理解每種排序演算法的運作方式和效率。

---

## **1. 冒泡排序（Bubble Sort）**

### 冒泡排序簡介
冒泡排序是一種簡單的排序演算法，通過多次比較和交換相鄰元素，使得較大的元素逐步“冒泡”到列表的末尾。其時間複雜度為 O(n²)，不適用於大規模資料的排序。

### 運作原理
1. 從左到右遍歷待排序的數列。
2. 比較相鄰的兩個元素，如果前一個元素比後一個大，則交換它們的位置。
3. 重複步驟 1 和 2，直到整個數列有序。

### 範例程式碼
```python
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        # 提前退出冒泡循環的標誌位
        swapped = False
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
                swapped = True
        # 如果內循環沒有交換，說明數列已經有序
        if not swapped:
            break
    return arr

# 測試冒泡排序
data = [64, 34, 25, 12, 22, 11, 90]
sorted_data = bubble_sort(data)
print("排序後的數列:", sorted_data)
```

輸出：
```
排序後的數列: [11, 12, 22, 25, 34, 64, 90]
```
* 以下為概念圖
![image](https://hackmd.io/_uploads/Hym5uYH4kg.png)

---

## **2. 選擇排序（Selection Sort）**

### 選擇排序簡介
選擇排序通過多次選擇剩餘未排序部分中的最小元素，並將其放到已排序部分的末尾。其時間複雜度為 O(n²)，適用於小規模資料的排序。

### 運作原理
1. 從待排序的數列中找到最小（或最大）元素。
2. 將最小元素與數列的第一個元素交換。
3. 對剩餘的元素重複步驟 1 和 2，直到整個數列有序。

### 範例程式碼
```python
def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        # 假設最小元素的索引為 i
        min_idx = i
        for j in range(i+1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        # 將找到的最小元素與第 i 個元素交換
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr

# 測試選擇排序
data = [64, 25, 12, 22, 11]
sorted_data = selection_sort(data)
print("排序後的數列:", sorted_data)
```

輸出：
```
排序後的數列: [11, 12, 22, 25, 64]
```
* 以下是概念圖
![image](https://hackmd.io/_uploads/SyeOtKSVJl.png)

---

## **3. 插入排序（Insertion Sort）**

### 插入排序簡介
插入排序通過將未排序部分的元素逐一插入到已排序部分的正確位置來實現排序。其時間複雜度為 O(n²)，但在資料基本有序的情況下效率較高。

### 運作原理
1. 將數列分為已排序部分和未排序部分，初始時已排序部分只有第一個元素。
2. 從未排序部分選取一個元素，將其插入到已排序部分的適當位置。
3. 重複步驟 2，直到整個數列有序。

### 範例程式碼
```python
def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i-1
        # 將 key 插入到已排序部分的正確位置
        while j >=0 and key < arr[j]:
            arr[j+1] = arr[j]
            j -= 1
        arr[j+1] = key
    return arr

# 測試插入排序
data = [12, 11, 13, 5, 6]
sorted_data = insertion_sort(data)
print("排序後的數列:", sorted_data)
```

輸出：
```
排序後的數列: [5, 6, 11, 12, 13]
```
* 以下是概念圖
![image](https://hackmd.io/_uploads/HJg7cYrEkg.png)



---

## **4. 快速排序（Quick Sort）**

### 快速排序簡介
快速排序是一種高效的排序演算法，採用分治法的策略。其時間複雜度平均為 O(n log n)，是實際應用中常用的排序方法之一。

### 運作原理
1. 選擇一個元素作為基準（pivot）。
2. 將數列分為兩部分，左邊所有元素小於基準，右邊所有元素大於基準。
3. 對左右兩部分分別遞迴進行快速排序。
4. 合併排序結果。

### 範例程式碼
```python
def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    else:
        pivot = arr[len(arr) // 2]
        left = [x for x in arr if x < pivot]
        middle = [x for x in arr if x == pivot]
        right = [x for x in arr if x > pivot]
        return quick_sort(left) + middle + quick_sort(right)

# 測試快速排序
data = [3,6,8,10,1,2,1]
sorted_data = quick_sort(data)
print("排序後的數列:", sorted_data)
```

輸出：
```
排序後的數列: [1, 1, 2, 3, 6, 8, 10]
```
* 以下是概念圖
![image](https://hackmd.io/_uploads/Bk0LctrVkl.png)



---

## **5. 合併排序（Merge Sort）**

### 合併排序簡介
合併排序也是一種分治法的排序演算法。其核心思想是將數列分成兩半，分別排序後再合併。其時間複雜度為 O(n log n)，且穩定性較高。

### 運作原理
1. 將數列分成兩半。
2. 對每一半遞迴進行合併排序。
3. 將兩個已排序的子序列合併成一個有序的數列。

### 範例程式碼
```python
def merge_sort(arr):
    if len(arr) >1:
        mid = len(arr)//2
        L = arr[:mid]
        R = arr[mid:]

        merge_sort(L)
        merge_sort(R)

        i = j = k = 0

        # 合併兩個子序列
        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                i +=1
            else:
                arr[k] = R[j]
                j +=1
            k +=1

        # 檢查是否有剩餘元素
        while i < len(L):
            arr[k] = L[i]
            i +=1
            k +=1

        while j < len(R):
            arr[k] = R[j]
            j +=1
            k +=1
    return arr

# 測試合併排序
data = [12, 11, 13, 5, 6, 7]
sorted_data = merge_sort(data)
print("排序後的數列:", sorted_data)
```

輸出：
```
排序後的數列: [5, 6, 7, 11, 12, 13]
```
* 以下是概念圖
![image](https://hackmd.io/_uploads/SyJq5YrNyx.png)


---

---

# searching algorithm

# 搜尋演算法

- [x] **學習目標**
    * 理解常見的搜尋演算法及其運作原理。
    * 能夠實現各種搜尋演算法的 Python 程式碼。
    * 掌握選擇合適的搜尋演算法來解決不同的問題。

- [x] **知識點**
    本文將介紹幾種常見的搜尋演算法，包括線性搜尋和二分搜尋。通過程式碼範例，幫助你理解每種搜尋演算法的運作方式和效率。

---

## **1. 線性搜尋（Linear Search）**

### 線性搜尋簡介
線性搜尋是一種簡單的搜尋演算法，通過從頭到尾依次檢查數列中的每個元素，直到找到目標元素。其時間複雜度為 O(n)，不適用於大規模資料的搜尋，但在無序或小規模的數列中表現良好。

### 運作原理
1. 從數列的第一個元素開始，依次比較每個元素是否等於目標值。
2. 如果找到目標值，返回其索引位置。
3. 如果遍歷整個數列仍未找到，返回 -1。

### 範例程式碼
```python
def linear_search(arr, target):
    for index, value in enumerate(arr):
        if value == target:
            return index
    return -1

# 測試線性搜尋
data = [5, 3, 7, 1, 9]
target = 7
result = linear_search(data, target)
print(f"目標 {target} 的索引位置為:", result)
```

輸出：
```
目標 7 的索引位置為: 2
```
* 概念圖
![image](https://hackmd.io/_uploads/ryIVptrNkx.png)



---

## **2. 二分搜尋（Binary Search）**

### 二分搜尋簡介
二分搜尋是一種高效的搜尋演算法，適用於已排序的數列。通過每次將搜尋範圍減半，快速定位目標元素。其時間複雜度為 O(log n)，適用於大規模的已排序數列。

### 運作原理
1. 設定搜尋範圍的左右邊界（left 和 right）。
2. 計算中間位置的索引（mid）。
3. 比較中間元素與目標值：
    - 如果中間元素等於目標值，返回其索引。
    - 如果中間元素大於目標值，縮小搜尋範圍到左半部分。
    - 如果中間元素小於目標值，縮小搜尋範圍到右半部分。
4. 重複步驟 2 和 3，直到找到目標元素或搜尋範圍為空。

### 範例程式碼
```python
def binary_search(arr, target):
    left, right = 0, len(arr) -1
    while left <= right:
        mid = left + (right - left) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid +1
        else:
            right = mid -1
    return -1

# 測試二分搜尋
data = [1, 3, 5, 7, 9]
target = 7
result = binary_search(data, target)
print(f"目標 {target} 的索引位置為:", result)
```

輸出：
```
目標 7 的索引位置為: 3
```
* 概念圖
![image](https://hackmd.io/_uploads/SyEt6YB4Jg.png)



### 注意事項
- 二分搜尋僅適用於已排序的數列。
- 在實作時，需確保每次縮小搜尋範圍的邊界設定正確，以避免無限迴圈。

---


## **3. 插值搜尋（Interpolation Search）**

### 插值搜尋簡介
插值搜尋是一種改進的二分搜尋演算法，特別適用於均勻分佈的已排序數列。通過根據目標值的大小來估計其可能的位置，從而減少搜尋次數。

### 運作原理
1. 設定搜尋範圍的左右邊界（left 和 right）。
2. 根據目標值的大小，估計中間位置的索引（mid）。
3. 比較中間元素與目標值：
    - 如果中間元素等於目標值，返回其索引。
    - 如果中間元素小於目標值，縮小搜尋範圍到右半部分。
    - 如果中間元素大於目標值，縮小搜尋範圍到左半部分。
4. 重複步驟 2 和 3，直到找到目標元素或搜尋範圍為空。

### 範例程式碼
```python
def interpolation_search(arr, target):
    low = 0
    high = len(arr) -1

    while low <= high and target >= arr[low] and target <= arr[high]:
        if low == high:
            if arr[low] == target:
                return low
            return -1

        # 插值公式
        pos = low + ((target - arr[low]) * (high - low)) // (arr[high] - arr[low])

        if arr[pos] == target:
            return pos
        if arr[pos] < target:
            low = pos +1
        else:
            high = pos -1
    return -1

# 測試插值搜尋
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
target = 70
result = interpolation_search(data, target)
print(f"目標 {target} 的索引位置為:", result)
```

輸出：
```
目標 70 的索引位置為: 6
```
* 概念圖
![image](https://hackmd.io/_uploads/rJDeAYHNyg.png)


### 注意事項
- 插值搜尋僅適用於已排序且分佈均勻的數列。
- 在數列分佈不均勻時，插值搜尋的效率可能低於二分搜尋。

---

## **4. 指數搜尋（Exponential Search）**

### 指數搜尋簡介
指數搜尋結合了二分搜尋和跳躍搜尋的特點，特別適用於無限或未知大小的已排序數列。通過先跳躍搜索來找到可能包含目標值的區間，然後在該區間內進行二分搜尋。

### 運作原理
1. 如果目標值等於數列的第一個元素，返回其索引。
2. 按照指數方式（1, 2, 4, 8, …）擴展搜尋範圍，直到找到一個範圍內的元素大於目標值。
3. 在確定的範圍內使用二分搜尋來定位目標值。
4. 如果目標值不存在，返回 -1。

### 範例程式碼
```python
def binary_search(arr, left, right, target):
    while left <= right:
        mid = left + (right - left) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid +1
        else:
            right = mid -1
    return -1

def exponential_search(arr, target):
    if arr[0] == target:
        return 0
    index = 1
    while index < len(arr) and arr[index] <= target:
        index *= 2
    return binary_search(arr, index//2, min(index, len(arr)-1), target)

# 測試指數搜尋
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
target = 70
result = exponential_search(data, target)
print(f"目標 {target} 的索引位置為:", result)
```

輸出：
```
目標 70 的索引位置為: 6
```
* 概念圖
![image](https://hackmd.io/_uploads/HkpO0Yr4ye.png)



### 注意事項
- 指數搜尋適用於已排序的數列，特別是當數列大小未知或非常大時。
- 指數搜尋首先快速擴展搜尋範圍，然後在確定的範圍內進行高效的二分搜尋。

---

# 工作
- [ ] 把內容潤飾






# reference



* 2022資訊之芽 py 語法班
[https://sprout.tw/py2022/slides](https://)
* 為你自己學 PYTHON
https://pythonbook.cc/chapters/basic/variable
* Python 3.13.0 Documentation
https://docs.python.org/3/
* Python 3.13.0 Module Index
https://docs.python.org/3/py-modindex.html#cap-t
* Python 3.13.0 Standard Library
https://docs.python.org/3/library/index.html
* PEP-8 Style Guide
https://peps.python.org/pep-0008/


