• 数据结构(c++)(1)-- 栈


          最近在复习数据结构(我用的是数据结构与算法分析c++描述 第三版的书,很不错的书,有兴趣的可以去看看)的相关知识,顺便就做了些整理,以供参考。

          栈(stack)是限制插入和删除操作只能在一个位置进行的表,该位置是表的末端,称为栈的顶。对栈的操作是push(入栈)和pop(出栈),前者相当于插入,后者则是删除最后插入的元素。最后插入的元素可以通过使用top方法在执行pop之前进行访问。对空栈的pop或top操作,在栈ADT中一般认为是一个错误。另一方面,当运行push时超出栈空间的最大内存时候,这是栈在实现过程中所受的限制,并不是ADT错误。

          下面打个比方,以便于更好理解栈。其实对于栈,是一种后进先出的表,我们可以想象这样一种现实中的场景,当汽车依次进入了一个狭窄的巷子的时候,突然发现前面有个障碍物挡住了道路,那么这个时候该怎么办?显而易见,这个时候先进去的车辆是无法挪动的,只有在最后的车辆可以通过倒车而进行行驶,当最后一辆车出去后,相应的倒数第二辆车才可以出去,一直到最后第一辆车才有可能出了这个巷子,这也正是我们的栈的工作原理。

          例如,将元素6、3、7、6、2依次插入到栈中的话,则栈的示意图如下:


    由于栈是是一个表,因此任何实现表的方法都可以用来实现栈。其实栈就是对我们比较熟悉的表的操作进行了限制,对数组来说,我们可以通过下标来访问数组中的任意一个元素,而如果我们想数组表现出栈的特性,那么很容易做到的,只需要对数组进行包装,封装成一个类,该类只有显著的push和pop操作,也就是对数组的下标操作做一些限制,每次只能对数组中的最后位置进行操作(这里的最后位置指的是存放有元素的最大下标的位置)。在实际中,很明显list和vector支持栈操作,99%的情况下,它们都是合理的选择。当然对于栈的实现的选择,需要具体情况具体分析,有时候为了特殊目的而设计的实现可以运行的更快。由于栈的所有操作都是常量时间的操作,所以,除非是在很特别的环境下,否则不太可能有明显的改进。

    当前两个比较流行的栈的实现方式,一个是使用链表结构,另一个则是使用数组。

    1、栈的链表实现

    栈的一种实现方法是使用单向链表。我们通过在表顶端插入元素来实现push,通过删除表顶端的元素实现pop。top操作知识访问表顶端的元素并返回它的值。有时pop操作 和top操作可以合二为一。这里面为什么说要将元素放在表的顶端而不是末尾或其它位置呢?这个是因为在栈中我们只关心栈定的元素,那么这个栈顶元素的访问效率问题就必须要考虑了,所以将元素放在链表的顶端,可以通过链表的头指针直接进行访问,这个访问时间是常量,而如果放在末尾,那么则需要遍历链表找到栈顶的元素,显然浪费了访问的时间,这是不可取的。

    2、栈的数组实现

    另一种可选的实现避免了使用链并且可能是更流行的解决方案。由于使用vector中的back、push_back、pop_back方法,实现栈特别容易。更一般的方法是使用数组进行栈的构建,下面给出一个基本的示例:

    #include<iostream>
    using namespace std;
    
    #define MAXSIZE 20
    template <typename Object>
    class CStack
    {
    public:
    	CStack():m_topOfStack(-1){}
    	bool empty() const;
    	bool pop();
    	bool top(Object &item) const;
    	bool push(const Object &item);
    private:
    	Object m_theArray[MAXSIZE];
    	int m_topOfStack;
    };
    template <typename Object>
    bool CStack<Object>::empty() const
    {
    	if(m_topOfStack==-1)
    		return true;
    	return false;
    }
    template <typename Object>
    bool CStack<Object>::pop() 
    {
    	if(m_topOfStack==-1)
    		return false;
    	m_topOfStack--;
    	return true;
    }
    template <typename Object>
    bool CStack<Object>::top(Object &item) const
    {
    	if(m_topOfStack==-1)
    		return -1;
    	item=m_theArray[m_topOfStack];
    	return true;
    }
    template <typename Object>
    bool CStack<Object>::push(const Object &item)
    {
    	if(m_topOfStack>=MAXSIZE-1)
    		return false;
    	m_theArray[++m_topOfStack]=item;
    }
    在栈中,这些操作都是以常数时间运行的,而且是以非常快的常数时间运行。在某些机器上,若在带有自增和自减寻址功能的寄存器上操作,则(整数)push和pop都可以写成一条指令。最现代的计算机将栈操作作为其指令系统的一部分,这个事实强化了这样一种思想,即在计算机科学中,栈很可能是继数组之后的最基本的数据结构。

          

  • 相关阅读:
    centos7安装es6.4.0
    将mysql数据同步到ES6.4(全量+增量)
    c#基于supersocket的简单websocket服务端收发消息实现
    c#log4net简单好用的配置
    MongoDB安装配置教程
    IntelliJ IDEA 中创建maven项目
    VMware Workstation 的安装和使用
    Redis使用场景
    Redis 下载安装
    MySQL--启动和关闭MySQL服务
  • 原文地址:https://www.cnblogs.com/hliu17/p/7399963.html
Copyright © 2020-2023  润新知