20230610

上週作業檢討

盧冠綸 @ Sprout 2023

管理貨櫃

操作:

1. 插入貨櫃,把編號由小到大排。

2. 移除 指定重量的貨櫃。

插入(架構)

Container* insert(Container* head, int index, int weight){
    Container *newone = new Container;
    // TODO: 初始化 newone
    
    if (head == nullptr){
        return newone;
    }else if (新貨櫃的編號,小於head的編號){
        // TODO: 把新貨櫃插在最前面
    }else if (新貨櫃的編號,小於tail的編號){
        // TODO: 把新貨櫃插在中間正確的地方
    }else{ // 新貨櫃的編號,大於tail的編號
        // TODO: 把新貨櫃插在最後面
    }

更詳細的做法在下一頁。

修改有寫 TODO 的部分即可。

插入(詳細架構)

Container* insert(Container* head, int index, int weight){
    Container *newone = new Container;
    // TODO: 初始化 newone
    
    if (head == nullptr) return newone;
    
    // 新貨櫃的編號,小於head的編號
    if (head -> index < newone -> index){ 
        // TODO: 把 newone 插在 head 前面
        return newone;
    }
    
    // 新貨櫃的編號,小於tail的編號
    Container *temp = head;
    while (temp 不是 tail){ // TODO: 怎麼判斷 temp 是不是 tail ?
        if (temp -> next -> index > newone -> index){
            // TODO: 把 newone 插在 temp 和 temp->next 之間
            return head;
        }
        temp = temp -> next;
    }
    // 如果迴圈跑完了但還沒 return,代表 temp 已經是 tail,且 newone 的 id 比他大。
    
    // 新貨櫃的編號,大於tail的編號
    // TODO: 把 newone 插在 temp 後面
    return head;
}

移除(架構)

Container* remove(Container* head, int max_weight){
    if (head == nullptr){
        // 什麼都不做
    }else if (要移除的貨櫃是 head){
        // 把該貨櫃移除
        // head 改成 head 的下一個
    }else if (要移除的貨櫃不是 head){
        // 把該貨櫃移除
    }else{ // 找不到要移除的貨櫃
        // 什麼都不做
    }
}

移除(詳細架構)

Container* remove(Container* head, int max_weight){
    if (head == nullptr) return nullptr;
    
    // 要移除的貨櫃是 head
    if (head -> weight == max_weight) return head -> next;
    
    // 要移除的貨櫃不是 head
    Container *prev = head, *now = prev -> next;
    while (now != nullptr){
        if (now -> weight == max_weight){
            // TODO: 把 now 從 linked list 中移除
            return head;
        }
        prev = prev -> next;
        now = now -> next;
    }
    
    // 找不到要移除的貨櫃
    return head;

參考解答

Container* insert(Container* head, int index, int weight){
    Container *newone = new Container;
    newone -> index = index;
    newone -> weight = weight;
    newone -> next = head;
    if (head == nullptr) return newone;
    if (head -> index > newone -> index) return newone;
    Container *temp = head;
    while (temp -> next != nullptr){
        if (temp -> next -> index > newone -> index){
            newone -> next = temp -> next;
            temp -> next = newone;
            return head;
        }
        temp = temp -> next;
    }
    newone -> next = nullptr;
    temp -> next = newone;
    return head;
}

Container* remove(Container* head, int max_weight){
    if (head == nullptr) return nullptr;
    if (head -> weight == max_weight) return head -> next;
    Container *temp = head, *next = head -> next;
    while (next != nullptr){
        if (next -> weight == max_weight){
            temp -> next = next -> next;
            return head;
        }
        next = next -> next;
        temp = temp -> next;
    }
    return head;
}

奇怪的火車問題

輸入資料:初始化你的每個 linked list。

 

操作:

1 x:把第 x 台火車反轉。

2 a b:把第 a 台火車,第一節車廂以外者,

             接到第 b 台火車後面。

3 x:輸出第 x 台火車。

架構

因為有「反轉」,如果用 doubly linked list,

應該會比較方便。

(當然你要用一般的 linked list 寫也不是不行)

struct box{
    int id;
    box *prev;
    box *next;
};

架構

int main(){
    ios_base::sync_with_stdio(false);cin.tie(0);
    int num, step;
    box *head[10001]; // 存所有火車的頭
    box *tail[10001]; // 存所有火車的尾
    cin >> num >> step;
    for (int i=1 ; i<=num ; i++){
        // TODO: 1. 輸入第 i 台火車的資料
        //       2. 產生第 i 個 linked list
        //       3. 維護 head[i] 和 tail[i]
    }
    for (int i=0 ; i<step ; i++){
        int command, index1, index2;
        cin >> command;
        if (command == 1){
            cin >> index1;
            // TODO: 反轉第 index1 台火車
        }
        if (command == 2){
            cin >> index1 >> index2;
            // TODO: 把 index1 火車後面,接到 index2 後面
        }
        if (command){
            cin >> index1;
            // TODO: 印出第 index1 台火車
        }
    }   
}
    

處理輸入

for (int i=0 ; i<num ; i++){
    head[i] = nullptr;
    tail[i] = nullptr;
    int count; // 第 i 台火車的長度
    cin >> count;
    for (int j=0 ; j<count ; j++){
        int id;
        cin >> id;
        box *temp = new box;
        temp -> id = id;
        if (j == 0){
            // TODO: 更新 head[i]
            // TODO: 更新 tail[i]
            // TODO: 調整 temp 的 prev 和 next
        }
        else{
            // TODO: 調整 tail[i] 的 next
            // TODO: 調整 temp 的 prev 和 next
            // TODO: 更新 tail[i]
        }
    }
}
// TODO: 1. 輸入第 i 台火車的資料
//       2. 產生第 i 個 linked list
//       3. 維護 head[i] 和 tail[i]

前一頁的 TODO:

操作一

box *temp = head[index];
while (temp != nullptr){
    box *temp2 = temp -> next;
    // TODO: 把 temp -> prev 跟 temp -> next 兩個指針對調
    temp = temp2;
}

反轉第 index 台火車:

操作二

// 如果第 index1 台火車長度在 1 以下,就什麼都不做
if (head[index1] == nullptr) continue;
if (head[index1] == tail[index1]) continue;

// 如果第 index2 台火車長度為 0 
if (head[index2] == nullptr){
    box *cat = head[index1] -> next; // 要接在 index2 後的車廂
    head[index1] -> next = // TODO
    if (cat != nullptr) cat -> prev = // TODO
    // TODO: 更新 head[index2], tail[index2], tail[index1]
}

// 如果第 index2 台火車長度非 0 
else{
    box *cat = head[index1] -> next; // 要接在 index2 後的車廂
    head[index1] -> next = // TODO
    if (cat != nullptr) cat -> prev = // TODO
    tail[index2] -> next = // TODO
    // TODO: 更新 tail[index1]、tail[index2]
}

反轉第 index 台火車:

操作三

box *temp = head[index];
while (temp != nullptr){
    cout << temp -> id << " ";
    temp = temp -> next;
}
cout << endl;

印出第 index 台火車:

總架構

#include <iostream>
#include <string>
using namespace std;

struct box{
    int id;
    box *prev;
    box *next;
};

int main(){
    ios_base::sync_with_stdio(false);cin.tie(0);
    int num, step;
    box *head[10001]; // 存所有火車的頭
    box *tail[10001]; // 存所有火車的尾
    cin >> num >> step;
    
    // 處理輸入
    for (int i=1 ; i<=num ; i++){
        head[i] = nullptr;
        tail[i] = nullptr;
        int count; // 第 i 台火車的長度
        cin >> count;
        for (int j=0 ; j<count ; j++){
            int id;
            cin >> id;
            box *temp = new box;
            temp -> id = id;
            if (j == 0){
                head[i] = // TODO
                tail[i] = // TODO
                temp -> prev = // TODO
                temp -> next = // TODO
            }
            else{
                tail[i] -> next = // TODO
                temp -> prev = // TODO
                temp -> next = // TODO
                tail[i] = // TODO
            }
        }
    }
    
    // 處理操作
    for (int i=0 ; i<step ; i++){
        int command, index1, index2;
        cin >> command;
        
        // 反轉第 index1 台火車
        if (command == 1){
            cin >> index1;
            box *temp = head[index1];
            while (temp != nullptr){
                box *temp2 = temp -> next;
                // TODO: 把 temp -> prev 跟 temp -> next 兩個指針對調
                temp = temp2;
            }
            // TODO: 交換 head[index1] 和 tail[index1]
        }
        
        // 把 index1 火車後面,接到 index2 後面
        if (command == 2){
            cin >> index1 >> index2;
            // 如果第 index1 台火車長度在 1 以下,就什麼都不做
            if (head[index1] == nullptr) continue;
            if (head[index1] == tail[index1]) continue;

            // 如果第 index2 台火車長度為 0 
            if (head[index2] == nullptr){
                box *cat = head[index1] -> next; // 要接在 index2 後的車廂
                head[index1] -> next = // TODO
                if (cat != nullptr) cat -> prev = // TODO
                head[index2] = // TODO
                tail[index2] = // TODO
                tail[index1] = // TODO
            }

            // 如果第 index2 台火車長度非 0 
            else{
                box *cat = head[index1] -> next; // 要接在 index2 後的車廂
                head[index1] -> next = // TODO
                if (cat != nullptr) cat -> prev = // TODO
                tail[index2] -> next = // TODO
                tail[index2] = // TODO
                tail[index1] = // TODO
            }
        }
        
        // 印出第 index1 台火車
        if (command == 3){
            cin >> index1;
            box *temp = head[index1];
            while (temp != nullptr){
                cout << temp -> id << " ";
                temp = temp -> next;
            }
            cout << endl;
        }
    }   
}
    

參考解答

#include <iostream>
#include <string>
using namespace std;

struct box{
    int id;
    box *prev;
    box *next;
};

int main(){
    ios_base::sync_with_stdio(false);cin.tie(0);
    int num, step;
    box *head[10001]; // 存所有火車的頭
    box *tail[10001]; // 存所有火車的尾
    cin >> num >> step;
    
    // 處理輸入
    for (int i=1 ; i<=num ; i++){
        head[i] = nullptr;
        tail[i] = nullptr;
        int count; // 第 i 台火車的長度
        cin >> count;
        for (int j=0 ; j<count ; j++){
            int id;
            cin >> id;
            box *temp = new box;
            temp -> id = id;
            if (j == 0){
                head[i] = temp;
                tail[i] = temp;
                temp -> prev = nullptr;
                temp -> next = nullptr;
            }
            else{
                tail[i] -> next = temp;
                temp -> prev = tail[i];
                temp -> next = nullptr;
                tail[i] = temp;
            }
        }
    }
    
    // 處理操作
    for (int i=0 ; i<step ; i++){
        int command, index1, index2;
        cin >> command;
        
        // 反轉第 index1 台火車
        if (command == 1){
            cin >> index1;
            box *temp = head[index1];
            while (temp != nullptr){
                box *temp2 = temp -> next;
                temp -> next = temp -> prev;
                temp -> prev = temp2;
                temp = temp2;
            }
            swap(head[index1], tail[index1]);
        }
        
        // 把 index1 火車後面,接到 index2 後面
        if (command == 2){
            cin >> index1 >> index2;
            // 如果第 index1 台火車長度在 1 以下,就什麼都不做
            if (head[index1] == nullptr) continue;
            if (head[index1] == tail[index1]) continue;

            // 如果第 index2 台火車長度為 0
            if (head[index2] == nullptr){
                box *cat = head[index1] -> next; // 要接在 index2 後的車廂
                head[index1] -> next = nullptr;
                if (cat != nullptr) cat -> prev = nullptr;
                head[index2] = cat;
                tail[index2] = tail[index1];
                tail[index1] = head[index1];
            }

            // 如果第 index2 台火車長度非 0
            else{
                box *cat = head[index1] -> next; // 要接在 index2 後的車廂
                head[index1] -> next = nullptr;
                if (cat != nullptr) cat -> prev = tail[index2];
                tail[index2] -> next = cat;
                tail[index2] = tail[index1];
                tail[index1] = head[index1];
            }
        }
        
        // 印出第 index1 台火車
        if (command == 3){
            cin >> index1;
            box *temp = head[index1];
            while (temp != nullptr){
                cout << temp -> id << " ";
                temp = temp -> next;
            }
            cout << endl;
        }
    }
}
    

謝謝大家

Copy of 20230610 上週作業檢討

By allen522019

Copy of 20230610 上週作業檢討

  • 149