###### tags: `資料結構 & 演算法`
{%hackmd @kk6333/theme-sty1 %}
# DS1 - 遞迴 & 二分搜尋法 Binary Search
## 遞迴
遞迴是利用重複呼叫函數來達成目的
需要有幾項設定
- base line : 為遞迴的中止條件
- 相同函數呼叫 : 顧名思義
這邊簡單寫一個加成遞迴,在 num >= 3 時會跳出遞迴函數
```cpp=
void Add( int num ){
if(num >= 3) return; // base line
Add( num + 1 ); // 重複呼叫函數
}
```
---
<br>
## 二分搜尋法 Binary Search
這邊紀錄一下第一個學到的演算法 ~ Binary Search
Binary Search 的用法、寫法可以有很多種
但主要的想法是將資料"**分半**"進行操作
這邊用兩個例子來解釋、練習
<br>
### Example.1 : 尋找指定 value 的位置(index)
我們現在有一個 5 個數字按照大小排序的 List
```cpp=
int arr[] = {1,3,5,8,11};
```
會指定一個 List 中的值,並找出其位置 index
如果使用二分搜尋法可以使用以下想法
**先上Code**
```cpp=
// 二分搜尋
int BinarySearch( int arr[], int first, int last, int value ){
// 設定中點 index
int mid_idx = (first + last) / 2;
// 如果 List 中沒有此 value
if(first == last && value != arr[mid_idx] ) return -1;
// mid 為 value
if ( value == arr[mid_idx]) return mid_idx;
// 篩選出左邊界
else if ( value > arr[mid_idx] ) return BinarySearch( arr, mid_idx + 1, last, value );
// 篩選出右邊界
else return BinarySearch( arr, first, mid_idx - 1, value );
}
```
**解釋**
:::warning
> first : 左邊界 index
> last : 右邊界 index
會將 List 設一個 [左邊界]、[右邊界]
當要找的 value 大於當前的中點,我們會縮減左邊界,
因為左邊的數字皆小於中點 => 小於 value,反之縮減右邊界
> ex:
> value=8
> {1,3,5,8,11} => 中點=5 => 縮小左邊界 {~~1,3,5~~,8,11}
當中點等於 value 時便 return 中點 index
如無法在縮減邊界 (剩下一數字),但未找到 value ,則傳回 -1
可以將整個方法視為不斷把資料"分半"直到剩下資料的中點為要的值
:::
---
<br>
### Example.2 : 尋找最大值
現在有一個 5 個數字不按順序排的 List
```cpp=
int arr[] = {3,1,7,13,2};
```
要找出 List 中的最大值
**先上Code**
```cpp=
// 利用二分搜尋找最大值
int MaxBinarySearch( int arr[], int first, int last){
// 只剩一個數字 (最底層)
if(first == last) return first;
// 中點 index
int mid_idx = (first + last) / 2;
// 獲得下層最大的數 index
int idx1 = MaxBinarySearch( arr, mid_idx+1, last ); // 右半邊
int idx2 = MaxBinarySearch( arr, first, mid_idx ); // 左半邊
// 回傳較大的數 index
if(arr[idx1] > arr[idx2]) return idx1;
else return idx2;
}
```
**解釋**
:::warning
> first : 左邊界 index
> last : 右邊界 index
這邊我將 List 以"中點"將個數字劃分為了一個個的節點
當只剩一個數時 (劃分到最後一個節點) 開始回傳數字 index
並跟前一劃分的 Node 比大小,較大的數字可繼續往上比
用下圖可以更直觀解釋

:::