Quiz 11
===
# Index
1. [總說明](#%E7%B8%BD%E8%AA%AA%E6%98%8E)
- [`main()`](#main-line-1--line-25)
- [`sort()`](#main-line-1--line-25)
- [`weight()`](#weightchar-c-line-79--line-85)
2. [[A] Bubble Sort](#A-Bubble-Sort)
- [Explanation](#Explanation)
- [Code](#Code)
3. [[B] Selection Sort]()
- [Explanation](#Explanation1)
- [Code](#Code1)
4. [[C] Insertion Sort]()
- [Explanation](#Explanation2)
- [Code](#Code2)
# 總說明
這週三題的解法相差無幾,差別僅在於演算法而已,因此會先在這裡一次說明他們的做法。
以下將以[[B] Selection Sort](https://hackmd.io/gvmuZuSMSlSeTEsvD5h2Lg#B-Selection-Sort)做範例說明。
### `main()` (line 1 ~ line 25)
1. 首先先建立一個字元陣列,其長度(在此為`SIZE` = 60)隨意,只要能存入所有輸入的字元即可。
2. 欲將使用者輸入的字串存入陣列中的方法有許多種,`scanf`(需一個一個字元慢慢讀取,無法一次讀取完整的含有空白的字串), `gets`, `fgets`等等,因使用`gets`有時會有warning,因此在此我選則使用`fgets`。
`gets`及`fgets`有點類似,當未有任何字串被輸入,將會回傳NULL,所以若想讓程式執行直到輸入EOF,直接寫`while(gets(string))`即可。
- `gets(string)`
- `fgets(string, string_length, FILE)`
- 讀取鍵盤的輸入時,將FILE設為stdin
3. 為了符合題目所要求的輸出規則(每組不同input之間需有一行空白,而最後一次輸出後則無一行空白),需另外設立一個變數(在此為`printed`)來判斷此次input是否為第一次,若為第一次,則不需留空,若是,則輸出一行空白行。
4. 呼叫函式,排序及輸出等等的皆會在函式中進行。
5. 結束以上工作後,再進行下一輪前需要先將陣列初始化,避免上一次所輸入的字串較下一次的長,使得一些上次所存的字元仍留在字串中,被誤認為是新輸入的字串內容。
- 可使用`for` loop將字元陣列裡的每一格皆設定為一個非使用者會輸入的值(e.g. 空白, , ,& 等等)
- 在此使用動態陣列calloc
- calloc會將每格皆初始化為0
- [動態陣列說明](https://openhome.cc/Gossip/CGossip/MallocFree.html)
### `sort(char arr[])` (line 27 ~ line 77)
sort()可簡單為以下執行事項
1. 建立一個新字元陣列,其中只留下我們需要的字元
2. 輸出(`pass`)
3. 排序
說明:
1. 新字元陣列
- 此陣列的長度隨意,只要能夠儲存每一項即可
- 使用for loop,並判段`arr`(原陣列)裡的每個字元是否為所求,若是,則將它存入`new_arr`(新陣列)之中。
- 在將各個字元存入新陣列的同時,需同時紀錄新陣列所儲存的項目數,這將在之後的排序及輸出用到
- [A]題因為有負數的關係,因此新陣列的變數型態需設為`int`,才有辦法儲存負數,其餘字元將以ascii 表中所對應到的數值儲存。
- 註:B, C題中在字元陣列的尾端加上`\0`僅僅是為了方便測試,此行非必要
2. 輸出
- 此三題皆會用到兩層迴圈,而輸出的部分需放在外層迴圈內。
4. 排序
- 詳見各題
### `weight(char c)` (line 79 ~ line 85)
因為B, C題須依照題目所規定的大小優先順序排列,因此需另外使用一個陣列(在此為`w_arr` (line 8))儲存它們所對應到的大小,並使用此函式以得到各個字元的數值。
此函式將會利用for loop在`w_arr`中尋找與parameter `c`相同的字元,若找到了,將會回傳字元在`w_arr`的index,其index即為它的大小、先後順序。
# [A] Bubble Sort
## Explanation
Bubble Sort動畫說明:https://www.youtube.com/watch?v=nmhjrI-aW5o
## Code
```c=
#include <stdio.h>
#include <stdlib.h>
#define SIZE 60
void bubble_sort(char arr[]);
int main(){
char *input = calloc(SIZE, sizeof(char));
int printed = 0;
while(fgets(input, SIZE, stdin)){
if(printed){
puts("");
}
else{
printed = 1;
}
bubble_sort(input);
free(input);
input = calloc(SIZE, sizeof(char));
}
}
void bubble_sort(char arr[]){
//create new array without spaces and other useless char
int *new_arr = malloc(SIZE * sizeof(int));
int len = 0;
int negative = 0;
int swapped;
int tmp;
for(int i=0; i<SIZE; i++){
if(((arr[i] >= 'a') && (arr[i] <= 'z')) || ((arr[i] >= 'A') && (arr[i] <= 'Z'))){
new_arr[len++] = arr[i];
}
else if((arr[i] >= '0') && (arr[i] <= '9')){
new_arr[len++] = arr[i];
if(negative){
new_arr[len-1] *= (-1);
negative = 0;
}
}
else if(arr[i] == '-'){
negative = 1;
}
}
for(int i=0; i<len; i++){
//print
printf("Pass %d:", i);
for(size_t idx=0; idx<len; idx++){
if(new_arr[idx] < 0){
printf(" -%c", new_arr[idx]*(-1));
}
else{
printf(" %c", new_arr[idx]);
}
if(idx == (len-i-1)){
printf(" /");
}
}
puts("");
//sort, swap
swapped = 0;
for(int j=1; j<len-i; j++){
if(new_arr[j] < new_arr[j-1]){
tmp = new_arr[j];
new_arr[j] = new_arr[j-1];
new_arr[j-1] = tmp;
swapped = 1;
}
}
if(!swapped){
break;
}
}
}
```
# [B] Selection Sort
## Explanation
Selection Sort動畫說明:https://www.youtube.com/watch?v=xWBP4lzkoyM
## Code
```c=
#include <stdio.h>
#include <stdlib.h>
#define SIZE 60
void selection_sort(char arr[]);
size_t weight(char c);
char w_arr[22] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F'};
int main(){
char *input = calloc(SIZE, sizeof(char));
int printed = 0;
while(fgets(input, SIZE, stdin)){
if(printed){
puts("");
}
else{
printed = 1;
}
selection_sort(input);
free(input);
input = calloc(SIZE, sizeof(char));
}
}
void selection_sort(char arr[]){
//create new array without spaces and other useless char
char *new_arr = malloc(SIZE * sizeof(char));
int len = 0;
for(int i=0; i<SIZE; i++){
if(((arr[i] >= '0') && (arr[i] <= '9')) || ((arr[i] >= 'a') && (arr[i] <= 'f')) || ((arr[i] >= 'A') && (arr[i] <= 'F'))){
new_arr[len++] = arr[i];
}
}
new_arr[len] = '\0';
size_t smallest_idx;
size_t smallest_w, curr_w;
char tmp;
//sorting
for(int pass=0; pass<len; pass++){
//print
printf("Pass %d:", pass);
for(size_t i=0; i<len; i++){
if(i == pass){
printf(" /");
}
printf(" %c", new_arr[i]);
}
puts("");
if(pass == len-1){
break;
}
//find smallest
smallest_idx = pass;
smallest_w = weight(new_arr[smallest_idx]);
for(size_t curr=pass+1; curr<len; curr++){
curr_w = weight(new_arr[curr]);
if(curr_w < smallest_w){
smallest_idx = curr;
smallest_w = curr_w;
}
}
//swap
tmp = new_arr[pass];
new_arr[pass] = new_arr[smallest_idx];
new_arr[smallest_idx] = tmp;
}
free(new_arr);
}
size_t weight(char c){
for(int i=0; i<22; i++){
if(c == w_arr[i]){
return i;
}
}
}
```
# [C] Insertion Sort
## Explanation
Insertion Sort 動畫說明:https://www.youtube.com/watch?v=OGzPmgsI-pQ
## Code
```c=
#include <stdio.h>
#include <stdlib.h>
#define SIZE 60
void insertion_sort(char arr[]);
size_t weight(char c);
char w_arr[14] = {'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'};
int main(){
char *input = calloc(SIZE, sizeof(char));
int printed = 0;
while(fgets(input, SIZE, stdin)){
if(printed){
puts("");
}
else{
printed = 1;
}
insertion_sort(input);
free(input);
input = calloc(SIZE, sizeof(char));
}
}
void insertion_sort(char arr[]){
//create new array without spaces and other useless char
char *new_arr = malloc(SIZE * sizeof(char));
int len = 0;
for(int i=0; i<SIZE; i++){
if(((arr[i] >= '0') && (arr[i] <= '9')) || ((arr[i] >= 'a') && (arr[i] <= 'z')) || ((arr[i] >= 'A') && (arr[i] <= 'Z'))){
new_arr[len++] = arr[i];
}
}
new_arr[len] = '\0';
size_t key_w;
size_t k, ptr;
char key;
//sorting
for(int pass=0; pass<len; pass++){
//print
printf("Pass %d:", pass);
for(int i=0; i<len; i++){
printf(" %c", new_arr[i]);
if(i == pass){
printf(" /");
}
}
puts("");
if(pass == len-1){
break;
}
//swap
k = pass+1;
key = new_arr[k];
key_w = weight(key);
ptr = k;
while((ptr >= 1) && (weight(new_arr[ptr-1]) > key_w)){
new_arr[ptr] = new_arr[ptr-1];
ptr--;
}
new_arr[ptr] = key;
}
free(new_arr);
}
size_t weight(char c){
for(int i=0; i<14; i++){
if(c == w_arr[i]){
return i;
}
}
}
```
###### tags: `程設一quiz`