栈文档之共享栈
Posted 二木成林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈文档之共享栈相关的知识,希望对你有一定的参考价值。
共享栈
定义
概念
共享栈是顺序栈的变种。利用栈底位置相对不变的特性,可以让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延申,如图所示:
其中两个栈的栈顶指针都指向栈顶元素。top0=-1
时表示 0 号栈为空,top1=MAXSIZE
时表示 1 号栈为空(这是设定,因为栈顶指针存储的是下标,而 -1
和 MAXSIZE
都表示不合法的下标,所以用来指定初始栈空条件)。当两个栈顶指针相邻(即 top1 - top0 = 1
)时,判断栈满。
共享栈能够更加有效地利用存储空间,两个栈的空间相互调节,只会在整个存储空间被栈满时才会发生上溢,存取数据的时间复杂度仍为 O(1)
。
我们将共享栈中左边的顺序栈称为 0 号栈,右边的顺序栈称为 1 号栈。注意,这仅是一个区分的称呼而已。
结构体
共享栈的结构体跟顺序栈的结构体定义类似,只是共享栈多一个栈顶指针变量。关于结构体有以下两种形式:
- ①两个整型变量
top0
和top1
来分别存储 0 号和 1 号栈的栈顶指针。
/**
* 共享栈结构体定义
*/
typedef struct
/**
* 数据域,存储栈中元素
*/
int data[MAXSIZE];
/**
* 指针域,记录 0 号栈的栈顶指针
*/
int top0;
/**
* 指针域,记录 1 号栈的栈顶指针
*/
int top1;
SharedStack;
- ②用一个长度为
2
的整型数组来分别存储两个栈的栈顶指针,其中top[0]
存放 0 号栈的栈顶指针;top[1]
存储 1 号栈的栈顶指针。
/**
* 共享栈结构体定义
*/
typedef struct
/**
* 数据域,存储栈中元素
*/
int data[MAXSIZE];
/**
* 指针域,记录 0 号栈和 1 号栈的栈顶指针
*/
int top[2];
SharedStack;
特点
共享栈的特点如下:
- 共享栈是两个顺序栈共享一个一维数组的空间。
- 其中两个顺序栈的栈底位置不变,因为是将两个栈的栈底分别设置在共享空间的两端,两个栈的栈底分别向共享空间的中间延申。
- 当
top0==-1
时表示 0 号栈为空;当top1==MAXSIZE
表示 1 号栈为空。这是自定义的规定,因为-1
和MAXSIZE
都是数组下标不可设置的值。 - 当两个栈顶指针相邻时,则栈满。即两个栈的栈顶指针之差的绝对值为 1 表示栈满。
- 其中 0 号栈进栈时是栈顶指针
top0
先加一再赋值;其中 1 号栈进栈时是栈顶指针top1
先减一再赋值。因为top0
是从-1
往后移动,所以是增加;而top1
是从MAXSIZE
向前移动,所以是减一。 - 其中 0 号栈出栈时是先取值再栈顶指针
top0
减一;其中 1 号栈出栈时是先取值再栈顶指针top1
加一。 - 共享栈是为了更有效地利用存储空间,两个栈的空间相互调节,只有在整个存储空间被占满时才会发生上溢。共享栈存储和取用数据的时间复杂度均为
O(1)
。
基本操作
注,完整代码请参考:
概述
共享栈的常见操作如下:
void init(SharedStack *stack)
:初始化共享栈,即将 0 号栈的栈顶指针置为-1
表示空栈,将 1 号栈的栈顶指针置为MAXSIZE
表示空栈。其中stack
表示未初始化的共享栈。int isEmpty(SharedStack stack, int NUM)
:判断共享栈是否为空,如果为空则返回 1,否则返回 0 表示非空。其中stack
表示共享栈。如果共享栈为空则返回 1,否则返回 0。int isFull(SharedStack stack)
:判断共享栈是否已满。其中stack
表示共享栈。如果共享栈已满则返回 1,否则返回 0。int push(SharedStack *stack, int NUM, int ele)
:将元素压入共享栈中的指定序号栈中。其中stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号;ele
表示待入栈元素值。如果栈已满则不能入栈,返回 0 表示入栈失败,返回 1 表示入栈成功。int pop(SharedStack *stack, int NUM, int *ele)
:将元素从共享栈中的指定序号栈中的栈顶元素出栈。其中stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号;ele
用来存储出栈的元素值。如果栈为空则不能出栈,返回 0 表示出栈失败,返回 1 表示出栈成功。int getTop(SharedStack stack, int NUM, int *ele)
:获取共享栈中指定序号栈的栈顶元素。其中stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号;ele
用来存储出栈的元素值。如果栈为空则不能获取栈顶元素,返回 0 表示获取栈顶元素失败,返回 1 表示获取栈顶元素成功。int size(SharedStack stack, int NUM)
:获取共享栈中指定序号栈的元素个数。其中stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号。返回指定序号栈中的元素个数。void print(SharedStack stack, int NUM)
:打印指定序号栈中的所有元素。其中stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号。void clear(SharedStack *stack, int NUM)
:清空指定序号栈中的所有元素。其中stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号。
init
初始化共享栈,即初始化 0 号栈和 1 号栈。
实现步骤:
- 将 0 号栈的栈顶指针置为
-1
。 - 将 1 号栈的栈顶指针置为
MAXSIZE
。
实现代码如下:
/**
* 初始化共享栈
* @param stack 未初始化的共享栈
*/
void init(SharedStack *stack)
// 1.需要同时初始化 0 号栈和 1 号栈
// 1.1 将 0 号栈的栈顶指针指向 -1,表示 0 号栈是空栈
stack->top[0] = -1;
// 1.2 将 1 号栈的栈顶指针指向 MAXSIZE,表示 1 号栈是空栈
stack->top[1] = MAXSIZE;
isEmpty
判断共享栈中指定序号栈是否为空。
实现步骤:
- 如果 0 号栈的栈顶指针为
-1
则表示 0 号栈空。 - 如果 1 号栈的栈顶指针为
MAXSIZE
表示 1 号栈空。
实现代码如下:
/**
* 判断指定序号的栈是否是空栈
* @param stack 共享栈
* @param NUM 栈序号,只能传入 0 或者 1
* @return 如果指定栈是空栈则返回 1,否则返回 0 表示非空栈
*/
int isEmpty(SharedStack stack, int NUM)
if (NUM == 0)
// 0 号栈为空栈的条件是,栈顶指针指向 -1
return stack.top[0] == -1;
else if (NUM == 1)
// 1 号栈为空栈的条件是,栈顶指针指向 MAXSIZE
return stack.top[1] == MAXSIZE;
else
// 随便返回一个数,表示传入的序号不合法
return -MAXSIZE;
isFull
判断共享栈是否已满。
实现步骤:
- 判断 0 号栈和 1 号栈的栈顶指针之差的绝对值是否为 1,如果为 1 则表示已满,否则不是满栈。
实现代码如下:
/**
* 判断共享栈是否是满
* @param stack 共享栈
* @return 如果是栈满则返回 1,否则返回 0 表示栈未满
*/
int isFull(SharedStack stack)
// 如果 0 号栈和 1 号栈的栈顶元素相邻,则表示栈已满
if (stack.top[1] - stack.top[0] == 1)
return 1;
else
return 0;
push
将元素压入共享栈中的指定序号栈中。其中 stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号;ele
表示待入栈元素值。如果栈已满则不能入栈,返回 0 表示入栈失败,返回 1 表示入栈成功。
实现步骤:
- 参数校验,如果共享栈满,则不能入栈,无论是几号栈。
- 如果要将元素压入 0 号栈,则先将 0 号栈的栈顶指针增一,再赋值。
- 如果要将元素压入 1 号栈,则先将 1 号栈的的栈顶指针减一,再赋值。
实现代码如下:
/**
* 将元素压入栈
* @param stack 共享栈
* @param NUM 栈序号,只能传入 0 或者 1
* @param ele 新元素
* @return 如果栈满则返回 0 表示入栈失败;入栈成功则返回 1
*/
int push(SharedStack *stack, int NUM, int ele)
// 0.参数校验,如果栈满则不能入栈
if (isFull(*stack))
return 0;
// 1.根据栈序号是 0 还是 1,来决定将元素存入哪个栈
// 1.1 将元素存入 0 号栈
if (NUM == 0)
// 1.1.1 先移动 0 号栈的栈顶指针。由于 0 号栈是从 -1 开始的,所以栈顶指针是往后增
stack->top[0]++;
// 1.1.2 再赋值
stack->data[stack->top[0]] = ele;
// 1.2 将元素存入 1 号栈
else if (NUM == 1)
// 1.2.1 先移动 1 号栈的栈顶指针。由于 1 号栈是从 MAXSIZE 开始的,所以栈顶指针是往前减
stack->top[1]--;
// 1.2.2 再赋值
stack->data[stack->top[1]] = ele;
return 1;
pop
将元素从共享栈中的指定序号栈中的栈顶元素出栈。其中 stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号;ele
用来存储出栈的元素值。如果栈为空则不能出栈,返回 0 表示出栈失败,返回 1 表示出栈成功。
实现步骤:
- 参数校验,如果指定序号栈是空栈,则不能出栈。
- 如果要将 0 号栈的栈顶元素出栈,先取出 0 号栈的栈顶元素,再将栈顶指针减一,表示删除 0 号栈的栈顶元素。
- 如果要将 1 号栈的栈顶元素出栈,先取出 1 号栈的栈顶元素,再将栈顶指针加一,表示删除 1 号栈的栈顶元素。
实现代码如下:
/**
* 将元素出栈
* @param stack 共享栈
* @param NUM 栈序号,只能传入 0 或者 1
* @param ele 用来保存出栈元素
* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功
*/
int pop(SharedStack *stack, int NUM, int *ele)
// 0.参数校验,如果任何一个栈栈空则不能出栈
if (isEmpty(*stack, NUM))
return 0;
// 1.根据栈序号来决定将哪个栈的栈顶元素出栈
// 1.1 如果要将 0 号栈的栈顶元素出栈
if (NUM == 0)
// 1.1.1 用 ele 保存 0 号栈的栈顶元素
*ele = stack->data[stack->top[0]];
// 1.1.2 移动栈顶指针删除元素
stack->top[0]--;
// 1.2 如果要将 1 号栈的栈顶元素出栈
else if (NUM == 1)
// 1.2.1 用 ele 保存 1 号栈的栈顶元素
*ele = stack->data[stack->top[1]];
// 1.2.2 移动栈顶指针删除元素
stack->top[1]++;
return 1;
getTop
获取共享栈中指定序号栈的栈顶元素。其中 stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号;ele
用来存储出栈的元素值。如果栈为空则不能获取栈顶元素,返回 0 表示获取栈顶元素失败,返回 1 表示获取栈顶元素成功。
实现步骤:
- 参数校验,如果共享栈中指定序号栈为空则不能获取到栈顶元素。
- 如果要获取 0 号栈的栈顶元素,则直接取出 0 号栈的栈顶指针所指向的元素。
- 如果要获取 1 号栈的栈顶元素,则直接取出 1 号栈的栈顶指针所指向的元素。
实现代码如下:
/**
* 获取指定序号栈的栈顶元素,但不出栈
* @param stack 共享栈
* @param NUM 栈序号,只能传入 0 或者 1
* @param ele 用来保存栈顶元素
* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功
*/
int getTop(SharedStack stack, int NUM, int *ele)
// 0.参数校验,如果任何一个栈栈空则不能出栈
if (isEmpty(stack, NUM))
return 0;
// 1.用 ele 保存栈顶元素
// 1.1 用 ele 保存 0 号栈的栈顶元素
if (NUM == 0)
*ele = stack.data[stack.top[0]];
// 1.2 用 ele 保存 1 号栈的栈顶元素
else if (NUM == 1)
*ele = stack.data[stack.top[1]];
return 1;
size
获取共享栈中指定序号栈的元素个数。其中 stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号。返回指定序号栈中的元素个数。
实现步骤:
- 如果要获取 0 号栈的元素个数,则只需要将栈顶指针加一的和,就是 0 号栈的元素个数。
- 如果要获取 1 号栈的元素个数,则需要将
MAXSIZE
减去 1 号栈的栈顶指针,就是 1 号栈的元素个数。
实现代码如下:
/**
* 获取共享栈中指定序号栈的元素个数
* @param stack 共享栈
* @param NUM 栈序号,只能传入 0 或者 1
* @return 指定序号栈的元素个数
*/
int size(SharedStack stack, int NUM)
// 变量,记录栈中结点个数
int len = 0;
// 1.获取指定序号栈的元素个数
// 1.1 获取 0 号栈的元素个数
if (NUM == 0)
// 下标从 0 开始,所以元素个数就是下标加一
len = stack.top[0] + 1;
// 1.2 获取 1 号栈的元素个数
else if (NUM == 1)
// 1 号栈的元素从后往前,所以计算栈的元素个数是 MAXSIZE 减去 1 号栈的栈顶指针
len = MAXSIZE - stack.top[1];
return len;
print
打印指定序号栈中的所有元素。其中 stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号。
实现步骤:
- 如果要打印 0 号栈中的所有元素,则从 0 号栈的栈顶元素,开始向 0 号栈的栈底遍历所有元素。注意,循环变量是逐步减一的。
- 如果要打印 1 号栈中的所有元素,则从 1 号栈的栈顶元素,开始向 1 号栈的栈底遍历所有元素。注意,循环变量是逐步增一的。
实现代码如下:
/**
* 打印指定序号栈中的所有元素
* @param stack 共享栈
* @param NUM 栈序号,只能传入 0 或者 1
*/
void print(SharedStack stack, int NUM)
printf("[");
// 变量,记录栈顶指针
int top;
if (NUM == 0)
top = stack.top[0];
for (int i = top; i >= 0; i--)
printf("%d", stack.data[i]);
if (i != 0)
printf(", ");
else if (NUM == 1)
top = stack.top[1];
for (int i = top; i < MAXSIZE; i++)
printf("%d", stack.data[i]);
if (i != MAXSIZE - 1)
printf(", ");
printf("]\\n");
clear
清空指定序号栈中的所有元素。其中 stack
表示共享栈;NUM
表示栈序号,只能是 0 号或者 1 号。
实现步骤:
- 如果要清空 0 号栈,只需要将 0 号栈的栈顶指针置为
-1
。不需要将 0 号栈的已有元素重置为某个值。 - 如果要清空 1 号栈,只需要将 1 号栈的栈顶指针置为
MAXSIZE
。不需要将 1 号栈的已有元素重置为某个值。
实现代码如下:
/**
* 清空 0 号栈的所有元素
* @param stack 共享栈
* @param NUM 栈序号,只能传入 0 或者 1
*/
void clear(SharedStack *stack, int NUM)
if (NUM == 0)
// 直接将 0 号的栈顶指针指向 -1,就表示是空栈
stack->top[0] = -1;
else if (NUM == 1)
// 直接将 1 号的栈顶指针指向 MAXSIZE,就表示是空栈
stack->top[1] = MAXSIZE;
附录
附录一:初始版本
初始版本代码中 0 号和 1 号的入栈出栈操作是在不同函数中,而在上面代码,0 号和 1号的入栈或出栈操作是在同一个函数中,仅通过参数 NUM
来区分是哪个栈。其中共享栈的初始版本代码,如下:
#include<stdio.h>
/**
* 共享栈能存储的最大元素个数
*/
#define MAXSIZE 100
/**
* 共享栈结构体定义
*/
typedef struct
/**
* 数据域,存储栈中元素
*/
int data[MAXSIZE];
/**
* 指针域,记录 0 号栈的栈顶指针
*/
int top0;
/**
* 指针域,记录 1 号栈的栈顶指针
*/
int top1;
SharedStack;
/**
* 初始化共享栈
* @param stack 未初始化的共享栈
*/
void init(SharedStack *stack)
// 1.需要同时初始化 0 号栈和 1 号栈
// 1.1 将 0 号栈的栈顶指针指向 -1,表示 0 号栈是空栈
stack->top0 = -1;
// 1.2 将 1 号栈的栈顶指针指向 MAXSIZE,表示 1 号栈是空栈
stack->top1 = MAXSIZE;
/**
* 判断 0 号栈是否是空栈
* @param stack 共享栈
* @return 如果是空栈则返回 1,否则返回 0 表示非空栈
*/
int isEmptyStack0(SharedStack *stack)
// 0 号栈为空栈的条件是,栈顶指针指向 -1
if (stack->top0 == -1)
return 1;
else
return 0;
/**
* 判断 1 号栈是否是空栈
* @param stack 共享栈
* @return 如果是空栈则返回 1,否则返回 0 表示非空栈
*/
int isEmptyStack1(SharedStack *stack)
// 1 号栈为空栈的条件是,栈顶指针指向 MAXSIZE
if (stack->top1 == MAXSIZE)
return 1;
else
return 0;
/**
* 判断共享栈是否是满
* @param stack 共享栈
* @return 如果是栈满则返回 1,否则返回 0 表示栈未满
*/
int isFull(SharedStack *stack)
// 如果 0 号栈和 1 号栈的栈顶元素相邻,则表示栈已满
if (stack->top1 - stack->top0 == 1)
return 1;
else
return 0;
/**
* 将元素压入 0 号栈
* @param stack 共享栈
* @param ele 新元素
* @return 如果栈满则返回 0 表示入栈失败;入栈成功则返回 1
*/
int pushStack0(SharedStack *stack, int ele)
// 0.参数校验,如果栈满则不能入栈
if (isFull(stack))
return 0;
// 1.由于 0 号栈是从 -1 开始的,所以栈顶指针是往后增
stack->top0++;
// 2.栈顶指针增加后,将新元素填入到栈顶指针指向的位置
stack->data[stack->top0] = ele;
return 1;
/**
* 将元素压入 1 号栈
* @param stack 共享栈
* @param ele 新元素
* @return 如果栈满则返回 0 表示入栈失败;入栈成功则返回 1
*/
int pushStack1(SharedStack *stack, int ele)
// 0.参数校验,如果栈满则不能入栈
if (isFull(stack))
return 0;
// 1.由于 1 号栈是从 MAXSIZE 开始的,所以栈顶指针是往前减
stack->top1--;
// 2.栈顶指针变化后,将新元素填入到栈顶指针指向的位置
stack->data[stack->top1] = ele;
return 1;
/**
* 将元素从 0 号栈出栈
* @param stack 共享栈
* @param ele 用来保存出栈元素
* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功
*/
int popStack0(SharedStack *stack, int *ele)
// 0.参数校验,如果 0 号栈空则不能出栈
if (stack->top0 == -1)
return 0;
// 1.用 ele 保存 0 号栈的栈顶元素
*ele = stack->data[stack->top0];
// 2.然后栈顶指针减一,表示已经删除栈顶元素
stack->top0--;
return 1;
/**
* 将元素从 1 号栈出栈
* @param stack 共享栈
* @param ele 用来保存出栈元素
* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功
*/
int popStack1(SharedStack *stack, int *ele)
// 0.参数校验,如果 1 号栈空则不能出栈
if (stack->top1 == MAXSIZE)
return 0;
// 1.用 ele 保存 1 号栈的栈顶元素
*ele = stack->data[stack->top1];
// 2.然后栈顶指针加一,表示已经删除 1 号栈的栈顶元素
stack->top1++;
return 1;
/**
* 获取 0 号栈的栈顶元素,但不出栈
* @param stack 共享栈
* @param ele 用来保存栈顶元素
* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功
*/
int getTop0(SharedStack *stack, int *ele)
// 0.参数校验,如果 0 号栈空则不能出栈
if (stack->top0 == -1)
return 0;
// 1.用 ele 保存 0 号栈的栈顶元素
*ele = stack->data[stack->top0];
return 1;
/**
* 获取 1 号栈的栈顶元素,但不出栈
* @param stack 共享栈
* @param ele 用来保存栈顶元素
* @return 如果栈空则返回 0 表示出栈失败;否则返回 1 表示出栈成功
*/
int getTop1(SharedStack *stack, int *ele)
// 0.参数校验,如果 1 号栈空则不能出栈
if (stack->top1 == MAXSIZE)
return 0;
// 1.用 ele 保存 1 号栈的栈顶元素
*ele = stack->data[stack->top1];
return 1;
/**
* 获取 0 号栈中的元素个数
* @param stack 共享栈
* @return 0 号栈的元素个数
*/
int sizeStack0(SharedStack *stack)
// 下标从 0 开始,所以元素个数就是下标加一
return stack->top0 + 1;
/**
* 获取 1 号栈中的元素个数
* @param stack 共享栈
* @return 1 号栈的元素个数
*/
int sizeStack1(SharedStack *stack)
// 1 号栈的元素从后往前,所以计算栈的元素个数是 MAXSIZE 减去 1 号栈的栈顶指针
return MAXSIZE - stack->top1;
/**
* 共享栈中的元素总个数
* @param stack 共享栈
* @return 元素总个数
*/
int size(SharedStack *stack)
int len0 = stack->top0 + 1;
int len1 = MAXSIZE - stack->top1;
// 即 0 号栈和 1 号栈的元素个数之和
return len0 + len1;
/**
* 打印 0 号栈中的所有元素
* @param stack 共享栈
*/以上是关于栈文档之共享栈的主要内容,如果未能解决你的问题,请参考以下文章