PapaMelon #6 设计双向链表

157 阅读2分钟

题目链接

题解

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
#include <cassert>

using namespace std;

const vector<string> OP = {
    "PUSH_FRONT", "POP_FRONT", "INSERT",  "CONTAINS",
    "REMOVE",     "REVERSE",   "FOR_EACH",
    "PUSH_BACK",  "POP_BACK",   "VISIT"};

struct Node {
    int val;
    Node* next;
    Node* prev;
    Node(): val(-1), next(nullptr), prev(nullptr) {}
    Node(int x): val(x), next(nullptr), prev(nullptr) {}
};

struct List {
    Node* head;
    Node* tail;

    List() {
        head = new Node();
        tail = new Node();
        head->next = tail;
        tail->prev = head;
    }

    ~List() {
        clear();
        delete head;
        delete tail;
    }

    void clear() {
        while (head->next != tail) {
            Node* a = head->next;
            Node* b = a->next;

            a->next = a->prev = nullptr;
            delete a;

            head->next = b;
            b->prev = head;
        }
    }

    void push_front(int x) {
        Node* ptr = head->next;
        Node* node = new Node(x);
        head->next = node;
        node->prev = head;
        node->next = ptr;
        ptr->prev = node;
    }

    void pop_front() {
        if (head->next == tail) return;

        Node* a = head->next;
        Node* b = a->next;

        a->prev = a->next = nullptr;
        head->next = b;
        b->prev = head;
        delete a;
    }

    void insert(int index, int x) {
        Node* ptr = head->next;
        Node* pre = head;
        for (int i = 0; i < index; i++) {
            pre = ptr;
            ptr = ptr->next;
        }
        Node* node = new Node(x);
        pre->next = node;
        node->prev = pre;
        node->next = ptr;
        ptr->prev = node;
    }

    bool contains(int x) {
        Node* ptr = head->next;
        while (ptr != tail && ptr->val != x) ptr = ptr->next;
        return ptr != tail;
    }

    void remove(int x) {
        Node* pre = head;
        Node* ptr = head->next;

        while (ptr != tail) {
            if (ptr->val == x) {
                Node* a = ptr->next;
                pre->next = a;
                a->prev = pre;
                ptr->prev = ptr->next = nullptr;
                delete ptr;
                ptr = a;
            } else {
                pre = ptr;
                ptr = ptr->next;
            }
        }
    }

    void reverse() {
        Node* pre = head;
        Node* ptr = head->next;
        head->next = nullptr;
        head->prev = ptr;

        while (ptr) {
            Node* node = ptr->next;
            ptr->next = pre;
            ptr->prev = node;
            pre = ptr;
            ptr = node;
        }
        swap(head, tail);
    }

    void foreach() {
        Node* ptr = head->next;
        for (int i = 0; ptr != tail; i++, ptr = ptr->next) {
            if (i) cout << " ";
            cout << ptr->val;
        }
        cout << endl;
    }

    void push_back(int x) {
        Node* ptr = tail->prev;
        Node* node = new Node(x);
        node->prev = ptr;
        ptr->next = node;
        node->next = tail;
        tail->prev = node;
    }

    void pop_back() {
        if (tail->prev == head) return;
        Node* a = tail->prev;
        Node* b = a->prev;
        b->next = tail;
        tail->prev = b;
        a->prev = a->next = nullptr;
        delete a;
    }

    void visit(int x, int k) {
        Node* ptr = head->next;
        while (ptr != tail && ptr->val != x) ptr = ptr->next;
    
        if (ptr == tail) {
            cout << endl;
            return;
        }
       
        Node* a = ptr;
        for (int i = 0; i < k && a != head->next; i++) a = a->prev;
        Node* b = ptr;
        for (int i = 0; i <= k && b != tail; i++) b = b->next;

        for (int i = 0; a != b; i++, a = a->next) {
            if (i) cout << " ";
            cout << a->val;
        }
        cout << endl;
    }

};

List data;

void lpushfront() {
    int x;
    cin >> x;
    data.push_front(x);
}

void lpopfront() {
    data.pop_front();
}

void linsert() {
    int index, x;
    cin >> index >> x;
    data.insert(index, x);
}

void lcontains() {
    int x;
    cin >> x;
    bool ret = data.contains(x);
    if (ret) cout << "true" << endl;
    else cout << "false" << endl;
}

void lremove() {
    int x;
    cin >> x;
    data.remove(x);
}

void lreverse() {
    data.reverse();
}

void lforeach() {
    data.foreach();
}

void lpushback() {
    int x;
    cin >> x;
    data.push_back(x);
}

void lpopback() {
    data.pop_back();

}

void lvisit() {
    int x, k;
    cin >> x >> k;
    data.visit(x, k);
}

void solve() {
    int M;
    cin >> M;
    
    data.clear();
    while (M--) {
        string op;
        cin >> op;
        int id = find(OP.begin(), OP.end(), op) - OP.begin();

        switch (id) {
            case 0:
                lpushfront();
                break;
            case 1:
                lpopfront();
                break;
            case 2:
                linsert();
                break;
            case 3:
                lcontains();
                break;
            case 4:
                lremove();
                break;
            case 5:
                lreverse();
                break;
            case 6:
                lforeach();
                break;
            case 7:
                lpushback();
                break;
            case 8:
                lpopback();
                break;
            case 9:
                lvisit();
                break;
            default:
                assert(0);
        }
    }
}

int main() {
    solve();
    return 0;
}