美文网首页
栈基本特性和操作

栈基本特性和操作

作者: 不想当社畜 | 来源:发表于2019-03-15 17:48 被阅读0次

一、栈的特性(先进后出)

特点:栈只能在栈顶进行删除(pop),插入(push)操作。

栈的示意图

栈顶是顺序存储结构上第一个没有存放数据的地址。

空栈则表示为栈顶和栈底都指向同一个元素。

同时在编写代码的过程中,使用到了auto等c++11的特性,故需要编译器支持c++11的标准。(在编译器命令添加:-std=c++11)

二、栈的定义和基本操作

  1. 栈的定义
  2. 栈的初始化
  3. 栈的插入
  4. 栈的删除
  5. 获取栈的大小
  6. 获取栈顶元素值
  7. 清空栈

1.栈的定义(顺序存储的方式)

栈的定义,使用别名功能,方便栈适应不同的数据类型

// 定义数据类型 (方便栈选择不同的数据类型)
typedef int Elemtype;

const unsigned int StackInitSize = 100; // 初始化每个栈刚开始的容量
const unsigned int StackSizeCre  = 20; // 当栈的容量不能满足使用 需要对栈进行扩容处理


// 声明和定义
typedef struct Stack{
    Elemtype *base; // 栈底
    Elemtype *top;  // 栈顶
    uunsigned int StackSize; // 栈可以容下的最大容量
}

2.栈的初始化

需要考虑在使用new分配动态内存过程中,会出现动态内存分配不成功,则会报出bad_alloc的异常,异常处理工具。

// 初始化栈
void init_stack(Stack *sta){
    // 给该栈分配内存(最大容量内存)
    try{
        sta->base = new ElemType[StackInitSize];
        // 必须要保证分配内存成功!(当使用new 分配内存不成功,会抛出异常,所以需要捕捉这个异常!)
        // 当使用new 分配内存不成功时,会抛出 bad_alloc 的异常

    }catch(const std::bad_alloc& e)
    {
        std::cout<<"can,t init stack!";
        return ;
    }

    // 分配内存正常后
    sta->top = sta->base; // 此时空栈 栈顶和栈底对应的位置相同
    sta->StackSize = StackInitSize;
}

3. 栈的插入

在栈的插入之前,需要判断该栈是否已经满了,当满了需要另外开辟一个空间去存放栈的数据。

// 插入新的元素 在栈顶
void push( Stack &sta , ElemType e){
    
    auto size = sta.top - sta.base;

    // 先判断该栈是否已经满
    if(size == sta.StackSize){
        ElemType *newdata = new ElemType[sta.StackSize+StackSizeCre]; // 此处也需要判断是否分配正常 但是一般情况都分配内存成功,故不做异常检查
        
        auto temp = newdata;
        // 将原来的数据全部拷贝的当前数据中
        for(auto i = sta.base; i!= sta.top; ++i){
            *(temp++) = *I;
        }
        *(temp++) = e;
        delete[] sta.base;
        sta.base = newdata;
        sta.top = temp;
        sta.StackSize = sta.StackSize+StackSizeCre;
    }else {
        *(sta.top++) = e;
    }
}

4. 栈的删除

在删除栈的过程中,需要先判断该栈是否为空栈(即栈顶和栈底的指向同一个内存空间),之后在进行删除操作,返回指针对象,因为当为空的栈的话,方便返回空指针。

// 删除栈元素(只能删除栈顶的元素)
ElemType* pop(Stack &sta){

    // 先判断是否为空栈
    if(sta.base != sta.top){
        return &*(--sta.top);

    }else{
        std::cout<<"this stack is empty!\n";
        return nullptr;
    }

}

5. 获得栈的大小

栈的大小通过指向数据对象的指针进行相减得到,其结果的数据类型应该是size_t类型,需要进行隐式类型转换到unsigned int 类型。

// 返回栈的大小
unsigned int GetSize(Stack &sta){
    return sta.top-sta.base;
}

6. 获取栈顶的元素

只取值 不进行删除操作

// 获取栈顶元素的值
ElemType GetTopVal(Stack &sta){
    auto temp = sta.top;
    return *(--temp);
}

7. 清空栈

void clean(Stack &sta){
    sta.StackSize = 0;
    delete[] sta.base;
}

三、完整栈的使用程序

#include<iostream>
#include<stdexcept>

typedef  int ElemType; // 取别名 (方便给栈选择不同的数据类型)

const unsigned int StackInitSize = 100; // 初始化每个栈刚开始的容量
const unsigned int StackSizeCre  = 20; // 当栈的容量不能满足使用 需要对栈进行扩容处理

// 定义栈对象
struct Stack
{
    ElemType *base; // 栈底
    ElemType *top;  // 栈顶
    unsigned int StackSize; // 栈可以容纳最大的数据量
};

// 栈的初始化
void init_stack(Stack *sta){
    // 给该栈分配内存(最大容量内存)
    try{
        sta->base = new ElemType[StackInitSize];
        // 必须要保证分配内存成功!(当使用new 分配内存不成功,会抛出异常,所以需要捕捉这个异常!)
        // 当使用new 分配内存不成功时,会抛出 bad_alloc 的异常

    }catch(const std::bad_alloc& e)
    {
        std::cout<<"can,t init stack!";
        return ;
    }

    // 分配内存正常后
    sta->top = sta->base; // 此时空栈 栈顶和栈底对应的位置相同
    sta->StackSize = StackInitSize;
}

