这世间,唯有青春和梦想不可辜负。花开正好,微风不燥,扬帆起航,追逐梦想。

从数据结构上看,栈和队列也是线性表,不过是两种特殊的线性表。栈只允许在的一端进行插人或删除操作,而队列只允许在表的一端进行插人操作、而在另一端进行删除操作。因而,栈和队列也可以被称作为操作受限的线性表。从数据类型角度讲,栈和队列是与线性表不同的重要抽象数据类型,广泛地应用于各类软件系统中。

什么是栈?

栈(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语言_02

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]王曙燕.数据结构与算法:人民邮电出版社