数据结构——栈

栈的基本概念

数据结构三要素——逻辑结构、数据的运算、存储结构(物理结构)

栈的定义

​ 栈(Stack)是只允许在一端进行插入或删除操作的线性表

  • 栈顶:允许插入和删除的一端
  • 栈底:不允许插入和删除的一端 。固定的
  • 空栈:不含任何元素的空表

特点:后进先出

(Last In First Out) 即LIFO

栈的基本操作

InitStack(&S) 初始化栈。构造一个空栈S,分配内存空间。

DestoryStack(&L) 销毁栈。销毁并释放栈S所占用的内存空间。

Push(&S,x) 进栈。若栈S未满,则将X加入是使之成为新栈顶。

Pop(&S,&x) 出栈。若栈S非空,则弹出栈顶元素,并用x返回。

GetTop(S,&x)读栈顶元素。若栈S非空,则用x返回栈顶元素。

n个不同元素进栈,出栈元素不同排列的个数为1/n+1Cn2n

上述公式成为卡特兰(Catalan)数,可采用数学归纳法证明。

顺序栈的定义

初始化操作
#define MaxSize 10 	//定义栈中元素的最大个数
typedef struct{
    ElemType data[MaxSize];			//静态数组存放栈中元素
    int top;						//栈顶指针
}SqStack;
void testStack(){
    SqStack S;						//声明一个顺序栈
    InitStack(S);
    
}
//判断栈是否为空  利用top的指向判断
bool StackEmpty(SqStack S){
    if(S.top == -1)
        return true;		//栈空
    else
        return false;		//非空
}
进栈操作(增)
#define MaxSize 10 			//定义栈中元素的最大个数
typedef struct{
    ElemType data[MaxSize];	//静态数组存放栈中元素
    int top;				//栈顶指针
}SqStack;
//新元素入栈
bool Push(SqStack &S,ElemType x){
    if(S.top == MaxSize -1)		//栈满,报错
        return false;
    S.data[++S.top];
    return ture;
}
出栈操作(删)
//出栈操作的删除,数据还残留在内存中,只是逻辑上删除了
#define MaxSize 10
typedef struct{
    ElemType data[MaxSize];
    int top;
}SqStack;
//出栈操作,将栈顶元素删除,并返回删除的值
bool Pop(SqStack &S,ElemType &x){
    if(S.top == -1)			//判断栈是否为空
        return false;
    x=S.data[S.top--];
    return ture;
}
读栈顶元素操作
#define MaxSize 10	
typedef struct{
    ElemType data[MaxSize];
    int top;
}SqStack;
//读栈顶元素
bool GetTop(SqStack S,ElemType &x){
    if(S.top == -1)
        return false;
    x=S.data[S.top];
    return true;
}

顺序栈的缺点:栈的大小不可变

共享栈

利用栈底位置相对不变的特性,可以让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸。

#define MaxSize 10
typedef struct{
    int data[MaxSize];
    int top0;
    int top1;
}ShStack;
//初始化栈
void InitStack(ShStack &S){
    S.top0 = -1;
    S.top1 = MaxSize;
}

//判断栈满的条件,top0 + 1 == top1

​ 两个栈的栈顶指针都指向栈顶元素,top0 = -1 时 0号栈为空,top1 == MaxSize 时 1号栈为空;仅党两个栈顶指针相邻(top1 - top0 == 1)时,判断为栈满。当0号栈进栈时,top0先加再赋值,1号栈进栈时top先减1再赋值;出栈时则刚好相反

​ 共享栈是为了更有效地利用存储空间,两个栈的空间相互调节,只有在整个存储空间被沾满时才发生上溢。其存取数据的时间复杂度均为O(1) ,所以对存取效率没有什么影响。

栈的链式存储实现

​ 采用链式存储的栈成为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。

typedef struct node{
    StackElementType data;
    struct node *next;
}LinkStackNode;
typedef LinkStackNode *LinkStack;

​ 采用链式存储,便于结点的插入与删除。链栈的操作与链表类似,入栈和出栈的操作都在链表的表头进行。对于带头结点和不带头结点的链栈,具体的实现会有所不同。

链栈的进栈操作
int Push(LinkStack top,StackElementType x){
    LinkStackNode *temp;
    temp = (LinkStackNode *)malloc(sizeof(LinkStackNode));
    if(temp == NULL)
        return -1;					//申请空间失败
    temp->data = x;
    temp ->next = temp->next;
}
链栈出栈操作
int Pop(LinkStack top,StackElementType *x){
    //将栈top的栈顶元素弹出,放到x所致的存储空间中
    LinkStackNode *temp;
    temp = top->next;
    if(temp == NULL)
        return -1;
    top->next = temp ->next;
    *x = temp -> data;
    free(temp); 		//释放存储空间
    return 1;			//表示出栈成功
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值