堆栈
堆疊(stack)又稱為棧或堆叠,是计算机科學中的一種抽象資料型別,只允許在有序的線性資料集合的一端(稱為堆疊頂端,top)進行加入数据(push)和移除数据(pop)的運算。因而按照後進先出(LIFO, Last In First Out)的原理運作,堆疊常用一維数组或連結串列來實現。常與另一種有序的線性資料集合佇列相提並論。 操作堆疊使用兩種基本操作:推入(压栈,push)和彈出(弹栈,pop):
上面就是栈最核心的两个基本操作,可以在栈的可视化页面中直观理解这里的操作。[1] 特点堆栈的基本特点:
抽象定义以下是堆栈的VDM(Vienna Development Method):[2] 函数签名: init: -> Stack
push: N x Stack -> Stack
top: Stack -> (N ERROR)
pop: Stack -> Stack
isempty: Stack -> Boolean
此处的N代表某个元素(如自然数),而表示集合求并。 语义: top(init()) = ERROR top(push(i,s)) = i pop(init()) = init() pop(push(i, s)) = s isempty(init()) = true isempty(push(i, s)) = false 软件堆栈堆栈可以用数组和链表两种方式实现,一般为一个堆栈预先分配一个大小固定且较合适的空间并非难事,所以较流行的做法是 这里的例程是以C語言实现的。 陣列堆疊存储结构/* c3-1.h 栈的顺序存储表示 */
#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACK_INCREMENT 2 /* 存储空间分配增量 */
typedef struct SqStack
{
SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */
SElemType *top; /* 栈顶指针 */
int stacksize; /* 当前已分配的存储空间,以元素为单位 */
}SqStack; /* 顺序栈 */
基本操作/* bo3-1.c 顺序栈(存储结构由c3-1.h定义)的基本操作(9个) */
void InitStack(SqStack *S)
{ /* 构造一个空栈S */
(*S).base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!(*S).base)
exit(OVERFLOW); /* 存储分配失败 */
(*S).top=(*S).base;
(*S).stacksize=STACK_INIT_SIZE;
}
void DestroyStack(SqStack *S)
{ /* 销毁栈S,S不再存在 */
free((*S).base);
(*S).base=NULL;
(*S).top=NULL;
(*S).stacksize=0;
}
void ClearStack(SqStack *S)
{ /* 把S置为空栈 */
(*S).top=(*S).base;
}
Status StackEmpty(SqStack S)
{ /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
if(S.top==S.base)
return TRUE;
else
return FALSE;
}
int StackLength(SqStack S)
{ /* 返回S的元素个数,即栈的长度 */
return S.top-S.base;
}
Status GetTop(SqStack S,SElemType *e)
{ /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
if(S.top>S.base)
{
*e=*(S.top-1);
return OK;
}
else
return ERROR;
}
void Push(SqStack *S,SElemType e)
{ /* 插入元素e为新的栈顶元素 */
if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */
{
(*S).base=(SElemType *)realloc((*S).base,((*S).stacksize+STACK_INCREMENT)*sizeof(SElemType));
if(!(*S).base)
exit(OVERFLOW); /* 存储分配失败 */
(*S).top=(*S).base+(*S).stacksize;
(*S).stacksize+=STACK_INCREMENT;
}
*((*S).top)++=e;
}
Status Pop(SqStack *S,SElemType *e)
{ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
if((*S).top==(*S).base)
return ERROR;
*e=*--(*S).top;
return OK;
}
void StackTraverse(SqStack S,void(*visit)(SElemType))
{ /* 从栈底到栈顶依次对栈中每个元素调用函数visit() */
while(S.top>S.base)
visit(*S.base++);
printf("\n");
}
串列堆疊存储结构/* c2-2.h 线性表的单链表存储结构 */
struct LNode
{
ElemType data;
struct LNode *next;
};
typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */
基本操作/* bo3-5.c 链栈(存储结构由c2-2.h定义)的基本操作(4个) */
/* 部分基本操作是由bo2-8.cpp中的函数改名得来 */
/* 另一部分基本操作是由调用bo2-8.cpp中的函数(取特例)得来 */
typedef SElemType ElemType; /* 栈结点类型和链表结点类型一致 */
#include"c2-2.h" /* 单链表存储结构 */
typedef LinkList LinkStack; /* LinkStack是指向栈结点的指针类型 */
#define InitStack InitList /* InitStack()与InitList()作用相同,下同 */
#define DestroyStack DestroyList
#define ClearStack ClearList
#define StackEmpty ListEmpty
#define StackLength ListLength
#include"bo2-8.c" /* 无头结点单链表的基本操作 */
Status GetTop(LinkStack S,SElemType *e)
{ /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
return GetElem(S,1,e);
}
Status Push(LinkStack *S,SElemType e)
{ /* 插入元素e为新的栈顶元素 */
return ListInsert(S,1,e);
}
Status Pop(LinkStack *S,SElemType *e)
{ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
return ListDelete(S,1,e);
}
void StackTraverse(LinkStack S,void(*visit)(SElemType))
{ /* 从栈底到栈顶依次对栈中每个元素调用函数visit() */
LinkStack temp,p=S; /* p指向栈顶元素 */
InitStack(&temp); /* 初始化临时栈temp */
while(p)
{
Push(&temp,p->data); /* 由S栈顶到栈底,依次将栈元素入栈到temp栈 */
p=p->next;
}
ListTraverse(temp,visit); /* 遍历temp线性表 */
}
链表基本操作/* bo2-8.c 不带头结点的单链表(存储结构由c2-2.h定义)的部分基本操作(9个) */
#define DestroyList ClearList /* DestroyList()和ClearList()的操作是一样的 */
void InitList(LinkList *L)
{ /* 操作结果:构造一个空的线性表L */
*L=NULL; /* 指针为空 */
}
void ClearList(LinkList *L)
{ /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */
LinkList p;
while(*L) /* L不空 */
{
p=*L; /* p指向首元结点 */
*L=(*L)->next; /* L指向第2个结点(新首元结点) */
free(p); /* 释放首元结点 */
}
}
Status ListEmpty(LinkList L)
{ /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
if(L)
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{ /* 初始条件:线性表L已存在。操作结果:返回L中数据元素个数 */
int i=0;
LinkList p=L;
while(p) /* p指向结点(没到表尾) */
{
p=p->next; /* p指向下一个结点 */
i++;
}
return i;
}
Status GetElem(LinkList L,int i,ElemType *e)
{ /* L为不带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
int j=1;
LinkList p=L;
if(i<1) /* i值不合法 */
return ERROR;
while(j<i&&p) /* 没到第i个元素,也没到表尾 */
{
j++;
p=p->next;
}
if(j==i) /* 存在第i个元素 */
{
*e=p->data;
return OK;
}
else
return ERROR;
}
int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
{ /* 初始条件:线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) */
/* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int i=0;
LinkList p=L;
while(p)
{
i++;
if(compare(p->data,e)) /* 找到这样的数据元素 */
return i;
p=p->next;
}
return 0;
}
Status ListInsert(LinkList *L,int i,ElemType e)
{ /* 在不带头结点的单链线性表L中第i个位置之前插入元素e */
int j=1;
LinkList p=*L,s;
if(i<1) /* i值不合法 */
return ERROR;
s=(LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
s->data=e; /* 给s的data域赋值 */
if(i==1) /* 插在表头 */
{
s->next=*L;
*L=s; /* 改变L */
}
else
{ /* 插在表的其余处 */
while(p&&j<i-1) /* 寻找第i-1个结点 */
{
p=p->next;
j++;
}
if(!p) /* i大于表长+1 */
return ERROR;
s->next=p->next;
p->next=s;
}
return OK;
}
Status ListDelete(LinkList *L,int i,ElemType *e)
{ /* 在不带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */
int j=1;
LinkList p=*L,q;
if(i==1) /* 删除第1个结点 */
{
*L=p->next; /* L由第2个结点开始 */
*e=p->data;
free(p); /* 删除并释放第1个结点 */
}
else
{
while(p->next&&j<i-1) /* 寻找第i个结点,并令p指向其前驱 */
{
p=p->next;
j++;
}
if(!p->next||j>i-1) /* 删除位置不合理 */
return ERROR;
q=p->next; /* 删除并释放结点 */
p->next=q->next;
*e=q->data;
free(q);
}
return OK;
}
void ListTraverse(LinkList L,void(*vi)(ElemType))
{ /* 初始条件:线性表L已存在。操作结果:依次对L的每个数据元素调用函数vi() */
LinkList p=L;
while(p)
{
vi(p->data);
p=p->next;
}
printf("\n");
}
硬件堆栈架构层次上的堆栈通常被用以申请和访问内存。 硬件支持大多数CPU都有用作堆栈指针的寄存器。 堆疊的應用参考文献参见 |
Index:
pl ar de en es fr it arz nl ja pt ceb sv uk vi war zh ru af ast az bg zh-min-nan bn be ca cs cy da et el eo eu fa gl ko hi hr id he ka la lv lt hu mk ms min no nn ce uz kk ro simple sk sl sr sh fi ta tt th tg azb tr ur zh-yue hy my ace als am an hyw ban bjn map-bms ba be-tarask bcl bpy bar bs br cv nv eml hif fo fy ga gd gu hak ha hsb io ig ilo ia ie os is jv kn ht ku ckb ky mrj lb lij li lmo mai mg ml zh-classical mr xmf mzn cdo mn nap new ne frr oc mhr or as pa pnb ps pms nds crh qu sa sah sco sq scn si sd szl su sw tl shn te bug vec vo wa wuu yi yo diq bat-smg zu lad kbd ang smn ab roa-rup frp arc gn av ay bh bi bo bxr cbk-zam co za dag ary se pdc dv dsb myv ext fur gv gag inh ki glk gan guw xal haw rw kbp pam csb kw km kv koi kg gom ks gcr lo lbe ltg lez nia ln jbo lg mt mi tw mwl mdf mnw nqo fj nah na nds-nl nrm nov om pi pag pap pfl pcd krc kaa ksh rm rue sm sat sc trv stq nso sn cu so srn kab roa-tara tet tpi to chr tum tk tyv udm ug vep fiu-vro vls wo xh zea ty ak bm ch ny ee ff got iu ik kl mad cr pih ami pwn pnt dz rmy rn sg st tn ss ti din chy ts kcg ve
Portal di Ensiklopedia Dunia