链栈的设计与运行
1.链栈
提起链栈,很容易就想到单链表,不过链栈确实可以看做是受限的单链表,因为只能在链表头部进行操作,所以在链栈中也不再附加头结点,栈顶指针就是链表的头指针。
老话一句,实践一遍,万物皆好,下边的部分你要是懂了不妨照着葫芦画个瓢吧。
2.代码部分
- 主函数(和上一篇文章结构一样,本文如果哪里不懂可参考上一篇数据结构-顺序栈详解(超基础的那种))
#include"basic.h"
int main()
{
int choose = -1;
SElemType e; //定义一个结构体的元素e
InitStack(S); //初始化顺序栈
cout << "本次服务共有以下内容:" << endl << endl;
cout << "1. 链栈的初始化" << endl;
cout << "2. 判断栈是否为空" << endl;
cout << "3. 链栈进栈" << endl;
cout << "4. 链栈出栈" << endl;
cout << "5. 取栈顶元素" << endl;
cout << "0. 退出" << endl << endl;
while (choose != 0) {
cout << "请选择您需要的服务:" << endl; //输入选择
do {
cin >> choose;
if (choose < 0 || choose>5)
cout << "您输入的信息不在本次服务之内,请重新输入:" << endl;
} while (choose < 0 || choose>5);
switch (choose)
{
case 1:
InitStack(S);
cout << "顺序栈初始化成功!" << endl << endl;
break;
case 2:
if (StackEmpty(S)) cout << "此顺序栈为空!" << endl << endl;
else cout << "此顺序栈不为空!" << endl << endl;
break;
case 3:
cout << "请依次输入姓名和学号" << endl;
cin >> e.name >> e.mumber;
if (Push(S, e)) cout << "该元素入栈成功" << endl << endl;
break;
case 4:
Pop(S, e);
cout << "您本次取出的元素为:" << endl;
cout << e.name << " " << e.mumber << endl << endl;
break;
case 5:
e=GetTop(S);
cout << "您此时栈顶的元素为:" << endl;
cout << e.name << " " << e.mumber << endl << endl;
break;
default:break;
}
}
return 0;
}
- basic.h头文件(这里只写出了基本功能)
#pragma once
#include<iostream>
using namespace std;
#define OVERFLOR -2
#define OK 1
#define ERROR 0
typedef int Status; //表示状态
typedef struct //定义一个的结构体
{
char name[30]; //姓名
char mumber[30]; //学号
}SElemType;
typedef struct StackNode
{
SElemType data;
struct StackNode* next; //定义一个栈指针next
}StackNode,*LinkStack; //定义一个栈指针类LinkStack
LinkStack S; //定义一个栈顶指针
void InitStack(LinkStack& S) //链栈的初始化
{
S = NULL;
}
Status StackEmpty(LinkStack S) //判断栈是否为空
{
if (S == NULL) return OK;
else return ERROR;
}
Status Push(LinkStack &S, SElemType &e) //链栈进栈
{
LinkStack P;
P = new StackNode;
if (!P) exit(OVERFLOR); //判断是否成功创建新节点
P->data = e;
P->next = S;
S = P; //三步压进一个数
return OK;
}
Status Pop(LinkStack& S, SElemType& e) //链栈出栈
{
LinkStack P;
if (S == NULL) return ERROR;
P = S; //为了删除一个节点,引入P
e = S->data;
S = S->next;
delete P;
return 0;
}
SElemType GetTop(LinkStack S) //取栈顶元素(尽量减小接口的复杂度)
{
if (S == NULL) cout<<"此栈已空,无法取出栈顶元素"<<endl<<endl;
else return S->data;
}
3. 代码分析
- 要注意exit(OVERFLOR)与return ERROR的区别,虽然都是报错,但前者是表示位置不够溢出了的错误,后者是因为找不到等原因的错误,当把错误具体划分后对以后构建更复杂的项目很有帮助。
- 难点集中在链栈进栈和出栈上,这里都新建了一个栈指针P,
- 对于进栈来说流程是:构建一个新的节点;给新的节点赋值;栈顶指针指向新的节点;
- 对于出栈来说流程是:取出栈顶指针的值;栈顶指针下移;(当然,我这里为了删除原位置,引用新节点指针,最后再一个delete)
4. 运行结果
今天的笔记就做到这里,下一篇打算写链栈对进制转换问题的求解。