3.1-栈的顺序表示及栈的顺序储存表示
1.栈的定义:
在表尾进行插入和删除操作的线性表(仍然满足线性表的操作,只是在push和pop有些区别)
栈顶(top)允许插入和删除,另一端称栈底(bottom),不含任何数据元素的栈叫空栈。
栈:后进先出(last in first out)的线性表,简称LIFO结构。
栈的插入称为进栈,也称压栈,入栈。
栈的删除称为出栈,也称弹栈。
2.栈的抽象数据结构
因为栈本身就是一个线性表,所以线性表的操作特性它都具备,针对它的特殊性,在它的操作上可能会有一些变化。将进栈和出栈分别改名为push和pop。由于栈本身是一个线性表,所以线性表的顺序存储结构和链式存储结构同样适用于栈。
3.栈的顺序存储结构
栈的顺序存储结构,简称顺序栈。定义一个top变量来指示栈定元素在数组中的位置。若存储栈的长度为StackSize,则栈顶位置top必需小于StackSize。下标从0开始,当栈存在一个元素时候,top 等于 0 ,当栈为空栈时候,top 等于 -1。
栈的结构定义:
typedef struct SeqStack {
int data[MAXSIZE];
int top;
}SeqStack;
若现在有一个栈,StackSize为5,则普通栈、空栈、满栈的情况如下图所示:
4.进栈
void push(SeqStack* a, int e)
{
if (NULL == a)
{
cout << "栈未创建" << endl;
}
a->top++;
a->data[a->top] = e;
cout << "压入元素为:" << a->data[a->top] << endl;
}
5.出栈
void pop(SeqStack* a)
{
if (NULL == a)
{
cout << "栈未创建" << endl;
}
cout<<"弹出元素为:"<<a->data[a->top]<<endl;
a->top--;
}
总代码:
#include<iostream>//ZJJ数据据结构-栈3.1
using namespace std;
#define MAXSIZE 100
typedef struct SeqStack {
int data[MAXSIZE];
int top;
}SeqStack;
void initStack(SeqStack* a)
{
if (NULL == a)
{
cout << "栈未创建" << endl;
}
a->top = -1;
}
void push(SeqStack* a, int e)
{
if (NULL == a)
{
cout << "栈未创建" << endl;
}
a->top++;
a->data[a->top] = e;
cout << "压入元素为:" << a->data[a->top] << endl;
}
void pop(SeqStack* a)
{
if (NULL == a)
{
cout << "栈未创建" << endl;
}
cout<<"弹出元素为:"<<a->data[a->top]<<endl;
a->top--;
}
void showStack(SeqStack* a)
{
if (NULL == a)
{
cout << "栈未创建" << endl;
}
int i = a->top;
cout << "栈的剩余元素为:" << endl;
for (;i >= 0;i--)
{
cout << a->data[i] << endl;
}
}
int main()
{
SeqStack a;
initStack(&a);
push(&a,2);
push(&a, 5);
push(&a, 4);
push(&a, 88);
push(&a, 66);
pop(&a);
pop(&a);
pop(&a);
pop(&a);
showStack(&a);
}
运行如下:
栈的顺序存储结构
因为栈的本质是一个线性表,线性表有两种存储形式,那么栈也有分为
栈的顺序存储结构
栈的链式存储结构
特性:
最开始栈中不含有任何数据,叫做空栈,此时栈顶就是栈底。
然后数据从栈顶进入,栈顶栈底分离,整个栈的当前容量变大。
数据出栈时从栈顶弹出,栈顶下移,整个栈的当前容量变小。
定义:
typedef struct
{
ElemType* base;
ElemType* top;// 用于标注栈顶的位置
int stackSize;
}SqtSack;
这里定义了一个顺序存储的栈,它包含了三个元素base,top,stackSize。
base是指向栈底的指针变量,
top是指向栈顶的指针变量,
stackSize指示栈的当前可使用的最大容量。
使用ElemType* base 和 ElemType* top:
栈的操作
1.创建一个栈
代码实现:
void initStack(SqtSack* a)
{
a->base = (ElemType*)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if (!a->base)
{
exit(0);
}
a->top = a->base;// 最开始,栈顶就是栈底
a->stackSize = STACK_INIT_SIZE;
}
2.入栈操作
入栈操作又叫压栈操作,就是向栈中存放数据。
入栈操作要在栈顶进行,每次向栈中压入一个数据,top指针就要+1,直到栈满为止。
代码实现:
void Push(SqtSack* a, int e)
{
if (a->top - a->base >= a->stackSize) // 如果栈满,追加空间
{
a->base = (ElemType*)realloc(a->base, (a->stackSize + STACKINCREMENT) * sizeof(ElemType));
if (!a->base)
exit(0);
a->top = a->base + a->stackSize;// 设置栈顶
a->stackSize = a->stackSize + STACKINCREMENT;// 设置栈的最大容量
}
a->top++;
*(a->top) = e;
cout << "压入元素" << e << endl;
}
3.出栈操作
出栈操作就是在栈顶取出数据,栈顶指针随之下移的操作。
每当从栈内弹出一个数据,栈的当前容量就-1。
代码实现:
void pop(SqtSack* a)
{
if (a->base == a->top)// 栈已空
{
cout << "栈为空,无法弹出" << endl;
}
int e = *(a->top);
cout << "弹出元素为:" << e << endl;
a->top--;
}
栈的其他操作
1.清空一个栈
清空一个栈,就是将栈中的元素全部作废,但栈本身物理空间并不发生改变(不是销毁)。
思路:
我们只要将s->top的内容赋值为s->base即可,
这样s->base等于s->top,也就表明这个栈是空的了。
这个原理跟高级格式化只是但单纯地清空文件列表而没有覆盖硬盘的原理是一样的。
代码实现:
void ClearStack(SqtSack* a)
{
a->top = a->base;
cout << "栈已清空" << endl;
}
2.销毁一个栈
销毁一个栈与清空一个栈不同,销毁一个栈是要释放掉该栈所占据的物理内存空间,因此不要把销毁一个栈与清空一个栈这两种操作混淆。
代码实现:
void DestroyStack(SqtSack* a)
{
int i, len;
len = a->stackSize;
for (i = 0;i < len;i++)
{
free(a->base);
a->base++;
}
a->base = a->top = NULL;
a->stackSize = 0;
}
总代码:
#include<iostream>//ZJJ数据据结构-栈3.1
using namespace std;
#define MAXSIZE 10
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 100
typedef int ElemType;
typedef struct
{
ElemType* base;
ElemType* top;// 用于标注栈顶的位置
int stackSize;
}SqtSack;
void initStack(SqtSack* a)
{
a->base = (ElemType*)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if (!a->base)
{
exit(0);
}
a->top = a->base;// 最开始,栈顶就是栈底
a->stackSize = STACK_INIT_SIZE;
}
void Push(SqtSack* a, int e)
{
if (a->top - a->base >= a->stackSize) // 如果栈满,追加空间
{
a->base = (ElemType*)realloc(a->base, (a->stackSize + STACKINCREMENT) * sizeof(ElemType));
if (!a->base)
exit(0);
a->top = a->base + a->stackSize;// 设置栈顶
a->stackSize = a->stackSize + STACKINCREMENT;// 设置栈的最大容量
}
a->top++;
*(a->top) = e;
cout << "压入元素" << e << endl;
}
void pop(SqtSack* a)
{
if (a->base == a->top)// 栈已空
{
cout << "栈为空,无法弹出" << endl;
}
int e = *(a->top);
cout << "弹出元素为:" << e << endl;
a->top--;
}
void ClearStack(SqtSack* a)
{
a->top = a->base;
cout << "栈已清空" << endl;
}
void DestroyStack(SqtSack* a)
{
int i, len;
len = a->stackSize;
for (i = 0;i < len;i++)
{
free(a->base);
a->base++;
}
a->base = a->top = NULL;
a->stackSize = 0;
}
void ShowSqStack(SqtSack* a)
{
while (a->base != a->top)
{
cout << "栈的元素如下:" << endl;
cout << *(a->top) << endl;
a->top--;
}
}
int main()
{
SqtSack a;
initStack(&a);
int e;
cout << "输入压栈元素:(已输入999停止):" << endl;
cin >> e;
while (e != 999)
{
Push(&a, e);
cin >> e;
}
int q;
cout << "输出1进行弹栈操作:(以输入非1停止):" << endl;
cin >> q;
while (q == 1)
{
pop(&a);
cin >> q;
}
cout << "显示剩余栈的元素:" << endl;
ShowSqStack(&a);
ClearStack(&a);
system("pause");
DestroyStack(&a);
}
运行如下:
有无欠缺的,欢迎指正