堆栈
抽象数据类型
(重定向自LIFO)
堆疊(stack)又稱為棧或堆叠,是计算机科學中的一種抽象資料型別,只允許在有序的線性資料集合的一端(稱為堆疊頂端,top)進行加入数据(push)和移除数据(pop)的運算。因而按照後進先出(LIFO, Last In First Out)的原理運作,堆疊常用一維数组或連結串列來實現。常與另一種有序的線性資料集合佇列相提並論。
「堆栈」的各地常用名稱 | |
---|---|
中国大陸 | 堆栈、栈 |
臺灣 | 堆疊 |
操作编辑
堆疊使用兩種基本操作:推入(压栈,push)和彈出(弹栈,pop):
- 推入:將資料放入堆疊頂端,堆疊頂端移到新放入的資料。
- 彈出:將堆疊頂端資料移除,堆疊頂端移到移除後的下一筆資料。
特点编辑
堆栈的基本特点:
- 先入后出,后入先出。
- 除头尾节点之外,每个元素有一个前驱,一个后继。
抽象定义编辑
以下是堆栈的VDM(Vienna Development Method):[1]
函数签名:
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
软件堆栈编辑
堆栈可以用数组和链表两种方式实现,一般为一个堆栈预先分配一个大小固定且较合适的空间并非难事,所以较流行的做法是Stack
结构下含一个数组。如果空间实在紧张,也可用链表实现,且去掉表头。
这里的例程是以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;elsereturn 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;}elsereturn 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;elsereturn 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;}elsereturn 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都有用作堆栈指针的寄存器。
堆疊的應用编辑
参考文献编辑
- ^ Jones: "Systematic Software Development Using VDM"
- ^ 2.0 2.1 高一凡. 《数据结构》算法实现及解析 2004年10月第2版. 西安: 西安电子科技大学出版社. ISBN 9787560611761 (中文).
参见编辑
🔥 Top keywords: Baike: 首页Special:搜索胖猫跳江事件背着善宰跑九龍城寨之圍城逆天奇案2璩静淚之女王歌手2024Energy (組合)新生 (网络剧)习近平匈牙利邊佑錫劉俊謙 (香港)金智媛神耆小子塞尔维亚金秀賢 (男演員)母亲节猩球崛起:王國誕生九龍寨城馴鹿寶貝家族榮耀之繼承者Seventeen (組合)六四事件不夠善良的我們张维为楊佩潔TripleS支配物种庆余年郭葦昀洪若潭命案金惠奫2024年英雄联盟季中邀请赛春色寄情人BABYMONSTER笑看風雲乘風2024排球少年!!角色列表破墓徐巧芯中华人民共和国中華民國打天下2WIND BREAKER—防風少年—习明泽排球少年!!彭丽媛磁暴ILLIT贾斯汀·比伯逆天奇案BOYNEXTDOOR猿人爭霸戰:猩凶革命張書偉我的婆婆怎麼那麼可愛我獨自升級怪獸8號謝坤達IVE (組合)與鳳行關於我轉生變成史萊姆這檔事角色列表黃道十二宮福建號航空母艦虽然不是英雄葉乃文五月天張員瑛草榴社区張文傑2024年花蓮地震极光香緹·摩爾迷宮飯呂家愷搜查班長1958日本劉德華海莉·鮑德溫蕭景鴻越位 (足球)葬送的芙莉蓮周處除三害 (電影)毛泽东願榮光歸香港林峯周雨彤伍允龍羅毓儀香港Baike: 分類索引沒有秘密猩球崛起:終極決戰角質層唐振剛柯佳嬿文化大革命