一、栈的定义
在我们软件应用中,栈这种后进先出数据结构的应用是非常普遍的。比如你用浏览器上网时,不管什么浏览器都有一一个“后退”键,你点击后可以按访问顺序的逆序加载浏览过的网页。这就是栈的一个实际运用。
栈(stack)是仅限在表尾进行插入和删除的线性表
二、栈的顺序存储结构及代码实现
首先来看,栈的定义,这里是用数组实现栈,实际上用链表也可以实现,称为链式栈。
个人认为栈这部分重点在于看懂源码,动手实现起来是十分容易的。
#define datatype int
#define maxsize 1024
struct stack
{
datatype data[maxsize];
int top; //栈顶指针,1个元素就是0,2个就是1,以此类推
};
栈的初始化
首先要对这个结构体申请空间,然后传回该结构体的指针。
stack* init_stack() //返回类型为结构体指针的函数,初始化栈
{
stack* s;
s = (stack*)malloc(sizeof(stack));
if (!s)
{
cout << "空间不足,申请失败" << endl;
return NULL;
}
else
{
s->top = -1;//定义栈底为-1
return s;
}
}
入栈
要判断是否为栈满,然后将该元素压入。
int push(stack* s, datatype x) //入栈
{
if (s->top == maxsize - 1)
{
cout << "栈满,无法入栈" << endl;
return 0;
}
else
{
s->data[++s->top] = x;
return 1;
}
}
出栈
要判断是否为空栈,然后将该元素的值传给指针。(改变函数,返回该值也可以)。
int pop(stack* s, datatype* e) //出栈一个元素,并且用e返回其值
{
if (empty_stack(s))
{
cout << "栈空,无法出栈" << endl;
return 0;
}
else
{
*e = s->data[s->top--];
return 1;
}
}
判断空栈
这个很简单,看top值是否为-1即可。
int empty_stack(stack* s) //判断空栈
{
if (s->top == -1)
return 1; //为空
else
return 0;
}
获得栈顶元素
datatype gettop(stack* s)
{
if (empty_stack(s))
{
cout << "栈空,无栈顶元素" << endl;
return 0;
}
else
return s->data[s->top]; //返回栈顶
}
显示栈中所有元素,自上而下
void print_stack(stack* s) //显示所有元素
{
if (empty_stack(s))
{
cout << "栈空,无元素" << endl;
return;
}
else
{
for (int i = s->top; i >= 0; i--)
cout << s->data[i] << endl;
return;
}
}
至于返回栈中元素数量,这个可以定义一个函数返回top+1的值,即为元素个数。同理,删除这个栈中所有元素,只需要把top的值修改为-1即可。销毁栈,释放栈空间即可。在此不多赘述。
三、STL中的<stack>
这就十分简单了,函数都封装好了。C++中stl的stack(栈)以其他容器(deque默认,vector,list)作为底层数据结构而形成,只是修改了接口以满足栈的特性。
#include<stack>//栈
stack<int> s;//参数也是数据类型,这是栈的定义方式
s.empty()//如果栈为空返回true,否则返回false
s.size()//返回栈中元素的个数
s.pop()//删除栈顶元素但不返回其值
s.top()//返回栈顶的元素,但不删除该元素
s.push(X)//在栈顶压入新元素 ,参数X为要压入的元素
四、两栈共享空间
数组有两个端点,两个栈有两个栈底,让一个栈的栈底为0,另一个为栈的栈末端,即为数组大小的n-1处。这样,两个栈都增加元素都是往中间处靠拢。
栈1为空时,就是top1等于-1时,而当top2等于n时,即是栈2为空时,那什么时候栈满呢?
若栈2是空栈,栈1的top1等于n-1时,就是栈1满了。反之,当栈1为空栈时,top2 等于0时,为栈2满。但更多的情况,其实就是,两个指针之间相差1时,即top1 + 1 == top2 为栈满。
事实上,使用这样的数据结构,通常都是当两个栈的空间需求有相反关系时,也就是一个栈增长时另一个栈在缩短的情况。当然,这只是针对两个具有相同数据类型的栈的一一个设计上的技巧,如果是不相同数据类型的栈,这种办法不但不能更好地处理问题,反而会使问题变得更复杂。
定义
#define datatype int
#define maxsize 1024
typedef struct
{
datatype data[maxsize];
int top1;
int top2;
}doublestack;
压入元素
在压入和删除时,就只是需要判断一下对哪个栈操作而已。
int double_stack_push(doublestack* s, int stacknumber, datatype x)
//结构体指针,要操作的栈,要压入的元素
{
if (s->top1 + 1 == s->top2)
return 0; //栈满
else
{
if (stacknumber == 1)
s->data[++s->top1] = x; //先自加再赋值
else if(stacknumber==2)
s->data[--s->top2] = x;
return 1;
}
}
删除元素
int double_stack_pop(doublestack* s, int stacknumber,datatype* e)
{
if (stacknumber == 1)
{
if (s->top1 == -1)
return 0; //栈1为空
else
*e = s->data[s->top1--];//先出栈再自减
}
else if (stacknumber == 2)
{
if (s->top1 == maxsize)
return 0; //栈1为空
else
*e = s->data[s->top2++];//先出栈再自加
}
return 1;
}