使用c++超详细解释数据结构中的顺序栈和链栈

2023-11-19

在C++中,栈(Stack)是一种数据结构,它可以用来存储数据,并支持两种基本操作:压入(Push)和弹出(Pop)。栈的特点是后进先出(Last In First Out,LIFO),也就是最后压入的元素最先弹出。栈可以用数组或链表等数据结构来实现。

在C++中,STL(Standard Template Library)提供了一个名为stack的容器,用于实现栈。stack容器是一个适配器(Adapter),它使用了一种已有的容器作为其底层实现,例如vector,deque等。stack容器提供了以下一些常用的成员函数:

  • push():将一个元素压入栈顶。
  • pop():从栈顶弹出一个元素。
  • top():返回栈顶元素的引用,但不删除该元素。
  • empty():判断栈是否为空。
  • size():返回栈中元素的个数。

下面是一个使用stack容器实现栈的示例代码:

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

int main() {
    stack<int> s; // 定义一个int类型的栈

    // 压入元素
    s.push(1);
    s.push(2);
    s.push(3);

    // 弹出并输出元素
    while (!s.empty()) {
        cout << s.top() << " ";
        s.pop();
    }
    cout << endl;

    return 0;
}

运行上述代码,将输出:3 2 1,说明栈的特点是后进先出。

顺序栈

除了stack容器以外,C++中还可以使用数组或链表等数据结构来实现栈。例如,下面是一个使用数组实现栈的示例代码:

#include <iostream>
using namespace std;

const int MAX_SIZE = 100; // 定义最大栈空间

class Stack {
private:
    int data[MAX_SIZE]; // 栈的数据存储数组
    int top; // 栈顶指针

public:
    Stack() { // 构造函数,初始化栈顶指针为-1
        top = -1;
    }

    void push(int value) { // 压入元素
        if (top == MAX_SIZE - 1) { // 判断栈是否已满
            cout << "Stack overflow!" << endl;
            return;
        }
        top++; // 栈顶指针加1
        data[top] = value; // 压入元素
    }

    void pop() { // 弹出栈顶元素
        if (top == -1) { // 判断栈是否已空
            cout << "Stack underflow!" << endl;
            return;
        }
        top--; // 栈顶指针减1
    }

    int getTop() { // 获取栈顶元素
        if (top == -1) { // 判断栈是否已空
            cout << "Stack underflow!" << endl;
            return -1;
        }
        return data[top]; // 返回栈顶元素
    }

    bool isEmpty() { // 判断栈是否为空
        return (top == -1);
    }

    int size() { // 返回栈中元素的个数
        return (top + 1);
    }
};

int main() {
    Stack s; // 定义一个栈

    // 压入元素
    s.push(1);
    s.push(2);
    s.push(3);

    // 弹出并输出元素
    while (!s.isEmpty()) {
        cout << s.getTop() << " ";
        s.pop();
    }
    cout << endl;

    return 0;
}

运行上述代码,将输出:3 2 1。

链栈

在这里插入图片描述

下面是一个使用链表实现栈的示例代码:

#include <iostream>
using namespace std;

class Node { // 定义链表节点
public:
    int data; // 节点存储的数据
    Node* next; // 指向下一个节点的指针

    Node(int value) { // 构造函数
        data = value;//存放栈顶元素,链栈的头指针就是栈顶
        next = NULL;//空栈相当于头指针指向空
    }
};

class Stack {
private:
    Node* top; // 栈顶指针

public:
    Stack() { // 构造函数,初始化栈顶指针为NULL
        top = NULL;//构造一个空栈,栈顶指针指向空
    }

    void push(int value) { // 压入元素
        Node* newNode = new Node(value); // 创建新节点
        newNode->next = top; // 新节点指向当前栈顶节点
        top = newNode; // 更新栈顶指针
    }

    void pop() { // 弹出栈顶元素
        if (top == NULL) { // 判断栈是否已空
            cout << "Stack underflow!" << endl;
            return;
        }
        Node* delNode = top; // 记录要删除的节点
        top = top->next; // 更新栈顶指针
        delete delNode; // 释放删除节点的空间
    }

    int getTop() { // 获取栈顶元素
        if (top == NULL) { // 判断栈是否已空
            cout << "Stack underflow!" << endl;
            return -1;
        }
        return top->data; // 返回栈顶元素
    }

    bool isEmpty() { // 判断栈是否为空
        return (top == NULL);
    }

    int size() { // 返回栈中元素的个数
        int count = 0;
        Node* p = top;
        while (p != NULL) {
            count++;
            p = p->next;
        }
        return count;
    }
};

int main() {
    Stack s; // 定义一个栈

    // 压入元素
    s.push(1);
    s.push(2);
    s.push(3);

    // 弹出并输出元素
    while (!s.isEmpty()) {
        cout << s.getTop() << " ";
        s.pop();
    }
    cout << endl;

    return 0;
}

