使用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++超详细解释数据结构中的顺序栈和链栈 的相关文章

  • 返回 Web 浏览器中 HtmlElement 的所有属性

    我需要从我的网络浏览器获取所有属性 当前 我正在使用 GetAttribute 但这样 我需要知道属性的名称 想象一下我不知道我的网络浏览器中有什么 我的 C 代码 StringWriter strWriter new StringWrit
  • “do { ... } while (0)”在内核代码中到底做了什么? [复制]

    这个问题在这里已经有答案了 可能的重复 当我们定义宏时 do while 0 有什么用 https stackoverflow com questions 923822 whats the use of do while0 when we
  • C++ 中跨多个文件的类

    我几乎 100 确定我在这两个类中的语法都是正确的 但是我收到以下错误 对于 CShape cpp 错误 C2011 CShape class 类型重新定义 对于 CCircle cpp 错误 CS2504 CShape 基类未定义 这是
  • 使用 gcc 的中间 GIMPLE 格式

    根据本文 http en wikipedia org wiki Intermediate languagegcc 在生成代码之前使用多种中间格式 我读到 GIMPLE 格式使用三个地址代码 这似乎是最容易使用的中间语言 但我需要更多细节 因
  • 来自 RAZOR 中不同文件夹的 RenderPartial

    我一直在尝试将我的 aspx 页面转换为 cshtml 并且在从另一个文件夹渲染部分页面时遇到问题 我以前做过的事 我认为等价的是 Html RenderPartial Views Inquiry InquiryList cshtml Mo
  • 为什么调用 istream::tellg() 会影响我的程序的行为?

    我正在尝试将 24 位位图图像转换为灰度图像 include
  • 尝试使用指向 ODBC DSN 的连接字符串时出现关键字不支持异常

    我为我的 Asp Net MVC 应用程序的数据库访问创建了一个 ODBC DSN 主要原因之一是它可以轻松地将数据库凭据 例如服务器地址 端口 用户名和密码 置于源代码控制之外 而不会妨碍我的发布能力 所以我将连接更改为DSN MyDSN
  • Request.Url.Port 给出错误的端口

    我的支持团队为我提供了一个 Live IP 例如http 201 121 152 168 68 现在在正常情况下你会认为68是端口 但是 当我执行 Request Host 时 我得到201 121 152 168当我执行 Request
  • 用于生成 C++ 代码轮廓/图的工具 - 有这样的东西吗? [复制]

    这个问题在这里已经有答案了 我需要深入研究用 C 编写的软件组件并对其进行一些修改 我幻想生成一些代码映射 它将显示类之间的关系并引导我完成方法的流程 调用图 有这个工具吗 几年前 我使用 Rational Rose 建模工具 该工具具有对
  • 如何混淆整数?

    我需要从 C 中的整数列表生成唯一值的列表 我以为是 MD5 或类似的 但它们生成了太多字节 整数大小为 2 个字节 例如 我想获得单向通信 0 gt ARY812Q3 1 gt S6321Q66 2 gt 13TZ79K2 因此 在证明哈
  • Control.Invoke 在隐藏的 ShowDialog 中“卡住”

    我有解决这个问题的方法 但这不是我第一次被咬 所以我试图确切地了解发生了什么 从我的申请中 我ShowDialog表单 表单上有一个按钮 单击该按钮时会调用另一个 非 GUI 线程上的代码 非 GUI 线程发回状态 Pushed then
  • Fluent NHibernate 一对一映射

    我很难利用 Fluent NHibernate 的 HasOne 映射 基本上 A 类在 B 类中可以有匹配的 只有一条或没有 记录 请帮助定义关系的 AMap 和 BMap 类 谢谢 public class A public virtu
  • OpenGL 中连续暂停

    void keyPress unsigned char key int x int y int i switch key case f i 3 while i x pos 3 sleep 100 glutPostRedisplay 上面是在
  • 使用资源文件进行本地化不起作用

    我添加了新的 Rosource 文件 UserNotification resx 然后我添加了两个文件进行本地化 并将其命名为 UserNotification hr HR resx 和 UserNotification sl SI res
  • 执行按钮单击时使 wpf UI 响应

    在我的 wpf c 应用程序中 当用户按下按钮时会执行一个很长的过程 当按下按钮直到执行完整的代码时 窗口将冻结 用户无法在窗口中执行任何其他任务 如何使按钮单击代码作为后台进程 以便窗口响应用户 我尝试过以下方法 但没有成功 privat
  • Eclipse 调试模式下的 GDB 找不到 stdlib/rand.c

    我试图让 gdb 在 ubuntu 上与 eclipse cdt 一起运行 以开始调试一些简单的程序 所以我做了我认为必要的步骤来让它运行 1 创建可执行项目 2 Compile 3 Run 4 创建文件 gdbinit 并将其放在主项目文
  • System.Globalization.CultureInfo 不包含 Name 的定义

    我对 System Globalization CultureInfo 类和 System Globalization 命名空间有这个特殊问题 我从具有 CultureInfo 属性的 API 调用返回一个对象 语言 我能够成功地将其在客户
  • 虚拟继承 - 跳过构造函数

    我有以下课程 class Socket Socket Socket SOCKET s class Connection public virtual Socket Connection IP ip 这两个类包含一些纯虚函数和一些非虚函数以及
  • K&R 之后用什么书来学习纯 C 编程? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何从 dll 导出 C++ 类? [复制]

    这个问题在这里已经有答案了 我有一个有两个重载函数的类 如何从 dll 导出它以及如何由其他 C 类使用它 我的班级是这样的 define DECLDIREXP declspec dllexport define DECLDIRIMP de

随机推荐