【数据结构】栈(C++ )

简介: 【数据结构】栈(C++ )

@TOC

只能在一边进出,先进的后出。

进出的一端叫做栈顶,另一端叫做栈底。

栈可以使用顺序存储结构,也能使用链式存储结构。


注意:栈只能在一端进行操作,这是栈的关键特征,也就是说栈不允许在中间进行查找、插入、删除等操作,(但是在实际应用中我们可以打破它)。

这里掌握初始化、入栈、出栈、取栈顶元素操作即可。

顺序存储结构实现栈

#include<iostream>
using namespace std;

#define MAX_SIZE 128
typedef int DataType;

//栈的结构有多重方式定义,不用局限于这一种
/*
    例如:
        定义两个int型,并且直接开辟好数组空间
        定义一个指针,一个int top
*/
typedef struct _Stack
{
    DataType* top;    //栈顶指针
    DataType* base;//栈底指针
    //其实没有必要定义一个来标记元素的个数。
    //两个指针指向同一个数组,他们两个相减得到是中间元素的个数。
    //否则两个地址相减没有意义
}Stack;

//栈的初始化
bool initStack(Stack& S)
{
    //先用栈底指针来拿到这个刚开辟好空间的数组
    S.base = new int[MAX_SIZE];//指针来定位这个数组
    if (!S.base)
    {
        return false;
    }
    S.top = S.base;
    return true;
}

//入栈
bool pushStack(Stack& S, DataType data)
{
    if (!S.base)
    {
        return false;
    }
    if (S.top - S.base == MAX_SIZE)
    {
        //栈满
        return false;
    }

    //栈中还有空位置
    *(S.top) = data;
    S.top++;
    return true;
}

//出栈-栈顶元素出栈
DataType popStack(Stack& S)
{
    //不为空
    if (S.top != S.base)
    {
        return *(--S .top);
    }
    else
    {
        return -1;
    }
}
//返回栈顶元素         
DataType getTop(Stack& S)
{
    if (S.top - S.base == 0)
    {
        return -1;
    }
    return *(S.top-1);
}
int main(void)
{
    Stack S;
    initStack(S);    
    int n = 0;
    int m = 0;
    cin >> n;
    m = n;
    while (n)
    {    
        pushStack(S, n);
        n--;
    }
    cout << "____" << endl;
    cout << getTop(S) << endl;
    cout << "____" << endl;
    while (m)
    {
        cout << popStack(S) << endl;
        m--;
    }
    return    0;
}

入栈操作图示:

在这里插入图片描述

链接存储结构实现栈

#include<iostream>
using namespace std;

//数据类型
typedef int DataType;
//最大存储数量
#define  MAX_SZIE 128
//结点结构
typedef struct _Snode
{
    DataType data;
    struct _Snode* next;
}Snode;

//栈(头)结构
typedef struct _Stack
{
    int count;
    Snode* base;
    Snode* top;
}Stack;

//初始化
bool initStack(Stack* S)
{
    if (!S)
    {
        return false;
    }
    S->base = S->top = NULL;
    S->count = 0;
    return true;
}

//入栈
bool pushStack(Stack* S, Snode* node)
{
    if (!S || !node)
    {
        return false;
    }

    //第一次插入元素
    if (S->count == 0)
    {
        S->base = S->top = node;
        S->top->next = NULL;
        S->count++;
    }
    else
    {
        S->top->next = node;
        S->top = node;
        S->count++;
    }
    return false;
}
//出栈
bool popStack(Stack* S)
{
    if (!S || S->count == 0)
    {
        return false;
    }
    Snode* tempnode = S->base;

    while (tempnode->next != S->top && S->count != 1)
    {
        tempnode = tempnode->next;
    }
    if (S->count == 1)//如果栈中只剩下一个结点可以删除
    {
        S->base = NULL;
    }
    //现在tempnode是top的前一个结点
    delete S->top;
    S->top = tempnode;//如果是最后一个结点的话base和top都被置空了
    S->top->next = NULL;
    
    S->count--;
    return true;
}
//拿到栈顶元素
bool getTop(Stack* S,DataType* m_data)
{
    if (!S || S->count == 0)
    {
        return S;
    }
    *m_data = S->top->data;
    return false;
}
//判断栈是否为空
bool isEmpty(Stack* S)
{
    if (S->count == 0)
    {
        return true;
    }
    return false;
}
int main(void)
{
    Stack* S = new Stack;
    initStack(S);

    int n = 5;
    int m = n;
    while (n)
    {
        Snode* tempnode = new Snode;
        tempnode->data = n;
        pushStack(S, tempnode);
        n--;
    }

    while (m >0)
    { 
        m--;
    }

    cout << S->top->data << " ";
    popStack(S);

    cout << S->top->data << " ";
    popStack(S);

    cout << S->top->data << " ";
    popStack(S);
    
    cout << S->top->data << " ";
    popStack(S);

    cout << S->top->data << " ";
    popStack(S);

    if (!isEmpty(S))
    {
        cout << S->top->data << " ";
    }


    int temp = 0;
    getTop(S, &temp);
    cout << temp << endl;

    delete S;
    return    0; 
}

补充:要修改指针指向地址,可以传递二级指针。

一级指针修改值。

实际应用

迷宫求解

链接——【栈】实现迷宫求解(C++)(详解)

表达式求值

链接——【数据结构】栈(C++)

相关文章
|
6月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
192 0
|
7月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
162 0
栈区的非法访问导致的死循环(x64)
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
581 77
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
11月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
280 11
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
481 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
11月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
存储 人工智能 算法
【C++数据结构——图】最短路径(头歌教学实验平台习题) 【合集】
任务描述 本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。 相关知识 为了完成本关任务,你需要掌握:Dijkst本关任务:编写一个程序,利用Dijkstra算法,实现带权有向图的最短路径。为了完成本关任务,你需要掌握:Dijkstra算法。带权有向图:该图对应的二维数组如下所示:Dijkstra算法:Dijkstra算法是指给定一个带权有向图G与源点v,求从v到G中其他顶点的最短路径。Dijkstra算法的具体步骤如下:(1)初始时,S只包含源点,即S={v},v的距离为0。
188 15
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
395 12
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
212 10