运行上述代码,将输出:3 2 1。在使用链表实现栈时,需要注意链表节点的定义和操作,以及链表头指针(即栈顶指针)的更新。

总之,栈是一种常用的数据结构,在C++中可以使用stack容器、数组、链表等数据结构来实现。在编写栈的实现代码时,需要注意栈的特点是后进先出,即最后压入的元素最先弹出,同时需要注意栈的空间限制和边界条件。

链栈入栈操作

在这里插入图片描述

链栈(Linked Stack)是一种使用链表实现的栈(Stack)数据结构,在C++中可以使用类(Class)来定义链栈。链栈的入栈(Push)操作就是将一个元素压入栈顶,下面是一个使用类实现链栈入栈操作的示例代码:

#include <iostream>
using namespace std;

class Node { // 定义链表节点
public:
    int data; // 节点存储的数据
    Node* next; // 指向下一个节点的指针

    Node(int value) { // 构造函数
        data = value;
        next = NULL;
    }
};

class LinkedStack { // 定义链栈类
private:
    Node* top; // 栈顶指针

public:
    LinkedStack() { // 构造函数,初始化栈顶指针为NULL
        top = NULL;
    }

    void push(int value) { // 入栈操作
        Node* newNode = new Node(value); // 创建新节点
        newNode->next = top; // 新节点指向当前栈顶节点
        top = newNode; // 更新栈顶指针
        cout << "Push " << value << " into the stack." << endl;
    }
};

int main() {
    LinkedStack s; // 定义一个链栈

    // 入栈操作
    s.push(1);
    s.push(2);
    s.push(3);

    return 0;
}

在上述代码中,我们定义了一个Node类作为链表节点,其中data表示节点存储的数据,next表示指向下一个节点的指针。然后定义了一个LinkedStack类作为链栈,其中top表示栈顶指针。在push方法中,我们首先创建一个新节点,并将其指向当前栈顶节点,然后将栈顶指针更新为新节点,最后输出入栈操作的信息。

运行上述代码,将输出:

Push 1 into the stack.
Push 2 into the stack.
Push 3 into the stack.

这说明我们已经成功地进行了链栈的入栈操作。在实际使用中,我们可以根据需要修改push方法的实现,比如添加入栈元素的判断和处理等。

链栈的出栈操作

在这里插入图片描述

链栈(Linked Stack)是一种使用链表实现的栈(Stack)数据结构,在C++中可以使用类(Class)来定义链栈。链栈的出栈(Pop)操作就是将栈顶元素弹出,下面是一个使用类实现链栈出栈操作的示例代码:

#include <iostream>
using namespace std;

class Node { // 定义链表节点
public:
    int data; // 节点存储的数据
    Node* next; // 指向下一个节点的指针

    Node(int value) { // 构造函数
        data = value;
        next = NULL;
    }
};

class LinkedStack { // 定义链栈类
private:
    Node* top; // 栈顶指针

public:
    LinkedStack() { // 构造函数,初始化栈顶指针为NULL
        top = NULL;
    }

    void push(int value) { // 入栈操作
        Node* newNode = new Node(value); // 创建新节点
        newNode->next = top; // 新节点指向当前栈顶节点
        top = newNode; // 更新栈顶指针
        cout << "Push " << value << " into the stack." << endl;
    }

    void pop() { // 出栈操作
        if (top == NULL) { // 判断栈是否已空
            cout << "Stack underflow!" << endl;
            return;
        }
        Node* delNode = top; // 记录要删除的节点
        top = top->next; // 更新栈顶指针
        cout << "Pop " << delNode->data << " from the stack." << endl;
        delete delNode; // 释放删除节点的空间
    }
};

int main() {
    LinkedStack s; // 定义一个链栈

    // 入栈操作
    s.push(1);
    s.push(2);
    s.push(3);

    // 出栈操作
    s.pop();
    s.pop();
    s.pop();
    s.pop();

    return 0;
}

在上述代码中,我们在LinkedStack类中添加了pop方法,用于出栈操作。首先判断栈是否为空,如果是则输出“Stack underflow!”并返回;否则,我们记录要删除的节点,将栈顶指针更新为其下一个节点,输出出栈操作的信息,并释放删除节点的空间。

运行上述代码,将输出:

Push 1 into the stack.
Push 2 into the stack.
Push 3 into the stack.
Pop 3 from the stack.
Pop 2 from the stack.
Pop 1 from the stack.
Stack underflow!

这说明我们已经成功地进行了链栈的出栈操作。在实际使用中,我们可以根据需要修改pop方法的实现,比如添加出栈元素的返回值和异常处理等。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用c++超详细解释数据结构中的顺序栈和链栈 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