#include <stdio.h>
#include <stdlib.h>

typedef struct node {
    int val;
    struct node *next;
} Node;

Node *head = NULL;

Node* createN(int x) {
    Node *newnode;
    newnode = (Node *)malloc(sizeof(Node));
    newnode->val = x;
    newnode->next = NULL;
    return newnode;
}

void initL(int n) {
    int x, i;
    Node *p;
    scanf("%d", &x);
    head = createN(x);
    p = head;
    for (i = 1; i < n; i++) {
        scanf("%d", &x);
        p->next = createN(x);
        p = p->next;
    }
}

void freeL() {
    Node *p;
    while (head != NULL) {
        p = head->next;
        free(head);
        head = p;
    }
}

void printN(Node *a) {
    if (a == NULL) printf("NULL\n");
    else printf("%d\n", a->val);
}

void printL() {
    Node *p = head;
    while (p != NULL) {
        printf("%d ", p->val);
        p = p->next;
    }
    printf("\n");
}

Node* getN(int n) {
    int i;
    Node *p;
    p = head;
    for (i = 1; i < n; i++) p = p->next;
    return p;
}

int countL() {
    int ret = 0;
    Node *p = head;
    while (p != NULL) {
        p = p->next;
        ret++;
    }
    return ret;
}

Node* searchX(int x) {
    Node *p;
    for (p = head; p != NULL; p = p->next) {
        if (p->val == x) break;
    }
    return p;
}

void insHead(int x) {
    Node *p;
    p = createN(x);
    p->next = head;
    head = p;
}

void insMiddle(int n, int x) {
    int i;
    Node *p, *q;
    p = head;
    for (i = 1; i < n; i++) {
        p = p->next;
    }
    q = createN(x);
    q->next = p->next;
    p->next = q;
}

void insTail(int x) {
    Node *p;
    if (head == NULL) {
        head = createN(x);
        return;
    }
    p = head;
    while (p->next != NULL) {
        p = p->next;
    }
    p->next = createN(x);
}

void delHead() {
    if (head == NULL) return;
    Node *p;
    p = head;
    head = head->next;
    free(p);
}

void delMiddle(int n) {
    int i;
    Node *p, *q;
    p = head;
    for (i = 1; i < n - 1; i++) {
        p = p->next;
    }
    q = p->next;
    p->next = q->next;
    free(q);
}

void delTail() {
    if (head == NULL) return;
    if (head->next == NULL) {
        free(head);
        head = NULL;
        return;
    }
    Node *p;
    p = head;
    while (p->next->next != NULL) {
        p = p->next;
    }
    free(p->next);
    p->next = NULL;
}

// --- 以下、追加・修正した関数 ---

void push(int x) {
    // スタックのプッシュは先頭への挿入
    insHead(x);
}

int pop() {
    // スタックのポップは先頭から値を取り出し、ノードを削除
    if (head == NULL) return -1; // エラー処理（空の場合）
    
    int val = head->val; // 1. 値を保持
    delHead();           // 2. 先頭を削除
    return val;          // 3. 値を返す
}

void enqueue(int x) {
    // キューのエンキューは末尾への挿入
    insTail(x);
}

int dequeue() {
    // キューのデキューは先頭から値を取り出し、ノードを削除
    if (head == NULL) return -1; // エラー処理（空の場合）
    
    int val = head->val; // 1. 値を保持
    delHead();           // 2. 先頭を削除
    return val;          // 3. 値を返す
}

int main(void) {
    int s1, s2, s3, q1, q2, q3;

    // スタックの動作確認 (LIFO: 3, 2, 1 の順に出るはず)
    push(1);
    push(2);
    push(3);
    s1 = pop();
    s2 = pop();
    s3 = pop();
    printf("%d %d %d\n", s1, s2, s3);

    // キューの動作確認 (FIFO: 1, 2, 3 の順に出るはず)
    enqueue(1);
    enqueue(2);
    enqueue(3);
    q1 = dequeue();
    q2 = dequeue();
    q3 = dequeue();
    printf("%d %d %d\n", q1, q2, q3);

    freeL();
    return 0;
}