• 栈的浅析与实现


    1. 栈的简介

    1.1栈的特性

    (Stack)是一种线性存储结构,它具有如下特点:

    1. 栈中的数据元素遵守”先进后出"(First In Last Out)的原则,简称FILO结构。
    2. 限定只能在栈顶进行插入和删除操作(单向操作)。

    1.2栈的相关概念

    1. 栈顶与栈底:允许元素插入与删除的一端称为栈顶,另一端称为栈底。
    2. 压栈:栈的插入操作,叫做进栈,也称压栈、入栈。
    3. 弹栈:栈的删除操作,也叫做出栈。

    例:我们有一个存储整型元素的栈,我们依次压栈:{1,2,3}

    在压栈的过程中,栈顶的位置一直在”向上“移动,而栈底是固定不变的。
    如果我们要把栈中的元素弹出来:

    出栈的顺序为3、2、1 ,顺序与入栈时相反,这就是所谓的”先入后出“。
    在弹栈的过程中,栈顶位置一直在”向下“移动,而栈底一直保持不变。

    1.3 栈的操作

    栈的常用操作为:

    1. 弹栈,通常命名为pop
    2. 压栈,通常命名为push
    3. 求栈的大小
    4. 判断栈是否为空
    5. 获取栈顶元素的值

    1.4 栈的存储结构

       是一种线性结构,就能够以数组或链表(单向链表、双向链表或循环链表)作为底层数据结构。
    本文我们以数组、单向链表为底层数据结构构建栈。

     

    2. 基于数组的栈实现

      当以数组为底层数据结构时,通常以数组头为栈底,数组头到数组尾为栈顶的生长方向:

    2.1 栈的抽象数据类型

    栈提供了如上所述操作的相应接口。

    template<typename T>
    class ArrayStack
    {
    public:
        ArrayStack(int s = 10);    //默认的栈容量为10
        ~ArrayStack();
     
    public:
        T top();            //获取栈顶元素
        void push(T t);        //压栈操作
        T pop();            //弹栈操作
        bool isEmpty();        //判空操作
        int size();            //求栈的大小
     
    private:
        int count;            //栈的元素数量
        int capacity;        //栈的容量
        T * array;            //底层为数组
    };
    栈的定义
    1. count 为栈的元素数量,capacity为栈的容量,count<=capacity,当栈满的时候,count = capacity。
    2. 本实现中不支持栈的动态扩容,栈满的时候无法再插入元素。栈的容量在定义栈的时候就需要指定,默认的栈容量为10。

    2.2 栈的具体实现

    /*栈的判空操作*/
    template <typename T>
    bool ArrayStack<T>::isEmpty()
    {
         return count == 0; //栈元素为0时为栈空
    };
     
    /*返回栈的大小*/
     template <typename  T>
    int ArrayStack<T>::size()
    {
         return count;
    };
     
    /*插入元素*/
    template <typename T>
    void ArrayStack<T>::push(T t)
    {
         if (count != capacity)    //先判断是否栈满
         {
             array[count++] = t;   
         }
    };
     
    /*弹栈*/
    template <typename T>
    T ArrayStack<T>::pop()
    {
         if (count != 0)    //先判断是否是空栈
         {
             return array[--count];
         }
    };
     
    /*获取栈顶元素*/
    template <typename T>
    T ArrayStack<T>::top()
    {
         if (count != 0)
         {
             return array[count - 1];
         }
    };
    栈的操作

    2.3 栈的代码测试

    int main(int argc, char* argv[])
    {
        ArrayStack <int> p(5);
        for (int i = 0; i < 5; i++)
        {
            p.push(i);
        }
        cout << "栈的大小:"<<p.size() << endl;
        cout << "栈是否为空:"<<p.isEmpty() << endl;
        cout << "栈顶元素:"<<p.top() << endl;
        cout << "依次出栈:" << endl;
        while (!p.isEmpty())
        {
            cout << p.pop() << endl;
        }
        getchar();
        return 0;
    }
    测试

    测试结果

    栈的大小:5
    栈是否为空:0
    栈顶元素:4
    依次出栈:
    4
    3
    2
    1
    0

    3. 基于单链表的栈

    以链表为底层的数据结构时,以链表头为作为栈顶较为合适,这样方便节点的插入与删除。压栈产生的新节点将一直出现在链表的头部;

    3.1 链表节点

    /*链表节点结构*/
    template <typename T>
    struct Node
    {
        Node(T t) :value(t), next(nullptr){};
        Node() :next(nullptr){};
     
    public:
        T value;
        Node<T>* next;
    };
    栈的定义
    1. value:栈中元素的值
    2. next:链表节点指针,指向直接后继

    3.2 栈的抽象数据类型

    基于链表的栈提供的接口与基于数组的栈一致。

    /*栈的抽象数据结构*/
    template <typename T>
    class LinkStack
    {
    public:
         LinkStack();
         ~LinkStack();
    public:
     
         bool isEmpty();
         int size();
         void push(T t);
         T pop();
         T top();
     
    private:
     
         Node<T>* phead;
         int count;
    };
    栈的抽象

    3.3 栈的具体实现

    /*返回栈的大小*/
    template <typename T>
    int LinkStack<T>::size()
    {
         return count;
    };
    /*栈的判空操作*/
    template <typename T>
    bool LinkStack<T>::isEmpty()
    {
         return count == 0;
    };
    /*插入元素*/
    template<typename T>
    void LinkStack<T>::push(T t)
    {
         Node <T> *pnode = new  Node<T>(t);
         pnode->next = phead->next;
         phead->next = pnode;
         count++;
    };
    /*弹栈*/
    template <typename T>
    T LinkStack<T>::pop()
    {
         if (phead->next != nullptr) //栈空判断
         {
             Node<T>* pdel = phead->next;
             phead->next = phead->next->next;
             T value = pdel->value;
             delete pdel;
             count--;
             return value;
         }
    };
    /*获取栈顶元素*/
    template <typename T>
    T LinkStack<T>::top()
    {
        if (phead->next!=nullptr)
            return phead->next->value;
    };
    栈的操作

    3.4 栈的代码测试

    int main(int argc, char* argv[])
    {
        LinkStack <string> lstack;
        lstack.push("hello");
        lstack.push("to");
        lstack.push("you!");
     
        cout << "栈的大小:" << lstack.size() << endl;
        cout <<"栈顶元素:"<< lstack.top() << endl;
     
        while (!lstack.isEmpty())
        {
            lstack.pop();
        }
     
        cout << "栈的大小:" << lstack.size() << endl;
     
        getchar();
        return 0;
    }
    测试

    测试结果:

    栈的大小:3
    栈顶元素:you!
    栈的大小:0
    海阔凭鱼跃,天高任鸟飞。
  • 相关阅读:
    select选择框去掉默认的下拉箭头
    网站怎么添加ico小图标
    js实现逐字打印效果,文本逐字显示
    jQuery实现消息列表循环垂直向上滚动
    滤镜图片变黑白+图片模糊
    多选下拉框(select 下拉多选)
    JavaScript 数组相关基础方法
    h5+ IOS App中判断本地文件是否存在 plus.io.resolveLocalFileSystemURL()
    h5+ IOS App中取消视频默认全屏播放
    C# 多线程与队列操作小练刀
  • 原文地址:https://www.cnblogs.com/chenshikun/p/8193696.html
Copyright © 2020-2023  润新知