这世间,唯有青春和梦想不可辜负。花开正好,微风不燥,扬帆起航,追逐梦想。
从数据结构上看,栈和队列也是线性表,不过是两种特殊的线性表。栈只允许在的一端进行插人或删除操作,而队列只允许在表的一端进行插人操作、而在另一端进行删除操作。因而,栈和队列也可以被称作为操作受限的线性表。从数据类型角度讲,栈和队列是与线性表不同的重要抽象数据类型,广泛地应用于各类软件系统中。
什么是栈?
栈(stack)是种只允许在一端进行插人和删除的线性表, 它是一种操作受限的线性表。在表中只允许进行插人和删除的端称为栈顶 (top),,另端称为栈底( bottom)。栈的插人操作通常称为人栈或进栈( push ),而栈的删除操作则称为出栈或退栈( pop )。当栈中无数据元素时,称为空栈。根据栈定义,每次进栈的元素都被放在原栈顶元素之上而成为新的栈项,而每次出栈的总是当前栈中“最新”的元素,即最后进栈的元素。栈具有后进先出的特性,因此又称为后进先出(Last In First Out, LIFO) 表。
(一)栈的顺序存储结构
利用顺序存储方式实现的栈称为顺序栈。
类似于顺序表的定义,栈中的数据元素用一个预设的足够长度的一维数组来实现: datatype data[MAXSIZE],栈底位置可以设置在数组的任一个端点,而由于顺序表在元素尾部的插入和删除最为方便,因此栈顶一般选着在元素尾部,用一个int top来作为栈顶的指针,指明当前栈顶的位置。
C语言实现顺序栈
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 50
#define dataType int
typedef struct {
dataType data[MAXSIZE];
int top;
}SeqStack;
//初始化顺序栈
SeqStack* Init_SeqStack(){
SeqStack* s = (SeqStack*)malloc(sizeof(SeqStack));
s->top = 0;
return s;
}
//非空判断
int IsEmpty_SeqStack(SeqStack* s){
if (s->top == 0) {
return 1;
} else{
return 0;
}
}
//判满
int IsFull_SeqStack(SeqStack* s){
if (s->top == MAXSIZE){
return 1;
} else{
return 0;
}
}
//入栈
int Push_SeqStack(SeqStack* s,dataType elem){
if (IsFull_SeqStack(s)){
return 0;
}
s->data[s->top] = elem;
s->top ++;
return 1;
}
//出栈
int Pop_SeqStack(SeqStack* s , dataType* elem){
if(IsEmpty_SeqStack(s)){
return 0;
}
s->top --;
*elem = s->data[s->top];
return 1;
}
//取栈顶元素
dataType GetTop_SeqStack(SeqStack* s){
if (IsEmpty_SeqStack(s)){
return 0;
}
return s->data[s->top - 1];
}
Java实现顺序栈
基于上一篇博客实现的顺序表,这里直接复用SeqList实现顺序栈。
数据结构:线性数据结构
package cn.boom.stack;
public interface Stack<T> {
public abstract int getSize(); //获取元素个数
public abstract void push(T elem); //入栈
public abstract T pop(); //出栈
public abstract T getTop(); //获取栈顶元素
public abstract boolean isEmpty();//判空
}
package cn.boom.stack;
public class SeqStack<T> implements Stack<T> {
private SeqList<T> seqList;
public SeqStack() {
seqList = new SeqList<T>();
}
@Override
public int getSize() {
return seqList.getSize();
}
@Override
public void push(T elem) {
seqList.addLast(elem);
}
@Override
public T pop() {
return seqList.removeLast();
}
@Override
public T getTop() {
return seqList.getIndexOf(seqList.getSize() - 1);
}
@Override
public boolean isEmpty() {
return seqList.isEmpty();
}
}
(二)栈的链式存储结构
要避免栈上溢,更好的办法是使用链式存储结构,所以栈也可以采用链式存储结构表示,这种结构的栈简称为链栈。
根据链表的特点,由于头结点的存在,因而栈顶应取链表第一个结点操作方便,栈底就是链表的最后一个结点,因此,新入栈的元素即为链表新的第一个结点, 只要系统还有存储空间,就不会有栈满的情况发生。一个链栈可由栈顶指针top唯一确定。
C语言实现链栈
#include <stdlib.h>
#include <stdio.h>
#define dataType int
typedef struct Stacknode{
dataType data;
struct Stacknode *next;
}slStacktype;
//初始化链栈
slStacktype *Init_slStacktype(){
slStacktype *top = (slStacktype *) malloc(sizeof(slStacktype));
top->next = NULL;
return top;
}
//非空判断
int IsEmpty_slStacktype(slStacktype *top){
if (top->next == NULL) {
return 1;
} else {
return 0;
}
}
//入栈
int Push_slStacktype(slStacktype *top, dataType elem) {
slStacktype *s = (slStacktype *) malloc(sizeof(slStacktype));
//malloc申请空间失败
if (s == NULL){
return 0;
}
s->data = elem;
s->next = top->next;
top->next = s;
return 1;
}
//出栈
int Pop_slStcaktype(slStacktype *top ,dataType *elem) {
if (!IsEmpty_slStacktype(top)) {
slStacktype *p = top->next;
*elem = p->data;
top->next = p->next;
free(p);
return 1;
} else {
return 0;
}
}
Java实现链栈
基于上一篇博客实现的链表,这里直接复用LinkedListList实现链栈。
数据结构:线性数据结构
package cn.boom.stack;
public class LinkedListStack<T> implements Stack<T> {
private LinkedList<T> linkedList;
public LinkedListStack() {
linkedList = new LinkedList<T>();
}
@Override
public int getSize() {
return linkedList.getSize();
}
@Override
public void push(T elem) {
linkedList.addFirst(elem);
}
@Override
public T pop() {
return linkedList.remove(0);
}
@Override
public T getTop() {
return linkedList.get(0);
}
@Override
public boolean isEmpty() {
return linkedList.isEmpty();
}
}
参考文献
[1]王曙燕.数据结构与算法:人民邮电出版社