// 插入新的元素 在栈顶
void push( Stack &sta , ElemType e){
    
    auto size = sta.top - sta.base;

    // 先判断该栈是否已经满
    if(size == sta.StackSize){
        ElemType *newdata = new ElemType[sta.StackSize+StackSizeCre]; // 此处也需要判断是否分配正常 但是一般情况都分配内存成功,故不做异常检查
        
        auto temp = newdata;
        // 将原来的数据全部拷贝的当前数据中
        for(auto i = sta.base; i!= sta.top; ++i){
            *(temp++) = *I;
        }
        *(temp++) = e;
        delete[] sta.base;
        sta.base = newdata;
        sta.top = temp;
        sta.StackSize = sta.StackSize+StackSizeCre;
    }
    else{
        *(sta.top++) = e;
    }
}


// 删除栈元素(只能删除栈顶的元素)
ElemType* pop(Stack &sta){

    // 先判断是否为空栈
    if(sta.base != sta.top){
        return &*(--sta.top);

    }else{
        std::cout<<"this stack is empty!\n";
        return nullptr;
    }

}


// 返回栈的大小
unsigned int GetSize(Stack &sta){
    return sta.top-sta.base;
}

// 获取栈顶元素的值
ElemType GetTopVal(Stack &sta){
    auto temp = sta.top;
    return *(--temp);
}

// 清空栈
void clean(Stack &sta){
    sta.StackSize = 0;
    delete[] sta.base;
}

int main(){

    Stack stack ;

    // 初始化 栈对象
    init_stack(&stack);
    std::cout<<"after init\n";
    std::cout<<"size "<<GetSize(stack)<<" capacity "<<stack.StackSize<<std::endl;

    // 生成101个栈的对象
    for(int i = 0;i<101;++i){
        push(stack,i);
    }
    
    int size = GetSize(stack);
    std::cout<<"after push\n";
    std::cout<<"size "<<GetSize(stack)<<" capacity "<<stack.StackSize<<std::endl;
    // 取出栈顶的数据
    std::cout<<" the val : "<<GetTopVal(stack)<<std::endl;
    std::cout<<"after get val\n";
    std::cout<<"size "<<GetSize(stack)<<" capacity "<<stack.StackSize<<std::endl;


    // 删除栈顶的数据
    for(int i=0;i<size;++i){
        std::cout<<*pop(stack)<<"  ";
    }
    std::cout<<"after pop\n";
    std::cout<<"size "<<GetSize(stack)<<" campacity "<<stack.StackSize<<std::endl;
    
    // 清空栈数据
    clean(stack);
    std::cout<<"after clean\n";
    std::cout<<"size "<<GetSize(stack)<<" campacity "<<stack.StackSize<<std::endl;
    

    return 0;
}

输出结果

after init
size 0 capacity 100
after push
size 101 capacity 120
 the val : 100
after get val
size 101 capacity 120
100  99  98  97  96  95  94  93  92  91  90  89  88  87  86  85  84  83  82  81  80  79  78  77  76  75  74  73  72  71  70  69  68  67  66  65  64  63  62  61  60  59  58  57  56  55  54  53  52  51  50  49  48  47  46  45  44  43  42  41  40  39  38  37  36  35  34  33  32  31  30  29  28  27  26  25  24  23  22  21  20  19  18  17  16  15  14  13  12  11  10  9  8  7  6  5  4  3  2  1  0  after pop
size 0 campacity 120
after clean
size 0 campacity 0

相关文章

  • 栈基本特性和操作

    一、栈的特性(先进后出) 特点:栈只能在栈顶进行删除(pop),插入(push)操作。 栈顶是顺序存储结构上第一个...

  • 作业帮做-栈结构验证

    顺序栈操作验证 实验目的 掌握栈的顺序存储结构; 验证栈的操作特性; 掌握顺序栈的基本操作实现方法。 实验内容 建...

  • 04、栈、队列、双端队列、优先队列

    栈和队列的基本实现和特性 小结 Stack、Queue、Deque 的原理和操作复杂度 PriorityQueue...

  • 数据结构之队列

    队列其实和栈的特性刚好相反,队列是先进先出的,这个特性很容易就想到排队。 队列的基本操作 入队(enqueue),...

  • 数据结构入门教程-栈的应用实例1

    在这篇文章中数据结构入门教程-栈,我们了解了栈的基本操作,如入栈(push)和出栈(pop)这两个重要的特性,本篇...

  • 数据结构-栈

    栈 特性:后进先出 LIFO 基本概念 栈是运算受限的线性表,插入和删除限定在表的一端进行操作; 栈顶:允许插入删...

  • 数据结构与算法---栈

    栈的基本结构 后进先出,先进后出,就是典型的“栈”结构。 从栈的操作特性上来看, ,只允许在一端插入和删除数据。 ...

  • 数据结构之栈

    栈 栈:具有数据先入后出,先出后入的特性。从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删...

  • 栈和队列

    顺序栈的基本操作: 链栈的基本操作 顺序队的基本操作 链队的基本操作

  • 数据结构与算法(四)栈

    什么是栈 栈是一种操作受限的线性表.基本特性是先进后出,后进先出. 栈的实现 栈可以用数组来实现叫做顺序栈,也可以...

网友评论

      本文标题:栈基本特性和操作

      本文链接:https://www.haomeiwen.com/subject/ooprmqtx.html