栈(stack)是限定仅在表尾进行插入或删除操作的线性表。
栈是遵从后进先出(LIFO)原则的线性表,包括顺序栈和链栈。
栈可用于数制(进制)转换、括号匹配、表达式求值,在简易模拟计算器的四则混合运算中可采用栈实现对表达式的求值及括号匹配问题。
下面展现了两种对顺序栈的操作,主要是结构体和指针运用的不同。
1.对于LinkList L: L是指向定义的node结构体的指针,可以用->运算符来访问结构体成员,即L->elem,而(*L)就是个Node型的结构体,可以用点运算符访问该结构体成员,即(*L).elem。
2.对于LinkList *L:L是指向定义的Node结构体指针的指针,所以(*L)是指向Node结构体的指针,可以用->运算符来访问结构体成员,即(*L)->elem。(**L)就是Node型结构体,所以可以用点运算符来访问结构体成员,即(**L).elem。
在链表(链栈)操作中,我们常常要用链表变量作为函数的参数,这时,用LinkList L还是LinkList *L就很值得考虑,用不好可能函数就会出现逻辑错误,其准则是:
如果函数会改变指针L的值,而你希望函数结束调用后保存L的值,那就要用LinkList *L,这样,向函数传递的就是指针的地址,结束调用后,自然就可以去改变指针的值。
如果函数只需修改指针所指向的内容,而不会更改指针的值,那么用LinkList L就可以。
除了LinkList L与LinkList *L以外,LinkList *L与LinkList &L也是容易混淆的,它们的区别主要是:
3.LinkList *L
我们已经知道了 LinkList L 定义的是指向结构体的指针,所以 LinkList *L 就是定义了指向结构体的指针的指针,也就是二级指针。在这里可以通过指向运算符->访问结构体,即( L )-> data , 而** L 才是指结构体本身,可以通过操作运算符 . ,对结构进行访问,即(** L ). data 。
4.LinkList & L
这里可以这样理解LinkList & L: & L 是取指针 L 自己的地址,& L 就是将 L 自己的地址传给形参中,且这个变量(形参)是指针型。这时,形参实际上就是实参,形参怎么变,实参怎么变。
一.顺序栈的实现
#include<bits/stdc++.h>
using namespace std;
typedef int status;
const int Maxsize=100;
//顺序栈定义
typedef struct
{
int *base;
int *top;
int stacksize;
}SqStack;
//初始化
status InitStack(SqStack &s)
{
s.base=(int*)malloc(Maxsize*sizeof(int));
if(!s.base)exit(OVERFLOW);
s.top=s.base;
s.stacksize=Maxsize;
return 1;
}
//入栈
status PushStack(SqStack &s,int e)
{
if(s.top-s.base>=s.stacksize)
{
s.base=(int*)realloc(s.base,(s.stacksize+Maxsize)*sizeof(int));
if(!s.base)exit(OVERFLOW);
s.top=s.base+s.stacksize;
s.stacksize=s.stacksize+Maxsize;
}
*s.top=e;
*s.top++;
printf("元素%d入栈成功\n",e);
return 1;
}
//出栈
status PopStack(SqStack &s)
{
if(s.base==s.top)
{
printf("栈已空\n");
return 0;
}
else
{
int e;
e=*(s.top-1);
*s.top--;
printf("元素%d出栈成功\n",e);
return 1;
}
}
//取栈顶元素
status GettopStack(SqStack s)
{
if(s.base!=s.top)
printf("栈顶元素为%d\n",*(s.top-1));
else printf("栈已空\n");
return 1;
}
//栈中元素个数
status LenStack(SqStack s)
{
int len=0;
if(s.base==s.top)
printf("栈为空,没有元素\n");
else
{
while(s.base!=s.top)
{
s.top--;
len++;
}
printf("栈中有%d个元素\n",len);
}
return 1;
}
//菜单
void menu()
{
printf("1.入栈\n");
printf("2.出栈\n");
printf("3.取栈顶元素\n");
printf("4.栈中元素个数\n");
printf("5.退出\n");
}
int main()
{
SqStack s;
InitStack(s);
printf("栈初始化成功\n");
int choice;
while(1)
{
menu();
printf("请输入你要选择的功能:");
scanf("%d",&choice);
if(choice==5)break;
switch(choice)
{
case 1:
printf("请输入入栈元素:");
int e;
scanf("%d",&e);
PushStack(s,e);
break;
case 2:
PopStack(s);
break;
case 3:
GettopStack(s);
break;
case 4:
LenStack(s);
break;
default:
printf("输入无效选择\n");
}
}
return 0;
}
顺序栈除了定义两个指针:栈底和栈顶,还可以只定义一个栈顶指针实现,如下:
1.定义
typedef struct LNode
{
int data[Maxsize];
int top;
}SqStack;
2.初始化
SqStack *InitStack()
{
SqStack *s;
s=(SqStack *)malloc(sizeof(SqStack));
s->top=-1;
return s;
}
3.入栈
void PushStack(SqStack *s,int e)
{
if(s->top==Maxsize-1)
printf("栈已满\n");
else
{
s->top++;
s->data[s->top]=e;
printf("入栈成功\n");
}
}
4.出栈
int PopStack(SqStack *s)
{
int e;
if(s->top==-1)
printf("栈已空\n");
else
{
e=s->data[s->top];
s->top--;
printf("%d已出栈\n",e);
}
return 1;
}
5.取栈顶元素
int GettopStack(SqStack *s)
{
if(s->top==-1)
printf("栈已空\n");
else
printf("栈顶元素为:%d\n",s->data[s->top]);
return 1;
}
二.链栈的实现
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
int Max_SIZE=1e3+10;
//栈元素的节点
typedef struct LinkStackNode
{
int data;
LinkStackNode *next;
}LinkStackNode;
//栈的主体
typedef struct LinkStack
{
LinkStackNode *top;
int length;
}LinkStack;
LinkStack *initialize()//初始化链栈,创造头节点
{
LinkStack *p = new LinkStack;
p->length = 0;p->top = NULL;
return p;
}
int Isempty(LinkStack *p)//判断栈是否为空
{
if(p->length==0)
{
printf("栈为空\n");
return 1;
}
else
{
printf("栈不为空\n");
return 0;
}
}
int Isenough(LinkStack *p)//判断栈满
{
if(p->length==Max_SIZE) {
printf("栈已满\n");
return 1;
}
else
{
printf("栈未满\n");
return 0;
}
}
void Clear(LinkStack *p)//清空栈内所有元素
{
LinkStackNode *temp;
while(p->top != NULL)
{
temp=p->top;
p->top=p->top->next;
p->length--;
free(temp);
}
}
void Destroy(LinkStack *p)//栈的销毁
{
Clear(p);
free(p);
}
void *Push(LinkStack *p,int data)//入栈
{
if(!p) {printf("不存在栈!\n");exit(0);}
LinkStackNode *temp = new LinkStackNode;
temp->data=data;
temp->next=p->top;
p->top=temp;
p->length++;
}
void pop(LinkStack *p)//出栈 依次自上而下输出
{
if(!p) {
printf("不存在栈!\n");
}
int data;
LinkStackNode *temp=p->top;
data=temp->data;
printf("%d\n",data);
p->top=temp->next;
p->length--;
free(temp);
}
void top(LinkStack *p)//取栈顶元素(不弹出)
{
if(!p) {
printf("不存在栈!\n");
}
int data;
LinkStackNode *temp=p->top;
data=temp->data;
printf("栈顶元素=%d\n",data);
}
int main()
{
LinkStack *p=initialize();
int choice;
while(1)
{
printf("请输入你想要选择的功能:\n");
printf("1.入栈\n");
printf("2.出栈\n");
printf("3.栈空判断\n");
printf("4.栈满判断\n");
printf("5.获取栈顶元素\n");
printf("6.销毁栈 \n");
printf("7.退出程序\n");
printf("请输入你的选择:");
scanf("%d",&choice);
switch (choice) {
case 1:
int data;
printf("输入数据:\n");
scanf("%d",&data);
Push(p,data);
break;
case 2:
pop(p);
break;
case 3:
Isempty(p);
break;
case 4:
Isenough(p);
break;
case 5:
top(p);
break;
case 6:
Destroy(p);
break;
case 7:
exit(0);
default:
break;
}
}
return 0;
}