数据结构之栈(二)——栈的操作

栈的顺序存储结构


栈的顺序存储结构的定义

#include "stdafx.h"

#define MAXSIZE 100

//SElemType类型根据实际情况而定,这里假设为int
typedef int SElemType;

typedef struct
{
	SElemType data[MAXSIZE];
	//用于栈顶指针
	int top;
}SqStack;

进栈操作

//插入元素e为新的栈顶元素
bool Push(SqStack *S, SElemType e) {
	//栈满
	if (S->top == MAXSIZE - 1) {
		return false;
	}
	//栈顶指针增加1
	S->top++;
	//将新插入元素赋值给栈顶空间
	S->data[S->top] = e;
	return true;
}

出栈操作

//若栈不空,则删除S的栈顶元素,用e返回其值,并返回true,否则返回false
bool Pop(SqStack *S, SElemType *e) {
	if (S->top == -1)
		return false;
	//将要删除的栈顶元素赋值给e
	*e = S->data[S->top];
	//栈顶指针减一
	S->top--;
	return true;
}

时间复杂度

栈的入栈和出栈的时间复杂度是O(1)。

俩栈共享空间

数组有俩个端点,俩个栈有俩个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为栈的末端,即下标为数组长度n-1处。这样,俩个栈如果增加元素,就是俩端点向中间延伸。

俩栈共享空间的结构定义

//俩栈共享空间结构
typedef struct {
	SElemType data[MAXSIZE];
	//栈1栈顶指针
	int top1;
	//栈2栈顶指针
	int top2;
}SqDoubleStack;

俩栈共享空间的入栈操作

//插入元素e为新的栈顶元素
bool Push(SqDoubleStack *S, SElemType e, int stackNumber) {
	//栈已满,不能再push新元素
	if (S->top1 + 1 ==S->top2)
		return false;
	//栈1有元素进栈
	if (stackNumber == 1)
		//若栈1则先top1+1后给数组元素赋值
		S->data[++S->top1] = e;
	//栈2有元素进栈
	else if (stackNumber == 2)
		//若栈2则先top2-1后给数组元素赋值
		S->data[--S->top2] = e;
	return true;
}

俩栈共享空间的出栈操作

//若栈不空,则删除S的栈顶元素,用e返回其值,并返回true,否则返回false
bool Pop(SqDoubleStack *S, SElemType *e, int stackNumber) {
	if (stackNumber == 1) {
		if (S->top1 == -1) {
			//说明栈1已经是空栈,溢出
			return false;
		}
		//将栈1的栈顶元素出栈
		*e = S->data[S->top1--];
	}
	else if (stackNumber == 2) {
		if (S->top2 == MAXSIZE)
		{
			//说明栈2已经是空栈,溢出
			return false;
		}
		//将栈2的栈顶元素出栈
		*e = S->data[S->top2++];
	}
	return true;
}
使用这样的数据结构,通常都是针对俩个具有相同数据类型的栈的一个设计上的技巧,且俩个栈的空间需求有相反关系时,也就是一个栈增长时另一个栈在缩短的情况。

栈的链式存储结构

栈的链式存储结构,简称链栈。

链栈的结构定义

typedef struct StackNode {
	SElemType data;
	struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct LinkStack
{
	LinkStackPtr top;
	int count;
}LinkStack;

链栈的进栈操作

#include<stdlib.h>
//插入元素e为新的栈顶元素
bool Push(LinkStack *S, SElemType e) {
	LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
	s->data = e;
	//把当前的栈顶元素赋值给新结点的直接后继
	s->next = S->top;
	//将新的结点s赋值给栈顶指针
	S->top = s;
	S->count++;
	return true;
}

链栈的出栈操作

//若栈不空,则删除S的栈顶元素,用e返回其值,并返回true,否则返回false
bool Pop(LinkStack *S, SElemType *e) {
	LinkStackPtr p;
	if (S->count==0)
		return false;
	*e = S->top->data;
	//将栈顶结点赋值给p
	p = S->top;
	//使得栈顶指针下移一位,指向后一结点
	S->top = S->top->next;
	//释放结点p
	free(p);
	S->count--;
	return true;
}

时间复杂度

链栈的出栈和入栈操作的时间复杂度为O(1)。

顺序栈和链栈的区别

如歌栈的使用过程中元素变化不可预测,有时很小,有时非常大,那么最好是用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值