链栈的操作大部分与单链表相似,只是在插入和删除上,特殊一些。
栈顶在链表的位置:栈只是用栈顶来进行插入和删除操作,单链表有头指针,栈顶指针也是必须的,因此可以将它们两个合二为一,所以最好的把栈顶放在单链表的头部。
由于已经有栈顶在头部,所以单链表中的头结点便失去了意义,通常对于链栈来说,是不需要头结点的
1.我们首先定义链栈结构:
struct StackNode//定义表格
{
SElemType data;//数据域
StackNode* next;//指针域
};
typedef struct StackNode* LinkStackPtr;//表格指针
struct LinkStack
{
LinkStackPtr top;//栈顶指针
int count;//记录栈中的数据个数
};
2.创建空栈(由于不需要头结点,也不像顺序栈一样要一开始开辟出总空间,所以空栈的创建很简单,只需要建立栈顶指针并初始化,再初始化用于计数的count即可)
int InitStack(LinkStack* S)//创建一个空栈
{
S->top = NULL;
S->count = 0;
return 1;
}
3.判断栈是否为空(链栈一般是不会出现栈满的情况的,所以我们只需要有判断链栈是否为空的函数即可)
int StackEmpty(LinkStack* S)//判断栈是否为空
{
if (S->count == 0)
return 0;
return 1;
}
当用于计数的count为0就说明此时链栈为空
4.进栈操作(链栈与链表主要的不同之处)
void Push(LinkStack* S, SElemType e)//进栈操作
{
LinkStackPtr g = new StackNode;//创建新的结点
g->data = e;//向新结点中输入数据
g->next = S->top;
S->top = g;
S->count++;
}
指针top是始终指向栈顶的所以当创建的新结点作为新的栈顶后,要让top指向它
5.输出栈中的内容(不对栈进行任何改变,只是利用while循环将其中的内容展示出来)
void printStack(LinkStack* S)//输出栈中的内容
{
int i;
LinkStackPtr p=S->top;//用来遍历栈
if (S->count==0)
{
cout << "栈为空" << endl;
return;
}
while (p)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
创建一个表格指针p初始化指向栈顶以后,便重栈顶开始遍历整个链栈
6.出栈操作(链栈与链表主要的不同之处)
void Pop(LinkStack* S, SElemType* e)//出栈操作
{
LinkStackPtr p;//定义一个表格指针来指向待删除的栈顶的位置
p = S->top;
*e = S->top->data;//将要出栈的值返回到指针e指向的空间,便于知道哪一个值进行了出栈
S->top = S->top->next;//指向栈顶的指针top向下移
delete(p);
S->count--;
}
定义SElemType* e指针是用于记录删除的数据内容,便于让用户知道删除了什么,与出栈操作关系不大。
7.清空栈(我们用new开辟的空间是在堆区中的,必须要我们自己将内存释放,要不然会造成内存泄漏)(注意new与delete malloc与free才是最佳拍档不能混用)
void ClearStack(LinkStack* S)//清空栈
{
int i;
LinkStackPtr p, q;//定义表格指针p,q来交替遍历
p = S->top;
while (p)
{
q = p->next;
delete(p);
p = q;
}
S->top = NULL;
S->count = 0;
cout << "栈清空完毕" << endl;
}
清空栈记得将计数变量count变为0,栈顶指针指向空。
全部代码展示:
头文件FUNC.h
#pragma once
#include<iostream>
using namespace std;
#include<ctime>;
#define SElemType int
struct StackNode//定义表格
{
SElemType data;//数据域
StackNode* next;//指针域
};
typedef struct StackNode* LinkStackPtr;//表格指针
struct LinkStack
{
LinkStackPtr top;//栈顶指针
int count;//记录栈中的数据个数
};
int InitStack(LinkStack* S);//创建一个空栈
int StackEmpty(LinkStack* S);//判断栈是否为空
void Push(LinkStack* S, SElemType e);//进栈操作
void printStack(LinkStack* S);//输出栈中的内容
void Pop(LinkStack* S, SElemType* e);//出栈操作
void ClearStack(LinkStack* S);//清空栈
源文件FUNC.cpp
#include"FUNC.h"
int InitStack(LinkStack* S)//创建一个空栈
{
S->top = NULL;
S->count = 0;
return 1;
}
int StackEmpty(LinkStack* S)//判断栈是否为空
{
if (S->count == 0)
return 0;
return 1;
}
void Push(LinkStack* S, SElemType e)//进栈操作
{
LinkStackPtr g = new StackNode;//创建新的结点
g->data = e;//向新结点中输入数据
g->next = S->top;
S->top = g;
S->count++;
}
void printStack(LinkStack* S)//输出栈中的内容
{
int i;
LinkStackPtr p=S->top;//用来遍历栈
if (S->count==0)
{
cout << "栈为空" << endl;
return;
}
while (p)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
void Pop(LinkStack* S, SElemType* e)//出栈操作
{
LinkStackPtr p;//定义一个表格指针来指向待删除的栈顶的位置
p = S->top;
*e = S->top->data;//将要出栈的值返回到指针e指向的空间,便于知道哪一个值进行了出栈
S->top = S->top->next;//指向栈顶的指针top向下移
delete(p);
S->count--;
}
void ClearStack(LinkStack* S)//清空栈
{
int i;
LinkStackPtr p, q;//定义表格指针p,q来交替遍历
p = S->top;
while (p)
{
q = p->next;
delete(p);
p = q;
}
S->top = NULL;
S->count = 0;
cout << "栈清空完毕" << endl;
}
源文件text.cpp
#include"FUNC.h"
int main()
{
LinkStack S;//定义栈S
if (InitStack(&S) == 1)
{
cout << "空栈创建成功" << endl;
}
int DBD = 1;
int n;
srand((unsigned int)time(NULL));//添加随机数种子
cout << "欢迎来到链栈的调试" << endl;
while (DBD)
{
system("pause");
system("cls");
cout << "1.输出栈的内容 2.进栈操作 3.出栈操作 4.退出程序 5.清空栈" << endl;
cin >> n;
switch (n)
{
case 1:
{
printStack(&S);
break;
}
case 2:
{
SElemType e;
e = rand() % 100 + 1;//随机产生1-100的数到e中(e用来临时储存待插入栈的数据)
cout << "输入的数据为:" << e << endl;
Push(&S, e);
break;
}
case 3:
{
if (StackEmpty(&S) == 1)
{
SElemType e;
Pop(&S, &e);
cout << "值:" << e << "已出栈" << endl;
break;
}
else
{
cout << "栈为空" << endl;
break;
}
}
case 4:
{
DBD = 0;
cout << "谢谢使用" << endl;
break;
}
case 5:
{
if (StackEmpty(&S) == 1)
{
ClearStack(&S);
break;
}
else
{
cout << "栈为空" << endl;
break;
}
}
default:
{
cout << "输入不合法" << endl;
break;
}
}
}
return 0;
}
链栈完成。