高一凡-数据结构第3章-栈与队列
3.1栈
3.1.1栈的数据结构
struct SqStack {
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;//栈的容量,可以看成当前栈可以最大存储多少的元素
};
3.1.2接口
接口 | 功能 |
---|---|
void InitStack(SqStack &S) | 初始化一个栈,主要包含内存的分配 |
void DestroyStack(SqStack &S) | 摧毁一个栈,主要包括内存的释放 |
void ClearStack(SqStack &S) | 清空一个栈,并不释放内存,而是隐藏和覆盖 |
Status StackEmpty(SqStack S) | 判空 |
int StackLength(SqStack S) | 返回栈长,元素个数,栈的规模 |
Status GetTop(SqStack S, SElemType &e) | 获取栈顶元素 |
void Push(SqStack &S, SElemType e) | 压栈 |
Status Pop(SqStack &S, SElemType &e) | 弹栈 |
void StackTraverse(SqStack S, void(*visit)(SElemType)) | 遍历 |
void print(SElemType e) | 自定义打印函数,用于传递函数指针 |
可以清晰的看出,需要对栈进行修改的接口,其形参都是引用形式,而只读形参不带&符号。
3.1.3实现
//1.初始化函数
void InitStack(SqStack &S)
{
S.base = (SElemType*)malloc(sizeof(SElemType)*STACK_INIT_SIZE);
//给栈底元素分配一个类似于数组空间的内存,对待base可以看成是数组的起始位置
//而top可以看成是最后我们插入进去的元素所在数组中的位置(最后一个)
if (!S.base)//分配不成功,退出
exit(OVERFLOW);//OVERFLOW宏定义,头文件中定义
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;//宏定义,将栈的规模设置成初始规模
}
//2.销毁一个栈
void DestroyStack(SqStack &S)
{
free(S.base);//只需要free掉分配给base的内存,所以,我们只对base指针操作
S.top = S.base = NULL;//指针置零
S.stacksize = 0;//规模置零
}
//3.清空一个栈
void ClearStack(SqStack &S)
{
S.top = S.base;//只是将栈顶元素的指针指到了栈底,隐藏了其他元素
}
//4.判空
Status StackEmpty(SqStack S)
{
return S.top == S.base;//判空,只是简单的判断栈内是否存在元素
//然而此处的元素只是我们希望用户可见的元素,并不是真正在内存空间中的元素
}
//5.返回栈长
int StackLength(SqStack S)
{
return S.top - S.base;//返回栈的规模,即当前存了多少元素
}
//6.获取栈顶
Status GetTop(SqStack S, SElemType &e)
{
if (S.top > S.base)//判空
{
e = *(S.top - 1);//解引用的是top-1,这与push操作中的代码有关
return OK;
}
else
{
return ERROR;
}
}
//6.压栈操作
void Push(SqStack &S, SElemType e)
{
//当栈的规模等于栈的容量的时候,我们必须要进行分配空间了
if (S.top - S.base == S.stacksize)
{
//用到的是一个relloc函数,它可以在保存之前内存中元素的基础之上,继续(追加)分配一块空间
S.base = (SElemType*)realloc(S.base, sizeof(SElemType)*(S.stacksize + STACK_INIT_SIZE));
if (!S.base)
exit(OVERFLOW);
S.top = S.base + S.stacksize;//分配完空间之后,栈底的地址可能已经变化了,所以加上相对的位置,回复原样
S.stacksize += STACK_INCEEMET;//增加栈的容量
}
*(S.top)++ = e;//栈顶永远是*(s.top-1),可以将top看成一个哨兵,防止溢出
}
//7.弹出操作
Status Pop(SqStack &S, SElemType &e)
{
if (StackEmpty(S))//如果栈为空的话,那么,不能再弹栈了
return ERROR;
e = *--S.top;//用了前--,因而栈顶向前移动一位
return OK;
}
//遍历选项,传入函数指针
void StackTraverse(SqStack S, void(*visit)(SElemType))
{
while (S.top > S.base)
{
visit(*S.base++);
}
printf("\n");
}
//简单的函数指针
void print(SElemType e)
{
printf("%d ", e);
}
VS2015实例代码包:
–未完待续