数据结构之栈

本文详细介绍了栈这种数据结构,包括其定义、特性、操作及两种实现方式:静态栈与链式栈。通过具体代码示例,帮助读者理解栈的工作原理及其应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、栈的定义

  1.栈是一种特殊的线性表;
  
  2.栈只能在线性表的一端进行操作。即只允许在栈顶(Top)操作,而不允许在栈底(Bottom)操作。
  

二、栈的特性

  由于栈只允许在栈顶(Top)操作,故栈的特性为后进先出(Last In First Out)。如下图所示:
  这里写图片描述
(注:此图引用自狄泰软件学院唐老师ppt)

三、栈的操作
  • 创建栈(Stack())
  • 销毁栈(~Stack())
  • 清空栈(clear())
  • 进栈(push())
  • 出栈(pop())
  • 获取栈顶元素(top())
  • 获取栈的大小(size())
四、栈的实现

1.栈的抽象实现:

Stack.h

#ifndef STACK_H
#define STACK_H

namespace Stack {

template <typename T>
class Stack
{
public:
    virtual void push(const T& e) = 0;
    virtual void pop() = 0;
    virtual T top() = 0;
    virtual void clear() = 0;
    virtual int size() const = 0;
};

}

#endif // STACK_H

2.静态栈的实现:

设计要点:
  1.使用原生数组作为栈的存储空间;
  
  2.栈的存储空间在创建栈的时候指定(由模板参数指定),且不能动态的改变。

下面给出静态栈的具体实现:

StaticStack.h

#ifndef STATICSTACK_H
#define STATICSTACK_H

#include "Stack.h"
#include "Exception.h"

namespace Stack {

template <typename T, int N>
class StaticStack : public Stack<T>
{
protected:
    T m_space[N];
    int m_top;
    int m_size;

public:
    StaticStack()
    {
        m_top = -1;
        m_size = 0;
    }

    int capacity() const
    {
        return N;
    }

    void push(const T& e)
    {
        if (m_size < N) {
            m_space[m_top + 1] = e;     // 先赋值,再改变m_top 和m_size,是为了异常安全

            m_top ++;
            m_size ++;
        } else {
            throw("No space in current stack ...");
        }
    }

    void pop()
    {
        if (m_size > 0) {
            m_top --;
            m_size --;
        } else {
            throw("No element in current stack ...");
        }
    }

    T top()
    {
        if (m_size > 0) {
            return m_space[m_top];
        } else {
            throw("No element in current stack ...");
        }
    }

    void clear()
    {
        m_top = -1;
        m_size = 0;
    }

    int size() const
    {
        return m_size;
    }
};

}

#endif // STATICSTACK_H

3.链式栈的实现

  由于静态栈一次性创建指定大小的空间,如果栈的数据元素为类类型的话,就需要调用N次构造函数,故效率会比较低;另静态栈没法动态的改变栈的大小。
  
  基于以上两点,链式栈便可以解决上述两个问题。

设计要点:
  1.用类模板实现,是抽象父类Stack的直接子类;
  
  2.内部实现一个单链表;
  
  3.只在单链表成员对象的头部进行操作。

下面给出链式栈的具体实现:

LinkStack.h

#ifndef LINKSTACK_H
#define LINKSTACK_H

#include "Stack.h"

namespace Stack {

template <typename T>
class LinkStack : public Stack<T>
{
protected:
    struct Node {
        T value;
        struct Node* next;
    };
    // 为了防止泛指类型T在构造函数中抛出异常,导致栈初始化失败,故重新实现头结构
    struct {
        char reserved[sizeof(T)];
        Node* next;
    } m_header;
    int m_length;
public:
    LinkStack()
    {
        m_length = 0;
        m_header.next = NULL;
    }
    void push(const T& e)
    {
        Node* node = new Node();

        if (node) {
            node->value = e;
            if (0 == m_length) {
                m_header.next = node;
            } else {
                node->next = m_header.next;
                m_header.next = node;
            }
            m_length ++;
        } else {
            throw("No memory to create node ...");
        }
    }

    void pop()
    {
        if (m_length > 0) {
            Node* toPop = m_header.next;
            m_header.next = toPop->next;
            m_length --;
            delete toPop;
        } else {
            throw( "No element in current stack ...");
        }
    }

    T top()
    {
        if (m_length > 0) {
            return m_header.next->value;
        } else {
            throw( "No element in current stack ...");
        }
    }

    void clear()
    {
        while (m_length > 0) {
            pop();
        }
    }

    int size() const
    {
        return m_length;
    }
};

}

#endif // LINKSTACK_H
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值