一.栈的介绍
当我们对线性表的操作做出某种限定的时候,即为受限制的线性表,限定的同,线性表也会不同,限定的线性表主要表示为,栈和队列;
栈,也称堆栈,是一种限定的操作的线性结构。日常生活中常见栈的实例,例如,我们夏天逛超市时,可能会忍不住想买一瓶冰饮料喝,饮料放在冰柜里,可是,冰柜中放在靠外的饮料往往并不冰,而深处我们够不着的地方,才是我们想要的。这种情况类似于线性结构中的栈,其特点就是,只能从冰柜门将饮料放人,先放进冰柜的在最里面,只能最后拿出来,除此之外,还有坐电梯,洗碗,一摞书,交作业先交的放在下面。
栈的基本概念
栈:是一种特殊的线性表,对其操作限制在表的同端进行,具有 后进先出的特性,因此,栈又被称为后进先出LIFO(Last In First Out)表或先进后出 FILO (First In Last Out)表栈顶:指允许进行插人、删除操作的一端。通常用top来指示栈项元素的位置。
空栈:当表中没有元素时称为空栈。
栈底:指不允许进行操作的一一端,一般不需要指示。
二.顺序栈
1.顺序栈基本介绍
(1).栈是操作受限的线性表,其逻辑结构和线性表是一样的 ,因此栈的存储可以和一般线性表一样,主要有顺序栈和链栈,在实际使用中,大部分情况下,我们都使用顺序栈,这是因为在顺序栈中只允许在栈顶进行人栈和出栈工作,顺序表的插入删除时间复杂度高的缺点就不存在了,顺序存储又有实现容易,存储密度大等优点。
(2).栈的顺序存储结构简称顺序栈,和顺序表类似,顺序栈也用数组来存放栈中的元素,再设定一个整型变量来指示栈顶位置,通常这个变量设为top,称为栈顶指针。
2.顺序栈的基本运算
(1).顺序栈的基本运算包括栈的初始化、判栈空、判栈满、进栈、出栈、取栈顶元素等操作,这里仅给出栈的初始化、进栈和出栈的操作算法,请读者自行给出判断栈空、判断栈满、取栈顶元素等函数。
(2).若栈的大小为最大为10,下标从0开始,栈空时栈顶指针指向一1,栈满时顶指针指向9(即:最大值- 1)。
如图展示:
三.链栈
采用链表作为存储结构的栈及链栈,与链表相似,也可以说是被受限制的链表。通常为了方便操作附设了一个头节点是与链表的不同之处;
链栈在插入和删除操作仅限于表头位置进行,所以,栈顶就是表头指针;
四.顺序栈与链栈代码展示
(1).顺序栈代码:(入栈与出栈)
在这里插入代码片:
#include <iostream>
#include <stdlib.h>
using namespace std;
#define maxsize 100 //顺序栈最大的存储空间
#define NULL 0
#define OK 1
#define ERR 0
typedef int ElemType; //顺序栈存储元素的类型
typedef struct
{
ElemType data[maxsize];
int top; //top栈顶元素,top实际并不是指针类型,存放的是栈顶元素的下标
}SqStack;
SqStack* InitSqStack() //顺序栈的初始化
{
SqStack* s;
s = (SqStack*)malloc(sizeof(SqStack)); //申请顺序栈的空间
if (!s)
{
return NULL; //申请失败返回0
}
else
{
s->top = -1; //申请成功设置为空栈,这样初始化成功
return s;
}
}
SqStack* AssignStack(SqStack *s) //顺序栈的输入
{
int i, lenghth;
cout << "请输入顺序栈的长度" << endl; //输入栈的长度
cin >> lenghth;
cout << "请根据设定的长依次输入顺序栈的元素" << endl;
for (int i = 0; i < lenghth; i++)
{
cin >> s->data[i]; //输入栈的元素
s->top++; //栈顶不断向后移动
}
return s;
}
//顺序栈的插入
//将一个新的元素加入栈中,通常称为入栈和压栈
//算法思路:
//1.判断栈是否满,如果栈满了,给出提示,出错返回
//2.栈顶加1
//3.新元素赋值给栈顶
//4.完成返回
int Push(SqStack* s, ElemType x)
{
if (s->top == maxsize - 1) //判断栈是否满了
{ //可以改改define的值,这样看看程序会不会出错
return ERR;
}
else
{
s->top++; //栈顶加1
s->data[s->top] = x; //将新元素的值赋值新栈顶
return OK;
}
}
//顺序栈的删除(出栈)
//将栈顶的元素删除
//算法思路:
//1.判断栈是否为空,若是空栈,则没有元素出栈,给出提示出错返回
//2.将栈顶元素赋值给x指针所指向的变量
//3.栈顶指针减1
//4.完成返回
int delepop(SqStack *s,ElemType *u)
{
if (s->top == -1)
{
cout << "此栈为空栈" << endl; //判断是否为空栈(插入的就判断是否已经满了,删除判断是否为空)
return ERR;
}
else
{
*u = s->data[s->top]; //将栈的元素赋值给一个新元素指针存着,之后在栈顶减一
s->top--; //其实这个函数还是在这个数组中,但它不在这个栈中,如果你加回来,在输出,还是能看到原来的数
cout << "出栈成功" << endl;
return OK;
}
}
//顺序栈的输出显示
void OputSqlist(SqStack *s)
{
int i;
cout << "顺序表长度为:" << s->top+1 << endl;
cout << "依次输出顺序表的元素:" << endl;
for (i = 0; i < s->top+1; i++)
{
cout << s->data[i]<<' '; //遍历顺序表,并打印在控制台上
}
}
int main()
{
SqStack* s;
ElemType x;
ElemType u;
int k;
s = InitSqStack(); //栈的初始化
if (s == 0)
{
cout << "顺序栈初始化失败" << endl;
}
else
{
cout << "顺序栈初始化成功" << endl;
AssignStack(s); //栈值的输入
OputSqlist(s); //栈值打印
cout << endl;
cout << "请输入需要入栈的元素:" << endl;
cin >> x;
k = Push(s, x); //新栈值,入栈
if (k == 0)
{
cout << "空间已经满了,无法压栈" << endl;
}
else
{
cout << "入栈成功" << endl;
OputSqlist(s);
delepop(s, &u); //栈顶值,出栈
OputSqlist(s);
}
}
return 0;
}
(2).链栈的入栈与出栈(这里的内容,基本与基本链表差不多,所以注释先不写了,只不过上一期用的是尾插法,而链栈用的是头插法的思路,很简单的)
在这里插入代码片:
#include <iostream>
using namespace std;
#define OK 1
#define ERR 0
typedef int Elemtype;
typedef struct SNode
{
Elemtype data;
struct SNode* next;
}Linklist;
Linklist *CreatNode()
{
Linklist* S;
S = (Linklist*)malloc(sizeof(Linklist));
S->next = NULL;
return S;
}
int StackEmpty(Linklist* S)
{
if (!S->next)
{
cout << "链栈为空" << endl;
return OK;
}
else
{
cout << "链栈不为空" << endl;
return ERR;
}
}
void InserStack(Linklist* S)
{
Linklist* p;
char flag = 'y';
cout << "获取空间成功" << endl;
while (flag == 'y' || flag == 'Y')
{
p = (Linklist*)malloc(sizeof(Linklist));
cout << "请输入需要入栈的元素" << endl;
cin >> p->data;
p->next = S->next;
S->next = p;
getchar();
cout << "请问还需要继续输入吗?(摁下 'y'或者‘Y’)" << endl;
cin >> flag;
}
}
int PushStack(Linklist* S, Elemtype x)
{
Linklist* p;
p = (Linklist*)malloc(sizeof(Linklist));
if (!p)
{
return ERR;
}
p->data = x;
p->next = S->next;
S->next = p;
}
int Popstack(Linklist* S, Elemtype *x)
{
Linklist* p;
if (StackEmpty(S))
{
return ERR;
}
p = S->next;
S->next = p->next;
(*x) = p->data;
free(p);
return OK;
}
void OutputNode(Linklist* S)
{
Linklist* p;
int i;
p = S->next;
while (p != NULL)
{
cout << p->data<<" ";
p = p->next;
}
}
int main()
{
Linklist* S = CreatNode();
Elemtype k,u;
StackEmpty(S);
InserStack(S);
cout << "栈中的元素是:"<< endl;
OutputNode(S);
cout << endl;
cout << "请输入在栈顶插入的元素:" << endl;
cin >> k;
PushStack(S, k);
cout << "栈中的元素是:" << endl;
OutputNode(S);
cout << endl;
cout << "栈顶出栈的显示:" << endl;
Popstack(S,&u);
cout << endl;
cout << "栈中的元素是:" << endl;
OutputNode(S);
return 0;
}