---
# System prepended metadata

title: 內部排序法
tags: [程設班講義]

---

本次所統整的排序演算法只有內部排序法，沒有外部排序法。
###### 一個內建sort砸下去這小節的用途就小好多。

:::info
:::spoiler 資料在經過排序後有什麼好處?
1.容易閱讀
2.利於統計及整理
3.減少搜尋的時間
:::

### 排序方式
> **直接排序:** <font color="#D83507">直接交換</font>儲存資料的位置。(耗費較多時間進行資料的更動)
> **邏輯移動:** <font color="#D83507">改變</font>指向資料的<font color="#D83507">輔助指標的值</font>。

### 使用的記憶體種類
>**內部排序:** 資料量小，<font color="#D83507">可在記憶體內排序。</font>
>**外部排序:** 資料量大到無法在記憶體內排序，<font color="#D83507">用到輔助記憶體</font>。(ex.硬碟)

### 穩定性
>  **穩定的排序:** 在排序後，兩相同鍵值保持原本的次序。
>  **不穩定的排序** 在排序後，兩相同鍵值<font color="#D83507">不一定</font>保持原本的次序。

:::success 
::: spoiler 舉例
排序前: 3~左~  6  2  8  3~右~
穩定的排序: 2  3~左~  3~右~  6  8
不穩定的排序: 2  3~右~  3~左~  6  8
:::

### 時間複雜度
進行排序的執行時間我們叫他**時間複雜度**，其中又分為最好情況、最壞情況和平均情況。
(正文所出現的皆為平均情況。)
> **最好情況:** 資料已排序完成。
> **最懷情況:** 每一鍵值皆須重新排列。
> **平均情況:** 輸入的資料以等概率出現。(就是取平均)

:::success
::: spoiler 舉例
最好情況:
> 排序前: 2 4 6 8 9
> 排序後: 2 4 6 8 9

最壞情況:
> 排序前: 9 8 6 4 2
> 排序後: 2 4 6 8 9
:::

### 空間複雜度
進行排序所需的空間我們叫他**空間複雜度**，<font color="#D83507">任何排序法都有資料對調的動作，所以必定會用到一個額外空間</font>，若該排序法必須藉由遞迴的方式進行，其所使用到的堆疊則是該排序法須付出的額外空間。

---
# 泡沫排序法(bubble sort)
由第一個元素開始，比較相鄰元素的大小，若大小有誤則交換，以此類推直至排序完成。
### <font color="#2FB428">分析</font>
$1.$ 穩定的排序法。
$2.$ 時間複雜度為 $O(n^2)$。
$3.$ 空間複雜度為 $O(n)$。
$4.$ 適用資料量小或有部分排序的資料。

### <font color="#2FB428">圖例</font>


