数据结构:栈操作

 

栈(Stack)是一种线性数据结构,遵循“后进先出”(Last In First Out, LIFO)的原则。这意味着最后一个被添加到栈中的元素将是第一个被移除的元素。

栈的主要特点

  1. 后进先出(LIFO)

    • 最后一个进入栈的元素最先被移除。
    • 这种特性使得栈非常适合需要回溯的操作。
  2. 单端操作

    • 所有的插入和删除操作都发生在栈顶(顶部)。
    • 不能直接访问或修改栈底(底部)的元素,除非先移除所有上面的元素。
  3. 基本操作

    • Push:将一个元素压入栈顶。
    • Pop:移除并返回栈顶元素。
    • Peek/Top:返回栈顶元素但不移除它。
    • IsEmpty:检查栈是否为空。
    • Size:返回栈中元素的数量。

栈的应用场景

  1. 函数调用管理

    • 每当一个函数被调用时,其局部变量和返回地址会被压入栈中。
    • 当函数执行完毕时,这些信息会被弹出栈。
  2. 表达式求值

    • 中缀表达式可以转换为后缀表达式(逆波兰表示法),然后使用栈进行求值。
    • 例如,计算A + B * C时,可以使用栈来处理运算符的优先级。
  3. 括号匹配

    • 使用栈可以检查括号是否正确匹配。
    • 遇到左括号时压入栈,遇到右括号时弹出栈顶元素并与之匹配。
  4. 撤销操作

    • 在文本编辑器中,撤销操作可以通过栈实现。
    • 每次用户执行一个操作时,将其记录在栈中,撤销时从栈中弹出并恢复之前的版本。
  5. 深度优先搜索(DFS)

    • 在图论中,深度优先搜索可以使用栈来实现。
    • 每次访问一个节点时,将其压入栈中,并继续访问其子节点。

栈的实现

栈可以用多种方式实现,最常见的是使用数组或链表。

使用数组实现栈

#include <iostream>
using namespace std;

class Stack {
private:
    int* arr;
    int top;
    int capacity;

public:
    Stack(int size) {
        arr = new int[size];
        capacity = size;
        top = -1;
    }

    ~Stack() {
        delete[] arr;
    }

    void push(int x) {
        if (isFull()) {
            cout << "Stack Overflow" << endl;
            return;
        }
        arr[++top] = x;
    }

    int pop() {
        if (isEmpty()) {
            cout << "Stack Underflow" << endl;
            return -1;
        }
        return arr[top--];
    }

    int peek() {
        if (isEmpty()) {
            cout << "Stack is empty" << endl;
            return -1;
        }
        return arr[top];
    }

    bool isEmpty() {
        return top == -1;
    }

    bool isFull() {
        return top == capacity - 1;
    }

    int size() {
        return top + 1;
    }
};

int main() {
    Stack stack(5);

    stack.push(1);
    stack.push(2);
    stack.push(3);

    cout << "Top element is: " << stack.peek() << endl;

    stack.pop();
    stack.pop();

    cout << "Stack size is: " << stack.size() << endl;

    return 0;
}

使用链表实现栈

​
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node* next;
};

class Stack {
private:
    Node* top;

public:
    Stack() : top(nullptr) {}

    ~Stack() {
        while (!isEmpty()) {
            pop();
        }
    }

    void push(int x) {
        Node* newNode = new Node;
        newNode->data = x;
        newNode->next = top;
        top = newNode;
    }

    int pop() {
        if (isEmpty()) {
            cout << "Stack Underflow" << endl;
            return -1;
        }
        Node* temp = top;
        int poppedData = temp->data;
        top = top->next;
        delete temp;
        return poppedData;
    }

    int peek() {
        if (isEmpty()) {
            cout << "Stack is empty" << endl;
            return -1;
        }
        return top->data;
    }

    bool isEmpty() {
        return top == nullptr;
    }

    int size() {
        int count = 0;
        Node* current = top;
        while (current != nullptr) {
            count++;
            current = current->next;
        }
        return count;
    }
};

int main() {
    Stack stack;

    stack.push(1);
    stack.push(2);
    stack.push(3);

    cout << "Top element is: " << stack.peek() << endl;

    stack.pop();
    stack.pop();

    cout << "Stack size is: " << stack.size() << endl;

    return 0;
}

​

 

具体样例

乐乐班上有些同学想入栈或出栈,每次输入学生的学号和姓名,这个同学就入栈,在输入一个数字n, 表示用栈中n个同学出栈。栈初始为空。

输入

每行输入 入栈学生的学号、姓名和出栈学生的人数;

输入EOF结束输入。

输出

出栈学生的信息,包括学号和姓名

结束输入后,输出栈中还有多少学生。

样例输入

10 ou 0

11 yang 0

12 cheng 1

13 tian 1

样例输出

12 cheng

13 tian

There are 2 students in the stack

#include <iostream>
#include <stack>
#include <string>
#include <sstream>

using namespace std;

struct Student {
    int id;
    string name;
};

