栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线性表。栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据。栈是只能在某一端插入和删除的特殊线性表。用桶堆积物品,先堆进来的压在底下,随后一件一件往堆。取走时,只能从上面一件一件取。堆和取都在顶部进行,底部一般是不动的。栈就是一种类似桶堆积物品的数据结构,进行删除和插入的一端称栈顶,另一堆称栈底。插入一般称为进栈,删除则称为退栈。 栈也称为后进先出表。
基本概念
首先系统或者数据结构栈中数据内容的读取与(压入push和 弹出pop)是两回事!插入是增加数据弹出是删除数据 ,这些操作只能从栈顶即最低地址作为约束的接口界面入手操作 ,但读取栈中的数据 是随便的 没有接口约束之说。很多人都误解这个理念从而对栈产生困惑。[1]而系统栈在计算机体系结构中 又起到一个跨部件交互的媒介区域的作用 即 cpu 与内存的交流通道 ,cpu只从系统给我们自己编写的应用程序所规定的栈入口线性地读取执行指令, 用一个形象的词来形容它就是pipeline(管道线、流水线)。cpu内部交互具体参见 EU与BIU的概念介绍。
栈特性
栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。
栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为后进先出表。
栈可以用来在函数调用的时候存储断点,做递归时要用到栈!
栈与计算机
在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。在i386机器中,栈顶由称为esp的寄存器进行定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大。
栈在程序的运行中有着举足轻重的作用。最重要的是栈保存了一个函数调用时所需要的维护信息,这常常称之为堆栈帧或者活动记录。堆栈帧一般包含如下几方面的信息:
1.函数的返回地址和参数
2. 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
栈算法
进栈算法
①若TOP≥n时,则给出溢出信息,作出错处理(进栈前首先检查栈是否已满,满则溢出;不满则作②);
②置TOP=TOP+1(栈指针加1,指向进栈地址);
③S(TOP)=X,结束(X为新进栈的元素);
退栈算法
①若TOP≤0,则给出下溢信息,作出错处理(退栈前先检查是否已为空栈, 空则下溢;不空则作②);
②X=S(TOP),(退栈后的元素赋给X);
③TOP=TOP-1,结束(栈指针减1,指向栈顶)。
顺序存储结构
在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构.
顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的节点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现。由此得到的存储结构为顺序存储结构,通常顺序存储结构是借助于计算机程序设计语言(例如c/c++)的数组来描述的。
顺序存储结构的主要优点是节省存储空间,因为分配给数据的存储单元全用存放结点的数据(不考虑c/c++语言中数组需指定大小的情况),结点之间的逻辑关系没有占用额外的存储空间。采用这种方法时,可实现对结点的随机存取,即每一个结点对应一个序号,由该序号可以直接计算出来结点的存储地址。但顺序存储方法的主要缺点是不便于修改,对结点的插入、删除运算时,可能要移动一系列的结点。
优点:
随机存取表中元素。缺点:插入和删除操作需要移动元素。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以后的笔记潇汀会尽量详细讲解一些相关知识的,希望大家继续关注、支持、顶起我的博客。
你们的关注就是我的动力,本节笔记到这里就结束了。
潇汀一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。
编程开发的路很长很长,非常希望能和大家一起交流,共同学习,共同进步。
如果文章中有什么疏漏的地方,也请大家留言指正。也希望大家可以多留言来和我探讨编程相关的问题。
最后,谢谢你们一直的支持~~~
------------------------------------------
Country: China
Tel: +86-152******41
QQ: 451292510
E-mail: xiaoting_chen2010@163.com
------------------------------------------
C++完整个代码示例(代码在VS2005下测试可运行)
AL_StackSeq.h
/**
@(#)$Id: AL_StackSeq.h 44 2013-09-13 08:50:04Z xiaoting $
@brief Stack (stack) in computer science is limited only in the end of the table to insert or delete operations linear form.
A stack is a data structure that in accordance with the principle of LIFO data storage, data is first pushed into the end of the
last data in the stack, you need to read the data when the data from the topmost pop. The stack is only one end of the inserted
and deleted special linear form. Buckets stacked items, first came under pressure in the heap, followed by a one to the heap.
Removed, only a one taken from above. Take the top of the heap and are carried at the bottom of the general is not moving. Stack
is a similar data structure barrels stacked items, delete and insert one end of said stack, said another pile bottom of the stack.
Insert commonly known as the push to delete is called the stack back. Also known as LIFO stack table.
Sequential storage structure//
Using a set of addresses in the computer storage unit sequentially stores continuous linear form of individual data elements, called
the linear order of the table storage structure.
Sequential storage structure is a type of a storage structure, the structure is the logically adjacent nodes stored in the physical
location of the adjacent memory cells, the logical relationship between nodes from the storage unit to reflect the adjacency.
Storage structure thus obtained is stored in order structure, usually by means of sequential storage structure computer programming
language (e.g., c / c) of the array to describe.
The main advantage of the storage structure in order to save storage space, because the allocation to the data storage unit storing
all nodes with data (without regard to c / c language in the array size required for the case), the logical relationship between
the nodes does not take additional storage space. In this method, the node can be realized on a random access, that is, each node
corresponds to a number, the number can be calculated directly from the node out of the memory address. However, the main
disadvantage of sequential storage method is easy to modify the node insert, delete operations, may have to move a series of nodes.
Benefits:
Random Access table elements. Disadvantages: insert and delete operations need to move elements.
@Author $Author: xiaoting $
@Date $Date: 2013-09-13 16:50:04 +0800 (周五, 13 九月 2013) $
@Revision $Revision: 44 $
@URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_StackSeq.h $
@Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_StackSeq.h 44 2013-09-13 08:50:04Z xiaoting $
*/
#ifndef CXX_AL_STACKSEQ_H
#define CXX_AL_STACKSEQ_H
///
// AL_StackSeq
///
template<typename T>
class AL_StackSeq
{
public:
static const DWORD STACKSEQ_MAXSIZE = 0xffffffff;
static const DWORD STACKSEQ_DEFAULTSIZE = 100;
/**
* Construction
*
* @param DWORD dwSize (default value: STACKSEQ_DEFAULTSIZE)
* @return
* @note
* @attention
*/
AL_StackSeq(DWORD dwSize = STACKSEQ_DEFAULTSIZE);
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
~AL_StackSeq();
/**
* IsEmpty
*
* @param VOID
* @return BOOL
* @note Returns true stack is empty
* @attention
*/
BOOL IsEmpty() const;
/**
* Pop
*
* @param T& tTypeOut <OUT>
* @return BOOL
* @note Remove the top element and return data top element
* @attention if empty does not return a value... (please judge the stack is empty before use it)
*/
BOOL Pop(T& tTypeOut);
/**
* Push
*
* @param const T& tTemplate
* @return BOOL
* @note Add elements in the stack
* @attention
*/
BOOL Push(const T& tTemplate);
/**
* Size
*
* @param VOID
* @return DWORD
* @note Returns the number of elements in the stack
* @attention
*/
DWORD Size() const;
/**
* Top
*
* @param T& tTypeOut <OUT>
* @return BOOL
* @note Back to the top element...
* @attention if empty does not return a value... (please judge the stack is empty before use it)
*/
BOOL Top(T& tTypeOut) const;
/**
* Clear
*
* @param VOID
* @return VOID
* @note clear all data
* @attention
*/
VOID Clear();
protected:
private:
/**
* GetBuffer
*
* @param VOID
* @return VOID
* @note get the work buffer
* @attention when the buffer is not enough, it will become to double
*/
VOID GetBuffer();
/**
* IsFull
*
* @param VOID
* @return BOOL
* @note the buffer is full?
* @attention
*/
BOOL IsFull() const;
public:
protected:
private:
T* m_pElements;
DWORD m_dwMaxSize;
DWORD m_dwSize;
};
/**
* Construction
*
* @param DWORD dwSize (default value: STACKSEQ_DEFAULTSIZE)
* @return
* @note
* @attention
*/
template<typename T>
AL_StackSeq<T>::AL_StackSeq(DWORD dwSize):
m_pElements(NULL),
m_dwMaxSize(dwSize),
m_dwSize(0x00)
{
if (0x00 == m_dwMaxSize) {
//for memory deal
m_dwMaxSize = 1;
}
GetBuffer();
}
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template<typename T>
AL_StackSeq<T>::~AL_StackSeq()
{
if (NULL != m_pElements) {
delete[] m_pElements;
m_pElements = NULL;
}
}
/**
* IsEmpty
*
* @param VOID
* @return BOOL
* @note Returns true stack is empty
* @attention
*/
template<typename T> BOOL
AL_StackSeq<T>::IsEmpty() const
{
return (0x00 == m_dwSize) ? TRUE:FALSE;
}
/**
* Pop
*
* @param T& tTypeOut <OUT>
* @return BOOL
* @note Remove the top element and return data top element
* @attention if empty does not return a value... (please judge the stack is empty before use it)
*/
template<typename T> BOOL
AL_StackSeq<T>::Pop(T& tTypeOut)
{
if (TRUE == IsEmpty()) {
return FALSE;
}
tTypeOut = m_pElements[Size()-1];
//memset(&m_pElements[Size()-1], 0x00, sizeof(T)); //can not use memset, as to pointer or virtural pointer of class
m_dwSize--;
return TRUE;
}
/**
* Push
*
* @param const T& tTemplate
* @return BOOL
* @note Add elements in the stack
* @attention
*/
template<typename T> BOOL
AL_StackSeq<T>::Push(const T& tTemplate)
{
if (TRUE == IsFull()) {
// full, need to get more work buffer
GetBuffer();
}
m_pElements[Size()] = tTemplate;
m_dwSize++;
return TRUE;
}
/**
* Size
*
* @param VOID
* @return DWORD
* @note Returns the number of elements in the stack
* @attention
*/
template<typename T> DWORD
AL_StackSeq<T>::Size() const
{
return m_dwSize;
}
/**
* Top
*
* @param T& tTypeOut <OUT>
* @return BOOL
* @note Back to the top element...
* @attention if empty does not return a value... (please judge the stack is empty before use it)
*/
template<typename T> BOOL
AL_StackSeq<T>::Top(T& tTypeOut) const
{
if (TRUE == IsEmpty()) {
//Empty
return FALSE;
}
tTypeOut = m_pElements[Size()-1];
return TRUE;
}
/**
* Clear
*
* @param VOID
* @return VOID
* @note clear all data
* @attention
*/
template<typename T> VOID
AL_StackSeq<T>::Clear()
{
//memset(m_pElements, 0x00, sizeof(T)*Size()); //can not use memset, as to pointer or virtural pointer of class
m_dwSize = 0x00;
}
/**
* GetBuffer
*
* @param VOID
* @return VOID
* @note get the work buffer
* @attention when the buffer is not enough, it will become to double
*/
template<typename T> VOID
AL_StackSeq<T>::GetBuffer()
{
if ( (FALSE == IsFull()) && (NULL != m_pElements) ) {
//we do not need to get more buffer
return;
}
if (NULL == m_pElements) {
if(0 < m_dwMaxSize){
//get the new work buffer
m_pElements = new T[m_dwMaxSize];
//memset(m_pElements, 0x00, sizeof(T)*m_dwMaxSize); //can not use memset, as to pointer or virtural pointer of class
}
return;
}
//we need to get more buffer, store the previous pointer
T* pLastTpye = NULL;
// it will become to double
pLastTpye = m_pElements;
if (STACKSEQ_MAXSIZE == m_dwMaxSize) {
//can not get more buffer, please check the application
return;
}
else if (STACKSEQ_MAXSIZE/2 < m_dwMaxSize) {
m_dwMaxSize = STACKSEQ_MAXSIZE;
}
else {
m_dwMaxSize *= 2;
}
if(0 < m_dwMaxSize){
//get the new work buffer
m_pElements = new T[m_dwMaxSize];
//memset(m_pElements, 0x00, sizeof(T)*m_dwMaxSize); //can not use memset, as to pointer or virtural pointer of class
}
//need to copy the last to the current
for (DWORD dwCpy=0; dwCpy<Size(); dwCpy++) {
m_pElements[dwCpy] = pLastTpye[dwCpy];
}
// memcpy(m_pElements, pLastTpye, sizeof(T)*Size()); //can not use memcopy, as to pointer
//free the last work buffer
delete[] pLastTpye;
pLastTpye = NULL;
}
/**
* IsFull
*
* @param
* @return BOOL
* @note the buffer is full?
* @attention
*/
template<typename T> BOOL
AL_StackSeq<T>::IsFull() const
{
return (m_dwMaxSize <= Size()) ? TRUE:FALSE;
}
#endif // CXX_AL_STACKSEQ_H
/* EOF */
测试代码
#ifdef TEST_AL_STACKSEQ
AL_StackSeq<DWORD> cStackSeq(1);
BOOL bEmpty = cStackSeq.IsEmpty();
std::cout<<bEmpty<<std::endl;
DWORD dwPop = 0x00;
cStackSeq.Pop(dwPop);
std::cout<<dwPop<<std::endl;
DWORD dwSize = cStackSeq.Size();
std::cout<<dwSize<<std::endl;
DWORD dwTop = 0x00;
cStackSeq.Top(dwTop);
std::cout<<dwTop<<std::endl;
for (WORD wCnt=1; wCnt<16; wCnt++) {
//push 15 14 13 12.....
cStackSeq.Push(16 - wCnt);
cStackSeq.Top(dwTop);
std::cout<<dwTop<<std::endl;
}
bEmpty = cStackSeq.IsEmpty();
std::cout<<bEmpty<<std::endl;
dwSize = cStackSeq.Size();
std::cout<<dwSize<<std::endl;
while (0x00 != cStackSeq.Size()) {
cStackSeq.Pop(dwPop);
std::cout<<dwPop<<std::endl;
}
cStackSeq.Push(999);
cStackSeq.Push(888);
cStackSeq.Clear();
bEmpty = cStackSeq.IsEmpty();
std::cout<<bEmpty<<std::endl;
#endif