:::warning
:::spoiler 點我打開 (太長了，建議看完收起)
**第一輪之第一次交換(前者大於後者，交換)**
![image](https://hackmd.io/_uploads/HkQ_zfgwA.png)
![image](https://hackmd.io/_uploads/HJpqffxD0.png)

**第一輪之第二次交換(後者大於前者，不交換)**
![image](https://hackmd.io/_uploads/BkplmGevR.png)
![image](https://hackmd.io/_uploads/SJ7M7fxPA.png)

**第一輪之第三次交換(前者大於後者，交換)**
![image](https://hackmd.io/_uploads/Sy78mflDR.png)
![image](https://hackmd.io/_uploads/S1TvQMxwR.png)

**第一輪之第四次交換(後者大於前者，不交換)**
![image](https://hackmd.io/_uploads/SJKYXMxwA.png)
![image](https://hackmd.io/_uploads/B175XMlPA.png)

**以此類推重複至迴圈結束**
:::

### <font color="#2FB428">程式碼(配合例題)</font>
:::danger
:::spoiler 點我打開 (太長了，建議看完收起)
```cpp=
#include<iostream>
using namespace std ;

int main () {
	int a ;
	cin >> a ;
	int arr[a] ;
	for (int i = 0 ; i < a ; i ++) {  //輸入資料
		cin >> arr[i] ;
	}
	for (int i = 0 ; i < a - 1 ; i ++) {    //泡沫排序法
		for (int j = 0 ; j < a - i - 1 ; j ++) {
			if(arr[j] > arr[j+1]) {
				int tmp ;
				tmp = arr[j] ;
				arr[j] = arr[j+1] ;
				arr[j+1] = tmp ;
			}
		}
	}
	cout << arr[0] ;      //輸出資料(配合例題故以此方式輸出)
    for (int i = 1 ; i < a ; i ++) { 
        cout << ' ' << arr[i] ;
    } 
	cout << '\n' ;
}
```
:::

---
# 插入排序法(insert sort)
將陣列中的元素與與排序好的資料做比較，將元素插入適當的位置(已排序好的資料中)，以此類推直至排序完成。

### <font color="#2FB428">分析</font>
$1.$ 穩定的排序法。
$2.$ 時間複雜度為 $O(n^2)$。
$3.$ 空間複雜度為 $O(n)$。
$4.$ 適用資料量小或有部分排序的資料。

### <font color="#2FB428">圖例</font>
:::warning
:::spoiler 點我打開 (太長了，建議看完收起)
**原始資料:**
![image](https://hackmd.io/_uploads/rJLeGGeDA.png)

**第一次交換(將第一個元素放入陣列中的第一個位置)**
![image](https://hackmd.io/_uploads/rkwQzHxP0.png)
![image](https://hackmd.io/_uploads/BkhYMHxvC.png)

**第二次交換(將第二個元素與陣列中的元素比較後插入)**
![image](https://hackmd.io/_uploads/B1sVmBxD0.png)
![image](https://hackmd.io/_uploads/SJwBmrePR.png)

**第三次交換(將第三個元素與陣列中的元素比較後插入)**
![image](https://hackmd.io/_uploads/SypU4HeD0.png)
![image](https://hackmd.io/_uploads/Hk0wErxDC.png)

**第四次交換(將第四個元素與陣列中的元素比較後插入)**
![image](https://hackmd.io/_uploads/ryq-HBlDA.png)
![image](https://hackmd.io/_uploads/r1lXSHgDA.png)

**第五次交換(將第五個元素與陣列中的元素比較後插入)**
![image](https://hackmd.io/_uploads/Sk_d8rlv0.png)
![image](https://hackmd.io/_uploads/BJItUHeDA.png)
:::

### <font color="#2FB428">程式碼(配合例題)</font>
:::danger
:::spoiler 點我打開 (太長了，建議看完收起)
```cpp=
#include<iostream>
using namespace std ;

int main () {
	int a , j ;
	cin >> a ;
	int arr[a] ;
	for (int i = 0 ; i < a ; i ++) {  //輸入資料
		cin >> arr[i] ;
	}
	for (int i = 1 ; i < a ; i ++) {    //插入排序法
		int tmp ;
		tmp = arr[i] ;
		j = i - 1 ;
		while (j >= 0 && arr[j] > tmp) {
			arr[j+1] = arr[j] ;
			j-- ;
		}
		arr[j+1] = tmp ;
	}
	cout << arr[0] ;      //輸出資料(配合例題故以此方式輸出)
    for (int i = 1 ; i < a ; i ++) { 
        cout << ' ' << arr[i] ;
    } 
	cout << '\n' ;
}
```
:::

---
# 選擇排序法(selection sort)
有兩種方式，**由大至小**和**由小到大**。以由大至小為例，最小值放至第一個位置，第二小值放至第二個位子，以此類推直至排序完成。

### <font color="#2FB428">分析</font>
$1.$ 不穩定的排序法。
$2.$ 時間複雜度為 $O(n^2)$。
$3.$ 空間複雜度為 $O(n)$。

### <font color="#2FB428">圖例</font>
:::warning
:::spoiler 點我打開 (太長了，建議看完收起)
![image](https://hackmd.io/_uploads/rJLeGGeDA.png)

**第一次交換(找到最小值與第一個元素交換)**
![image](https://hackmd.io/_uploads/ryopTMxvA.png)
![image](https://hackmd.io/_uploads/B1pZRflw0.png)

**第二次交換(找到第二小值與第二個元素交換)**
![image](https://hackmd.io/_uploads/r1GcCzev0.png)
![image](https://hackmd.io/_uploads/Sky6Rzgv0.png)

**第三次交換(找到第三小值與第三個元素交換)**
![image](https://hackmd.io/_uploads/ByJqkXgPC.png)
![image](https://hackmd.io/_uploads/HyOjJmlDA.png)

**第四次交換(找到第三小值與第三個元素交換(本次大小相同，不交換))**
![image](https://hackmd.io/_uploads/ryQ7lmgwC.png)
![image](https://hackmd.io/_uploads/Skt-gmeP0.png)
:::

### <font color="#2FB428">程式碼(配合例題)</font>
:::danger
:::spoiler 點我打開 (太長了，建議看完收起)
```cpp=
#include<iostream>
using namespace std ;

int main () {
	int a ;
	cin >> a ;
	int arr[a] ;
	for (int i = 0 ; i < a ; i ++) {  //輸入資料
		cin >> arr[i] ;
	}
	for (int i = 0 ; i < a ; i ++) {    //選擇排序法
		for (int j = i+1 ; j < a ; j ++) {
			if(arr[i] > arr[j]) {
				int tmp ;
				tmp = arr[i] ;
				arr[i] = arr[j] ;
				arr[j] = tmp ;
			}
		}
	}
	cout << arr[0] ;      //輸出資料(配合例題故以此方式輸出)
    for(int i = 1 ; i < a ; i ++) {
		cout << ' ' << arr[i] ;
	}
	cout << '\n' ;
}
```
:::

---
# 謝耳排序法(shell sort)
分成特定的小區塊，以插入排序法排完區塊內的資料漸漸減少間隔的距離。

### <font color="#2FB428">分析</font>
$1.$ 穩定的排序法。
$2.$ 時間複雜度為 $O(n^{3/2})$。(以這題為例，最好的情況為 $O(n \;log^2 \; n) 。$
$3.$ 空間複雜度為 $O(n)$。
$4.$ 適用資料量小或有部分排序的資料。

### <font color="#2FB428">圖例</font>
:::warning
:::spoiler 點我打開 (太長了，建議看完收起)
![image](https://hackmd.io/_uploads/H1_NcG-vA.png)

**第一次交換(將該資料的長度($6$)除以$2$(不必定為$2$)，$6/2$得$3$，便是將他隔成3區。相同區塊做比較後交換，即顏色所示，其中綠的後者大於前者，不交換)**
![image](https://hackmd.io/_uploads/Hy9F9f-PR.png)
![image](https://hackmd.io/_uploads/B1AcozWDC.png)

**第二次交換(將區塊($3$)除以$2$(不必定為$2$)，$3/2$得$1$，便是將他隔成1區(在這等於直接做插入排序法)，相同區塊做比較後交換，即顏色所示)**
![image](https://hackmd.io/_uploads/B1anuXZwC.png)
![image](https://hackmd.io/_uploads/rJFkKQbvC.png)
::: 

### <font color="#2FB428">程式碼(配合例題)</font>
:::danger
:::spoiler 點我打開 (太長了，建議看完收起)
```cpp=
#include<iostream>
using namespace std ;
int main () {
	int a , j , shell ;
	cin >> a ;
	int arr[a] ;
	for (int i = 0 ; i < a ; i ++) {  //輸入資料
		cin >> arr[i] ;
	}
	shell = a / 2 ;                   //謝耳排序法
	while (shell != 0) {
		for (int i = shell ; i < a ; i ++) {    //裡頭的插入排序法
			int tmp ;
			tmp = arr[i] ;
			j = i - shell ;
			while (j >= 0 && arr[j] > tmp) {
				arr[j+shell] = arr[j] ;
				j = j - shell ;
			}
		arr[j+shell] = tmp ;
		}
		shell = shell / 2 ;
	}
	cout << arr[0] ;      //輸出資料(配合例題故以此方式輸出)
    for (int i = 1 ; i < a ; i ++) { 
        cout << ' ' << arr[i] ;
    } 
	cout << '\n' ;
}
```
:::

---
# 快速排序法(quick sort)
目前公認最佳的排序法，使用切割征服法，自行設定一個中間值，以此中間值將所有資料分成兩部分，小於中間值置於左側，大於則相反，在以相同方式處理兩邊資料，以此類推直至排序完成。(於我看來，和二分搜的概念類似)

### <font color="#2FB428">分析</font>
$1.$ 不穩定的排序法。
$2.$ 時間複雜度為 $O(n~log_2~n)$。
$3.$ 空間複雜度最差為 $O(n)$ ，最佳為 $(log_2~n)$。
$4.$ 平均執行時間最快。

### <font color="#2FB428">圖例</font>
:::warning
:::spoiler 點我打開 (太長了，建議看完收起)
**原始資料:**
![image](https://hackmd.io/_uploads/rJLeGGeDA.png)

**設一鍵值(通常取第一位)，小丟左大丟右:**
![image](https://hackmd.io/_uploads/ryOvwLbwA.png)
![image](https://hackmd.io/_uploads/B1J4uLZvR.png)

**再來在五的左側設一鍵值(通常取第一位)，小丟左大丟右，左半排序完成(若在這取的鍵值不為0或1還要繼續):**
![image](https://hackmd.io/_uploads/SkPOuIZvA.png)
![image](https://hackmd.io/_uploads/BJs9dI-w0.png)

**再來在五的右側設一鍵值(通常取第一位)，小丟左大丟右，右半排序完成(若在這取的鍵值不為0或1還要繼續):**
![image](https://hackmd.io/_uploads/SyGGKIbPR.png)
![image](https://hackmd.io/_uploads/BJ7Ut8ZwC.png)
:::

### <font color="#2FB428">程式碼(配合例題)</font>
:::danger
:::spoiler 點我打開 (太長了，建議看完收起)
```cpp=
#include<iostream>
using namespace std ;

int partition(int arr[], int low, int high);

void quickSort(int arr[], int low, int high) {    //快速排序法
    if (low < high) {
        int pivotIndex = partition(arr, low, high);
        quickSort(arr, low, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, high);
    }
}

int partition(int arr[], int low, int high) {
    int pivot = arr[high];  
    int i = low - 1;     
    for (int j = low; j <= high - 1; j++) {
        if (arr[j] <= pivot) {
            i++; 
            swap(arr[i], arr[j]); 
        }
    }
    int tmp ;
    tmp = arr[i+1] ;
    arr[i+1] = arr[high] ;
    arr[high] = tmp ;
    return i + 1;
}

int main() {
    int a;
    cin >> a;
    int arr[a];
    for (int i = 0; i < a; i++) {  //輸入資料
        cin >> arr[i];
	}
    quickSort(arr, 0, a - 1);
    cout << arr[0];      //輸出資料(配合例題故以此方式輸出)
    for (int i = 1; i < a; i++) {
        cout << ' ' << arr[i];
    }
    cout << '\n';
    return 0;
}
```
:::

---
# 合併排序法(merge sort)
針對已排序好的兩個或兩個以上的檔案由合併的方式，組成一個排序好的檔案。

#### <font color="#2FB428">分析</font>
$1.$ 穩定的排序法。
$2.$ 時間複雜度為 $O(n~log~n)$。
$3.$ 空間複雜度為 $O(n)$。
$4.$ 適用資料量大的外部檔案。

### <font color="#2FB428">圖例</font>
:::warning
:::spoiler 點我打開 (太長了，建議看完收起)
**原始資料:**
![image](https://hackmd.io/_uploads/rJLeGGeDA.png)

**先拆分:**
![image](https://hackmd.io/_uploads/SkyjKD5D0.png)
![image](https://hackmd.io/_uploads/B1Y0YDqvR.png)
![image](https://hackmd.io/_uploads/SJ_O9w9PA.png)

**會得到:**
再來進行合併的動作。
![image](https://hackmd.io/_uploads/SkXf64WvC.png)

**後合併(合併的資料做排序):**
![image](https://hackmd.io/_uploads/S1HeovcPC.png)
![image](https://hackmd.io/_uploads/r1VBiPcw0.png)
![image](https://hackmd.io/_uploads/ryaOjDcDC.png)
:::

### <font color="#2FB428">程式碼(配合例題)</font>
:::danger
:::spoiler 點我打開 (太長了，建議看完收起)
```cpp=
#include<iostream>
using namespace std;

void merge(int arr[], int left, int middle, int right) {
    int n1 = middle - left + 1;
    int n2 = right - middle;
    int leftArr[n1], rightArr[n2];
    for (int i = 0; i < n1 ; i++) {
	    leftArr[i] = arr[left + i];
	}
    for (int j = 0; j < n2; j++) {
    	rightArr[j] = arr[middle + 1 + j];
	}
    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (leftArr[i] <= rightArr[j]) {
            arr[k] = leftArr[i];
            i++;
        } else {
            arr[k] = rightArr[j];
            j++;
        }
        k++;
    }
    while (i < n1) {
        arr[k] = leftArr[i];
        i++;
        k++;
    }
    while (j < n2) {
        arr[k] = rightArr[j];
        j++;
        k++;
    }
}

void mergeSort(int arr[], int left, int right) {    //合併排序法
    if (left < right) {
        int middle = left + (right - left) / 2;
        mergeSort(arr, left, middle);
        mergeSort(arr, middle + 1, right);
        merge(arr, left, middle, right);
    }
}

int main() {
    int a;
    cin >> a;
    int arr[a];
    for (int i = 0; i < a; i++) {  //輸入資料
        cin >> arr[i];
    }
    mergeSort(arr, 0, a - 1);
    cout << arr[0] ;      //輸出資料(配合例題故以此方式輸出)
    for (int i = 1 ; i < a ; i++) {  
        cout << ' ' << arr[i] ;
    } 
	cout << '\n' ;
}
```
:::

---
# 堆積排序法(heap sort)
選擇排序法的改版，減少其的比較次數，利用到二元樹(後續的課程)的堆積樹。

### <font color="#2FB428">分析</font>
$1.$ 不穩定的排序法。
$2.$ 時間複雜度為 $O(n~log_2~n)$。
$3.$ 空間複雜度為 $O(n)$。

### <font color="#2FB428">圖例</font>
在進行堆積排序法的圖例前要先介紹什麼是堆積樹，不然不好解釋堆積排序法是怎麼進行的。


::: info
::: spoiler 堆積樹 (本題以最大堆積樹舉例)
**同樣以5 2 7 4 9 來解釋**
![image](https://hackmd.io/_uploads/SJcY2CQwR.png)

**arr [0] 跟arr [1] 比較，前者大於後者，不交換**
![image](https://hackmd.io/_uploads/SJcY2CQwR.png)

**arr [0] 跟arr [2] 比較，後者大於前者，交換**
![image](https://hackmd.io/_uploads/S1xc60mvR.png)

**arr [1] 跟arr [3] 比較，後者大於前者，交換。
此時的arr [1] 再跟 arr[0] 做比較，後者大於前者，不交換**
![image](https://hackmd.io/_uploads/H1Qx00mvR.png)

**arr [1] 跟arr [4] 比較，後者大於前者，交換。
此時的arr [1] 再跟 arr[0] 做比較，前者大於後者，交換**
(第一步)
![image](https://hackmd.io/_uploads/HycQCC7vC.png)
(第二步)
![image](https://hackmd.io/_uploads/HkPmyJ4DC.png)

**便可得到該陣列中最大的元素，提出，刪掉樹根，重複直至排序結束。**
:::

:::warning
:::spoiler 點我打開 (太長了，建議看完收起)
**原始資料:**
![image](https://hackmd.io/_uploads/rJLeGGeDA.png)

**第一次建立堆積樹**
![image](https://hackmd.io/_uploads/H1sFg1EDR.png)

**第二次建立堆積樹**
![image](https://hackmd.io/_uploads/BkUsl1NwR.png)

**第三次建立堆積樹**
![image](https://hackmd.io/_uploads/ryK6l1EDR.png)

**第四次建立堆積樹**
![image](https://hackmd.io/_uploads/B1pr-yVPA.png)

**第五次建立堆積樹**
![image](https://hackmd.io/_uploads/HyYvZJVvR.png)
:::

### <font color="#2FB428">程式碼(配合例題)</font>
:::danger
:::spoiler 點我打開 (太長了，建議看完收起)
```cpp=
#include <iostream>
using namespace std;

void heap(int arr[], int n, int i) {
    int largest = i; 
    int left = 2 * i + 1; 
    int right = 2 * i + 2; 
    if (left < n && arr[left] > arr[largest]) {
        largest = left;
    }
    if (right < n && arr[right] > arr[largest]) {
        largest = right;
    }
    if (largest != i) {
        swap(arr[i], arr[largest]);
        heap(arr, n, largest);
    }
}

void heapSort(int arr[], int n) {    //堆積排序法
	
    for (int i = n / 2 - 1; i >= 0; i--) {
        heap(arr, n, i);
    }
    
    for (int i = n - 1; i > 0; i--) {
        swap(arr[0], arr[i]);
        heap(arr, i, 0);
    }
}

int main() {
    int a ;
    cin >> a ;
    int arr[a] ;
    for (int i = 0 ; i < a ; i++) {  //輸入資料
    	cin >> arr[i] ;
    }
    heapSort(arr, a-1);
    cout << arr[0] ;      //輸出資料(配合例題故以此方式輸出)
    for (int i = 1 ; i < a ; i++) {  
        cout << ' ' << arr[i] ;
    } 
	cout << '\n' ;
}
```
:::

---
# 基數排序法(radix sort)
以分配模式排序，有 最高有效鍵值開始排序(MSD) 和 從最低有效鍵值開始排序(LSD)。
換句話說基數排序法不同於其他類型的排序法，他排序的方法利用的了數學的概念，**數字的大小和其位數有關**，利用這一點來進行排序。

### <font color="#2FB428">分析</font>
$1.$ 穩定的排序法。
$2.$ 時間複雜度為 $O(n \; log_b \; k)$，$b$ 為底數。
$3.$ 空間複雜度為 $O(n+k)$。

### <font color="#2FB428">圖例</font>
:::warning
:::spoiler 點我打開 (太長了，建議看完收起)
**原始資料:(為更詳細介紹，故將資料增加不同位數)**
![image](https://hackmd.io/_uploads/BJql5ZNP0.png)

**第一次排序:(排個位數)**
![image](https://hackmd.io/_uploads/rkFh5-VwC.png)

**第二次排序:(排十位數)**
![image](https://hackmd.io/_uploads/r18mjbVv0.png)

**第三次排序:(排百位數，若無則當0)**
![image](https://hackmd.io/_uploads/ry_qsZEvA.png)

**第四次排序:(排千位數，若無則當0)**
![image](https://hackmd.io/_uploads/ry_qsZEvA.png)
:::

### <font color="#2FB428">程式碼(配合例題)</font>
:::danger
:::spoiler 點我打開 (太長了，建議看完收起)
```cpp=
int getMax(int arr[], int n) {
    int max = arr[0];
    for (int i = 1; i < n;i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

void countSort(int arr[], int n, int exp) {
    int output[n]; 
    int count[10] = {0}; 

    for (int i = 0; i < n; i++) {
        count[(arr[i] / exp) % 10]++;
    }
    
    for (int i = 1; i < 10; i++) {
        count[i] += count[i - 1];
    }
    
    for (int i = n - 1; i >= 0; i--) {
        output[count[(arr[i] / exp) % 10] - 1] = arr[i];
        count[(arr[i] / exp) % 10]--;
    }
    
    for (int i = 0; i < n; i++) {
        arr[i] = output[i];
    }
}

void radixSort(int arr[], int n) {    //基數排序法

    int max = getMax(arr, n);
    
    for (int exp = 1; max / exp > 0; exp *= 10) {
        countSort(arr, n, exp);
    }
}

int main() {
    int a ;
    cin >> a ;
    int arr[a] ;
    for (int i = 0 ; i < a ; i++) {  //輸入資料
    	cin >> arr[i] ;
    }
    radixSort(arr, a-1);
    cout << arr[0] ;      //輸出資料(配合例題故以此方式輸出)
    for (int i = 1 ; i < a ; i++) {  
        cout << ' ' << arr[i] ;
    } 
	cout << '\n' ;
}
```
:::

# 例題
###### 有什麼題目沒提到或有新增的煩請留言告知。
[a066: Sort! Sort! Sort!](https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid=a066)

[a083: Sort yourself 1](https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid=a083)

[a084: Sort yourself 2](https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid=a084)

[a208: 真 ● 泡沫排序法](https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid=a208)

[a248: pI 你那第幾中隊的R 會不會排隊R 亂七八糟 一點紀律都沒有](https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid=a248)

[a934: 泡沫排...?](https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid=a934)

###### 都看到這了難道不按個愛心支持一下嗎?