◉ 顺序栈与链栈
顺序栈 底层是一个数组
在使用前需要先设置好栈的大小,大小受限
链栈 底层是一个单链表
每一次增加结点都需要开辟新空间,理论上大小不受限
◉ 基本操作
- 初始化栈 init
- 判断空栈 isEmpty
- 得到栈顶 getTop
- 获取长度 length
- 压栈入栈 push
- 弹栈出栈 pop
- 清空全栈 clear
- 摧毁全栈 destroy
◉ 实现注意事项
- C语言 中栈的数据类型可使用
void*
空指针,来支持多种类型的接收 - Java 中则可以方便地使用 泛型 来控制数据类型
- 顺序栈中应该设定一个栈顶指针
top
,初始值为-1
,指向栈顶元素 - 链栈中的单链表均应采用头插法,每次都要替换掉头指针,保证最后进去的数据在最前面
◉ C语言实现
—① 顺序栈
头文件 SqStack.h
#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
typedef enum Status
{
ERROR = 0, SUCCESS = 1
} Status;
typedef int ElemType;
typedef struct SqStack
{
ElemType* elem;
int top;
int size;
} SqStack;
//基于数组的顺序栈
Status initStack(SqStack* s, int sizes);//初始化栈
Status isEmptyStack(SqStack* s);//判断栈是否为空
Status getTopStack(SqStack* s, ElemType* e); //得到栈顶元素
Status clearStack(SqStack* s);//清空栈
Status destroyStack(SqStack* s);//销毁栈
Status stackLength(SqStack* s, int* length);//检测栈长度
Status pushStack(SqStack* s, ElemType data);//入栈
Status popStack(SqStack* s, ElemType* data);//出栈
#endif
实现文件 SqStack.c
#include "SqStack.h"
#include <malloc.h>
// 初始化栈
Status initStack(SqStack* s, int sizes)
{
// 栈已经开辟好了,不需要再开辟
if (s->elem != NULL) return ERROR;
// 为栈开辟空间
s->elem = (int*)malloc(sizeof(int) * sizes);
// 空间开辟成功时,设置栈顶和栈的大小
if (s->elem != NULL)
{
s->top = -1;
s->size = sizes;
return SUCCESS;
}
else return ERROR;
}
// 判断栈是否为空
Status isEmptyStack(SqStack* s)
{
// 未初始化或已初始化但没有元素,均视为空
if (s->elem == NULL || s->top == -1) return SUCCESS;
else return ERROR;
}
// 得到栈顶元素
Status getTopStack(SqStack* s, ElemType* e)
{
// 在栈不为空时获取
if (!isEmptyStack(s))
{
*e = s->elem[s->top];
return SUCCESS;
}
else return ERROR;
}
// 清空栈
Status clearStack(SqStack* s)
{
// 栈不为空时进行
if (!isEmptyStack(s))
{
// 不断弹出元素
while (s->top > -1) s->elem[s->top--] = NULL;
return SUCCESS;
}
else return ERROR;
}
// 销毁栈
Status destroyStack(SqStack* s)
{
// 栈已经初始化时进行
if (s->elem != NULL)
{
free(s->elem); // 释放数组
s->elem = NULL; // 指向空
s->size = 0; // 长度归零
s->top = 0; // 栈顶归零
return SUCCESS;
}
else return ERROR;
}
// 检测栈长度
Status stackLength(SqStack* s, int* length)
{
// 栈是否已经初始化
if (s->elem != NULL)
{
*length = s->top + 1; // 栈当前的长度
return SUCCESS;
}
else return ERROR;
}
// 入栈
Status pushStack(SqStack* s, ElemType data)
{
// 栈已经初始化并且还没有满
if (s->elem != NULL && s->top < s->size - 1)
{
s->elem[++s->top] = data; // 推入元素并改变栈顶
return SUCCESS;
}
else return ERROR;
}
// 出栈并返回被弹出的元素
Status popStack(SqStack* s, ElemType* data)
{
// 栈不为空时进行
if (!isEmptyStack(s))
{
*data = s->elem[s->top]; // 返回弹出的元素
s->elem[s->top--] = NULL; // 弹出元素并改变栈顶
return SUCCESS;
}
else return ERROR;
}
—② 链栈
头文件 LinkStack.h
#ifndef STACK_H_INCLUDED
#define STACK_H_INCLUDED
typedef enum Status
{
ERROR = 0,
SUCCESS = 1
} Status;
typedef int ElemType;
typedef struct StackNode
{
ElemType data;
struct StackNode* next;
}StackNode, * LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
//链栈
Status initLStack(LinkStack* s);//初始化栈
Status isEmptyLStack(LinkStack* s);//判断栈是否为空
Status getTopLStack(LinkStack* s, ElemType* e);//得到栈顶元素
Status clearLStack(LinkStack* s);//清空栈
Status destroyLStack(LinkStack* s);//销毁栈
Status LStackLength(LinkStack* s, int* length);//检测栈长度
Status pushLStack(LinkStack* s, ElemType data);//入栈
Status popLStack(LinkStack* s, ElemType* data);//出栈
#endif
实现文件 LinkStack.c
#include "LinkStack.h"
#include <malloc.h>
//初始化栈
Status initLStack(LinkStack* s)
{
// 栈已经开辟好了,不需要再开辟
if (s->top != NULL) return ERROR;
// 为栈开辟空间
s->top = (LinkStackPtr*)malloc(sizeof(LinkStack));
// 空间开辟成功时,设置栈的长度
if (s->top != NULL)
{
s->top->next = NULL;
s->count = 0;
return SUCCESS;
}
else return ERROR;
}
// 判断栈是否为空
Status isEmptyLStack(LinkStack* s)
{
// 未初始化或已初始化但没有元素,均视为空
if (s->top == NULL || s->count == 0) return SUCCESS;
else return ERROR;
}
// 得到栈顶元素
Status getTopLStack(LinkStack* s, ElemType* e)
{
// 在栈不为空时获取
if (!isEmptyLStack(s))
{
*e = s->top->data;
return SUCCESS;
}
else return ERROR;
}
// 清空栈
Status clearLStack(LinkStack* s)
{
// 栈不为空时进行
if (!isEmptyLStack(s))
{
LinkStackPtr temp; // 用于删除的临时指针
// 不断弹出元素
while (s->count > 0)
{
temp = s->top->next; // 存放下一个元素
free(s->top); // 释放栈顶元素
s->top = temp; // 改变栈顶
s->count--; // 栈长度 -1
}
return SUCCESS;
}
else return ERROR;
}
// 销毁栈
Status destroyLStack(LinkStack* s)
{
// 栈已经初始化时进行
if (s->top != NULL)
{
clearLStack(s); // 先将栈清空
free(s->top); // 再将栈顶指针释放掉
s->top = NULL; // 指向空
return SUCCESS;
}
else return ERROR;
}
// 检测栈长度
Status LStackLength(LinkStack* s, int* length)
{
// 栈已经初始化时进行
if (s->top != NULL)
{
*length = s->count; // 栈当前的长度
return SUCCESS;
}
else return ERROR;
}
// 入栈
Status pushLStack(LinkStack* s, ElemType data)
{
// 栈已经初始化时进行
if (s->top != NULL)
{
// 开辟新结点
StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));
// 开辟成功时,入栈
if (newNode != NULL)
{
newNode->data = data; // 新结点赋值
newNode->next = s->top; // 新结点直线前一个结点
s->top = newNode; // 栈顶指针指向新结点
s->count++; // 栈长度 +1
}
else return ERROR;
}
else return ERROR;
}
// 出栈
Status popLStack(LinkStack* s, ElemType* data)
{
// 栈不为空时进行
if (!isEmptyLStack(s))
{
LinkStackPtr temp = s->top->next; // 用于删除的临时指针
*data = s->top->data; // 取出数据
free(s->top); // 释放栈顶结点
s->top = temp; // 新的栈顶结点
s->count--; // 栈长度 -1
return SUCCESS;
}
else return ERROR;
}
◉ Java实现
—① 顺序栈
实现类 SqStack.java
package SqStack;
/**
* @author : Ice'Clean
* @date : 2021-04-04
*
* 实现顺序栈
*/
public class SqStack<T>{
/**
* 存放数据的数组
* 由于不能直接用泛型做为数组
* 这里采用了 Object 作为代替
* 在读取数据时再将数据进行转化
*/
private Object[] elem;
/**
* 存放栈顶坐标
* 一开始坐标指向 -1 表示栈为空
*/
private int top = -1;
/**
* 存放栈的大小
* 默认设置为 10
*/
private int size = 10;
/**
* 初始化栈并使用默认容量
*/
public SqStack(){
elem = new Object[this.size];
}
/**
* 初始化栈并指定栈的大小
* @param size 栈的最大容量
*/
public SqStack(int size){
this.size = size;
elem = new Object[size];
}
/**
* 入栈
* @param data 要进栈的数据
* @return 成功返回 true,否则 false
*/
public boolean pushStack(T data){
if(top < size - 1) {
elem[++top] = data;
return true;
}
return false;
}
/**
* 出栈
* @return 成功返回 true,否则 false
*/
public boolean popStack(){
if(top > -1){
elem[top--] = null;
return true;
}
return false;
}
/**
* 判断栈是否为空
* @return 成功返回 true,否则 false
*/
public boolean isEmptyStack(){
return top == -1;
}
/**
* 得到栈顶元素
* @return 栈顶元素的数值
*/
public T getTopStack(){
return (T)elem[top];
}
/**
* 返回栈的长度
* @return 栈当前的长度
*/
public int length(){
return this.top + 1;
}
/**
* 清空栈
* @return 成功返回 true,否则 false
*/
public boolean clearStack(){
while(top > -1)
{
elem[top--] = null;
}
return true;
}
/**
* 输出栈的内容
* @return 字符串形式的栈内容
*/
@Override
public String toString() {
StringBuilder content = new StringBuilder();
for(Object con : elem){
if(con == null){
break;
}
content.append(con);
content.append(" / ");
}
return "顺序栈 :" + content;
}
}
—② 链栈
结点类 StackNode.java
package LinkStack;
import java.util.Stack;
/**
* @author : Ice'Clean
* @date : 2021-04-04
*
* 链栈的结点
*/
public class StackNode<T> {
private T data;
private StackNode<T> next;
/**
* 创建空结点
*/
public StackNode()
{
}
/**
* 创建带数据和指向的结点
* @param data 结点的数据
* @param next 结点的指向
*/
public StackNode(T data, StackNode<T> next)
{
this.data = data;
this.next = next;
}
/**
* 使链表指向新的结点
* @param next 下一个结点
*/
public void setNext(StackNode<T> next)
{
this.next = next;
}
/**
* 修改该结点的数据
* @param data 该结点的新数据
*/
public void setData(T data)
{
this.data = data;
}
/**
* 获取下一个结点
* @return 下一个结点
*/
public StackNode<T> getNext() {
return next;
}
/**
* 获取该节点的数据
* @return 该节点的数据
*/
public T getData() {
return data;
}
}
实现类 LinkStack.java
package LinkStack;
/**
* @author : Ice'Clean
* @date : 2021-04-04
*
* 链栈实现
*/
public class LinkStack<T> {
/**
* 链栈的头结点
*/
private StackNode<T> top;
/**
* 链栈的长度
*/
private int count;
/**
* 初始化空链栈
*/
public LinkStack(){
}
/**
* 初始化链栈并压入一个数据
*/
public LinkStack(T data){
top = new StackNode<T>(data, null);
count++;
}
/**
* 入栈
* @param data 入栈的数据
* @return 是否成功
*/
public boolean push(T data){
if(top == null){
top = new StackNode<T>(data, null);
}
else{
// 新建一个结点指向 head,然后赋值给 head,保证 head 在栈顶
top = new StackNode<T>(data, top);
}
// 长度自增 1
count++;
return true;
}
/**
* 出栈
* @return 成功返回 true, 否则 false
*/
public boolean pop(){
if(count > 0){
StackNode<T> temp = top;
top = top.getNext();
temp = null;
count--;
return true;
}
return false;
}
/**
* 判断栈是否为空
* @return 是则返回 true,否则 false
*/
public boolean isEmpty(){
return count == 0;
}
/**
* 得到栈顶元素
* @return 栈顶元素的值
*/
public T getTop(){
if(count > 0){
return top.getData();
}
return null;
}
/**
* 清空栈
* @return 成功放回 true, 否则 false
*/
public boolean clear(){
while(count > 0){
pop();
}
return true;
}
/**
* 返回栈当前的长度
* @return 栈的长度
*/
public int length(){
return this.count;
}
/**
* 输出栈的内容
* @return 字符串形式的栈内容
*/
@Override
public String toString() {
StringBuilder content = new StringBuilder();
StackNode<T> temp = top;
while(temp != null){
content.append(temp.getData());
content.append(" -> ");
temp = temp.getNext();
}
content.append("null");
return "链栈:" + content;
}
}
测试类就没放了
时刻欢迎指正!
耕耘收获(IceClean)