---
tags: 大二筆記
---
# 資料結構 上
### IDE Code
WEEK_2:[正課](http://tpcg.io/LPPGDK)
[9.30實習題_Insertion_Sort](http://tpcg.io/ReFUIudS)
[9.30實習題_binary_search](http://tpcg.io/R0V5GY)
[9.30加分題_交集法_DFS](http://tpcg.io/IGWVDP)
WEEK_3:
[10.7實習題_非連續子序列之兩數最大和(Struct & Sort)](http://tpcg.io/C0JIB1)
[10.7延伸題_最大非連續子序列和(DP)](http://tpcg.io/6OEW46)
[10.7加分題_奇數魔方陣](http://tpcg.io/AL4WPS)
## I/O Stream(課外補充)
### I/O 優化(加速輸入輸出 遇TLE可用)
```c=
//取消強制flush
cin.tie(0);
//取消 iostream 與 stdio 的同步使用
ios_base::sync_with_stdio(false);
//不使用 cout << endl
cout << "\n";
```
### StringStream(好工具)
getline 搭配 stringstream
### 輸出
四捨五入cout << fixed << setprecision(10); 或是更高精度 (int)10*位數+0.5
寬度 cout << setw(n) << setfill( c ) <<;
參考資料:
https://cp.wiwiho.me/
## Swap
### Define
```c=
#define swap(x, y, t) ((t) = (x), (x) = (y), (y) = (t))
```
### Call by address (Call by pointer)
```c=
void swap(int *x,int *y){
int tmp=*x;
*x=*y;
*y=tmp;
}
```
### Call by reference
```c=
void swap(int &x,int &y){
int tmp=x;
x=y;
y=tmp;
}
```
## Auto
根據使用型態變化
### 變數宣告
```c=
// int x = 1;
auto x = 1;
// double y = sin(1.3);
auto y = sin(1.3);
```
### 陣列宣告
```c=
// initializer_list<int>
auto A = { 1, 2 };
// initializer_list<int>
auto B = { 3 };
```
### 函式宣告
```c=
// int my_fun();
auto my_fun(){
int value = 3;
return value;
}
```
參考資料:
https://blog.gtwang.org/programming/cpp-auto-variable-tutorial/
https://docs.microsoft.com/zh-tw/cpp/cpp/auto-cpp?view=msvc-160
<br>
## For Loop
使用於任何陣列。
for( auto y : x ){...}
y = x.begin() → x.end()。
```c=
int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//float[]、vector<double>,任何陣列。
```
### Call by value
```c=
for( auto y : x ){
y++;
}
//int x[10] = {1,2,3,4,5,6,7,8,9,10};
```
### Call by reference
可以修改陣列
```c=
for( auto &y : x ){
y++;
}
//int x[10] = {2,3,4,5,6,7,8,9,10,11};
```
參考資料:
https://docs.microsoft.com/zh-tw/cpp/cpp/range-based-for-statement-cpp?view=msvc-160
<br>
## Dynamic Memory Allocation
```c=
int *i;
float *pi;
i=(int*)malloc(sizeof(int));//動態記憶體配置
*i=1024;
pi=(float*)malloc(sizeof(float));//動態記憶體配置
*pi=3.1415;
printf("i=%d,pi=%d",*i,*pi);
free(i);
free(pi);
```
## Selection sort
從未排序中,選擇最小的放進數列中
<img src="https://codepumpkin.com/wp-content/uploads/2017/10/SelectionSort_Avg_case.gif">
```c=
//n為list大小
for(i=0;i<n;i++){ //i之前已排好
for(j=i+1;j<n;j++){ //i之後選擇最小的丟到前面去
if(list[i]>list[j]){
swap(&list[i],&list[j]);
}
}
}
for(i=0;i<n;i++){
printf("%d,",list[i]);
}
```
參考資料:
https://medium.com/appworks-school/%E5%88%9D%E5%AD%B8%E8%80%85%E5%AD%B8%E6%BC%94%E7%AE%97%E6%B3%95-%E6%8E%92%E5%BA%8F%E6%B3%95%E5%85%A5%E9%96%80-%E9%81%B8%E6%93%87%E6%8E%92%E5%BA%8F%E8%88%87%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F%E6%B3%95-23d4bc7085ff
<br>
## Insertion Sort
插入已排列的數列
題目:http://140.121.198.41:20211/contest/5/problem/2
<img src="https://upload.wikimedia.org/wikipedia/commons/9/9c/Insertion-sort-example.gif">
```c=
for(i=1;i<n;i++){ //輪到i去插入
int tmp = list[i]; // tmp = 正處理的值
j=i-1;
while( j>-1 && tmp<list[j] ){
itst[j+1]=list[j]; // 向右移
j--;
}
list[j+1]=tmp; // 插入新值
}
```
參考資料:
http://notepad.yehyeh.net/Content/Algorithm/Sort/Insertion/1.php
<br>
## Bubble Sort
<img src="https://codepumpkin.com/wp-content/uploads/2017/10/BubbleSort_Avg_case.gif">
## Merge Sort
<img src="https://cdn-images-1.medium.com/max/1600/1*d9AkauyhqsMZcLFYhrY3DQ.gif">
## Quick Sort
<img src="https://img-blog.csdnimg.cn/20191109215106141.gif">
## Binary_search
只適用於<font color="#f00">**「已排序」**</font>的數列
題目:http://140.121.198.41:20211/contest/5/problem/1
<img src="https://static.coderbridge.com/img/techbridge/images/huli/binary_search.gif">
### Main
```c=
int mid,L,R,target;
scanf("%d",&target);
L=0,R=n-1;
```
### Recursion
```c=
int binary_search(int L,int R,int list[],int target,int mid){
if(L<=R){ //終止條件
mid=(L+R)/2;
if(target==list[mid]){
return mid;
}
else if(target<list[mid]){
binary_search(L,mid-1,list,target,mid);
}
else{
binary_search(mid+1,R,list,target,mid);
}
}
return -1;
}
```
### Non-Recursion
```c=
int binary_search(int L,int R,int list[],int target,int mid){
while(L<=R){
mid=(L+R)/2;
if(target==list[mid])
return mid;
else if(target<list[mid])
R=mid-1;
else
L=mid+1;
}
return -1;
}
```
### Binary search tree
<img src="https://mmbiz.qpic.cn/mmbiz/QtPIxk7nOVeibpicoibyjNZKic9Ke41yzr53nolQM6w5ibEKzg8GCbbCrSOs75gH6ibzsKuyWLtqfJOgwMW0mibprneEQ/0?wx_fmt=gif">
參考資料:
https://www.gushiciku.cn/dc_tw/101530793
https://blog.techbridge.cc/2016/09/24/binary-search-introduction/
<br>
## 加分題_交集法(DFS)
題目:http://140.121.198.41:20211/contest/5/problem/a1
作法:
1 1 1 1 0 0 0 0 0 0
1 1 1 1 0 1 0 0 0 0
1 1 1 1 0 1 0 1 1 0 >>解答1 回復上一動
1 1 1 1 0 1 0 0 1 1 >>解答2 回復上一動
1 1 1 1 0 0 1 0 0 0
1 1 1 1 0 0 1 0 1 1 >>解答3 回復上一動
1 1 1 1 0 0 0 1 0 0
1 1 1 1 0 0 0 0 1 0
1 1 1 1 0 0 0 0 0 1
...
<img src="https://raw.githubusercontent.com/tg6169/tmp/master/new_dfs.gif">
### DFS
```c=
//input:n=10,inp[0..2]=4,1,2
//Output:0 1 1 1 0 0 0 0 1 0
//index=走訪位置,ans[]=答案,m為inp的序號
void DFS(int index,int m){
if(m==inp_size){//等於最後一個
for(int j=0;j<n;j++){ //check有重複出現的位置。
ans[j]=ans[j]&tmp[j]; //位元運算
}
}
else{
while(index<n){
if(check(index,inp[m])){ //判斷可不可以放進去。
for(int j=0;j<inp[m];j++){ //放入方塊。
tmp[index+j]=1;
}
DFS(index+inp[m],m+1); //進到下一層,左子樹。
for(int j=0;j<inp[m];j++){ //回復上一動,回節點。
tmp[index+j]=0;
}
}
index++;
}
}
}
```
### Check
```c=
bool check(int index,int m){
if((index==0||tmp[index-1]==0)&&(tmp[index+m]==0)&&((index+m)<=n)){
return true;
}
else{
return false;
}
}
```
### Main
```c=
int main() {
cin >> n; //陣列大小
inp_size=0;
while(cin >> inp[inp_size]){ //輸入input
inp_size++;
}
for(int j=0;j<n;j++){ //設為0
tmp[j]=0,ans[j]=1;
}
DFS(0,0);
for(int j=0;j<n;j++){
printf("%d ",ans[j]);
}
return 0;
}
```
## Abstraction
透過語意、規範,隱藏實作過程來簡化程式。
### Data Abstraction
透過資料型態(規範),來包裝各種元素。
* #### Array
```c=
int list[5]={0,1,2,3,4}; //儲存單一型態
```
* #### Structure
```c=
struct student{ //儲存多數型態
char lastName;
int studentId;
char grade;
}
```
### Abstraction Data Type(ADT)
以規範好的行為,去操作資料形態中的物件。
```c=
stack<int> Stack;
Stack.push(...)
Stack.pop
cout << Stack.top();
```
```c=
Bool IsZero(int x){
x==0?true:false
}
Bool Equal(int x,int y){
x==y?true:false
}
```
## Performance Analysis
### Space Complexity
```c=
float rsum(float list[ ], int n){
if(n)return rsum(list, n-1) + list[n-1];
return list[0];
}
```
Total
= float list[ ] + int n + return addres
= 4 + 4 + 4 = 12n
### Time Complexity
1. assignment
2. for loop <font color="#f00">**(n+1)**</font>
3. return
4. conditional
```c=
float sum(float list[ ], int n){
float tempsum= 0; count++; /* for assignment */
int i;
for (i= 0; i< n; i++){
count++; /* for the "for" loop */
tempsum+= list[i]; count++; /* for assignment */
}
count++; /* last execution of "for" */
count++; /* for return */
return tempsum;
}
```
### Asymptotic Notation(O, Ω, Θ)
* #### Big O
f(n) ≤ cg(n) for all n, n≥n<sub>0</sub>
<img src="https://player.slideplayer.com/25/7799420/data/images/img1.jpg">
* #### Omega Ω
f(n) ≥ cg(n) for all n, n≥n0
<img src="https://player.slideplayer.com/25/7799420/data/images/img3.jpg">
* #### Theta Θ
c<sub>1</sub> g(n) ≤ f(n) ≤ c<sub>2</sub> g(n) for all n, n≥n<sub>0</sub>
<img src="https://cdn.programiz.com/sites/tutorial2program/files/theta.png" width="280">
## Fibonacci
### Recursion
```c=
int fibonacci(int n) {
if(n<2){
return n;
}
if(n>=2){
return fibonacci(n-1)+fibonacci(n-2);
}
}
```
### Non-Recursion(DP)
```c=
int fibonacci(long long int n) {
for(int m=0;m<=n;m++){
if(m>=2){
c=a;
a=b;
b=c+b;
}
else if(m<2){
a=0;
b=1;
}
}
if(n<2&&n!=0){
return n;
}
else if(n>=2){
return b;
}
}
```
## 非連續子序列之兩數最大和(Struct & Sort)
### Struct
```c=
struct list {
int value;
int index;
};
```
### Sort compare
```c=
bool compare(list &s1, list &s2){
return s1.value > s2.value;
}
```
### Main
```c=
int main() {
int n,m;
list L[100000]; //struct
/*---------------輸入---------------*/
std::cin >> n;
for(m=0;m<n;m++){
std::cin >> L[m].value;
L[m].index=m;
}
int sub_len=m; //list長度
/*-------------搜尋比對-------------*/
if(sub_len==3){ //spical case:子序列長度=1
std::cout << L[0].value+L[2].value;
}
else{
std::sort(L,L+sub_len,compare); //找出前四大的數
int tmp,max = -INT16_MAX;
for(m=0;m<4;m++){ //比對是否相鄰
for(int i=m+1;i<4;i++){
if(abs(L[m].index-L[i].index)>1){ //比對是否相鄰
tmp=L[m].value+L[i].value; //找出最大和
if(tmp>max){
max=tmp;
}
}
}
}
std::cout << max;
}
return 0;
}
```
參考資料:範例八 https://shengyu7697.github.io/std-sort/
## 課外延伸題_最大非連續子序列和(DP)
### DP(Dynamic programming)
```c=
int sub_max(int* list){
if(sub_len==3){
return list[0]+list[2];
}
int temp[10005];
for(int m=0;m<sub_len;m++){
temp[m]=list[m];
}
temp[0]=list[0];
temp[1]=list[1]>list[0]?list[1]:list[0];
for(int i = 2;i<sub_len;i++){
temp[i]=max(max(temp[i],temp[i-1]),temp[i-2]+list[i]);
}
return temp[sub_len-1];
}
```
### Main
```c=
int main() {
int n,m;
int list[10005];
cin >> n;
for(m=0;m<n;m++){
cin >> list[m];
}
sub_len=m;//list大小,global變數
cout << sub_max(list);
return 0;
}
```
## 加分題_奇數魔方陣
題目:http://140.121.198.41:20211/contest/6/problem/a1
<img src="https://openhome.cc/Gossip/AlgorithmGossip/images/oddArray-2.jpg">
<br>
``` c=
int main(void) {
int square[row][column] = {0};
int N,K;
int r,c; //r=row_index,c=column_index
int r2,c2; //儲存上一步
cin >> N; //space
r=1; //first_step
c=N/2+1;
square[r][c]=1;
for(K=2;K<=N*N;K++){
r--; //下一步
c++;
if (r < 1)r=N; //邊界
if (c > N)c=1;
if(square[r][c]){ //重複出現
r=r2+1; //回到上一步
c=c2;
if(r>N)r=1; //邊界
}
c2=c; //儲存
r2=r;
square[r][c]=K; //放入K
}
return 0;
}
```
參考資料:
https://openhome.cc/Gossip/AlgorithmGossip/OddArray.htm
## Struct
### typedef
## Union