zoukankan      html  css  js  c++  java
  • 数据结构(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都可以写成一条指令。最现代的计算机将栈操作作为其指令系统的一部分,这个事实强化了这样一种思想,即在计算机科学中,栈很可能是继数组之后的最基本的数据结构。

          

  • 相关阅读:
    topcoder srm 320 div1
    topcoder srm 325 div1
    topcoder srm 330 div1
    topcoder srm 335 div1
    topcoder srm 340 div1
    topcoder srm 300 div1
    topcoder srm 305 div1
    topcoder srm 310 div1
    topcoder srm 315 div1
    如何统计iOS产品不同渠道的下载量?
  • 原文地址:https://www.cnblogs.com/hliu17/p/7399963.html
Copyright © 2011-2022 走看看