int main() {
    stack<Student> studentStack;
    string line;

    while (getline(cin, line)) {
        if (line.empty()) continue;

        istringstream iss(line);
        int id, n;
        string name;

        // 检查输入是否符合预期格式
        if (!(iss >> id >> name >> n)) {
            cerr << "Invalid input format: " << line << endl;
            continue;
        }

        studentStack.push({id, name});

        for (int i = 0; i < n && !studentStack.empty(); ++i) {
            Student s = studentStack.top();
            cout << s.id << " " << s.name << endl;
            studentStack.pop();
        }
    }

    cout << "There are " << studentStack.size() << " students in the stack" << endl;

    return 0;
}
  • stack<Student> studentStack;:声明一个stack对象studentStack,用于存储学生信息。
  • while (getline(cin, line)):循环读取每一行输入,直到输入结束(EOF)。
    • if (line.empty()) continue;:如果当前行为空,则跳过该行。
    • istringstream iss(line);:创建一个字符串流对象iss,用于解析当前行的输入。
    • int id, n; string name;:声明变量idnamen,分别用于存储学号、姓名和出栈人数。
    • if (!(iss >> id >> name >> n)):检查输入是否符合预期格式(即能否成功提取idnamen)。如果不符,则输出错误信息并跳过该行。
    • studentStack.push({id, name});:将当前学生推入栈顶。
    • for (int i = 0; i < n && !studentStack.empty(); ++i):根据n的值,从栈顶弹出相应数量的学生,并输出他们的信息。
      • Student s = studentStack.top();:获取栈顶学生的信息。
      • cout << s.id << " " << s.name << endl;:输出栈顶学生的学号和姓名。
      • studentStack.pop();:移除栈顶学生。
  • cout << "There are " << studentStack.size() << " students in the stack" << endl;:输出栈中剩余的学生数量。

 

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

// 定义学生结构体
struct Student {
    int id;       // 学号
    string name;  // 姓名
};

// 定义栈类
class Stack {
private:
    vector<Student> students;  // 使用向量存储学生信息

public:
    // 将学生推入栈顶
    void push(int id, const string& name) {
        students.push_back({id, name});
    }

    // 返回栈顶学生的信息,但不移除栈顶元素
    Student peek() {
        if (!students.empty()) {
            return students.back();
        } else {
            throw out_of_range("栈为空");
        }
    }

    // 返回并移除栈顶学生的信息
    Student pop() {
        if (!students.empty()) {
            Student student = students.back();
            students.pop_back();
            return student;
        } else {
            throw out_of_range("栈为空");
        }
    }

    // 检查栈是否为空
    bool isEmpty() {
        return students.empty();
    }

    // 获取栈中学生的数量
    int size() {
        return students.size();
    }
};

int main() {
    Stack studentStack;  // 创建一个栈对象
    int id;
    string name;
    int popCount;

    // 循环读取输入,直到输入结束(EOF)
    while (cin >> id >> name >> popCount) {
        // 将当前学生推入栈顶
        studentStack.push(id, name);

        // 根据popCount的值,从栈顶弹出相应数量的学生,并输出他们的信息
        for (int i = 0; i < popCount && !studentStack.isEmpty(); ++i) {
            Student student = studentStack.pop();
            cout << student.id << " " << student.name << endl;
        }
    }

    // 输出栈中剩余的学生数量
    cout << "There are " << studentStack.size() << " students in the stack" << endl;

    return 0;
}
  • class Stack:定义一个栈类,包含以下方法:
    • void push(int id, const string& name):将学生推入栈顶。
    • Student peek():返回栈顶学生的信息,但不移除栈顶元素。
    • Student pop():返回并移除栈顶学生的信息。
    • bool isEmpty():检查栈是否为空。
    • int size():返回栈中学生的数量。

主函数


 

cpp

深色版本

int main() {
    Stack studentStack;  // 创建一个栈对象
    int id;
    string name;
    int popCount;

    // 循环读取输入,直到输入结束(EOF)
    while (cin >> id >> name >> popCount) {
        // 将当前学生推入栈顶
        studentStack.push(id, name);

        // 根据popCount的值,从栈顶弹出相应数量的学生,并输出他们的信息
        for (int i = 0; i < popCount && !studentStack.isEmpty(); ++i) {
            Student student = studentStack.pop();
            cout << student.id << " " << student.name << endl;
        }
    }

    // 输出栈中剩余的学生数量
    cout << "There are " << studentStack.size() << " students in the stack" << endl;

    return 0;
}
  • Stack studentStack;:声明一个Stack对象studentStack
  • while (cin >> id >> name >> popCount):循环读取输入,直到输入结束(EOF)。
    • studentStack.push(id, name);:将当前学生推入栈顶。
    • for (int i = 0; i < popCount && !studentStack.isEmpty(); ++i):根据popCount的值,从栈顶弹出相应数量的学生,并输出他们的信息。
  • cout << "There are " << studentStack.size() << " students in the stack" << endl;:输出栈中剩余的学生数量。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值