数据结构--栈的相关知识点以及实现

参考:《数据结构--java语言描述》

是仅限在表尾(也就是栈顶)进行插入和删除操作的线性表。

允许插入和删除操作的一端称为栈顶(top)另一端称之为栈底(button)

不含任何元素的栈称之为空栈

遵循后进先出(LIFO, last  in first  out)的原则

入栈和出栈是栈的两个主要操作,如下图,实现栈的时候,需要一个栈顶指针top来表示栈顶的当前位置

栈的基本操作:

  1. 初始化 --构造一个空栈
  2. 入栈  --  在栈顶的位置插入一个新的元素
  3. 出栈  -- 删除栈顶元素
  4. 获取  -- 获取栈顶元素
  5. 判空 -- 判断当前栈是否为空
  6. 求长度  --  求出栈中数据元素的个数
  7. 正序遍历  --  依次访问栈中每一个元素并输出
  8. 销毁  --  销毁一个已存在的栈

栈接口定义代码如下:

public interface SequenceStack<T> {
    //入栈
    public void push(T obj);
    //出栈
    public T pop();
    //获取栈顶信息
    public T getHead();
    //判空
    public boolean isEmpty();
    //求长度
    public int size();
    //正序遍历
    public void nextOrder();
    //销毁
    public void clear();

}

顺序表实现

顺序栈:利用一组地址连续的存储单元依次存放自栈底至栈顶的数据元素,把数组中下标为0的一端作为栈底。为了指示栈中元素的位置,定义变量top来指示栈顶元素在顺序表中的位置

上图是栈顶指针top指向栈顶元素时对应的入栈和出栈的关系

深入理解顺序栈的top指针(实现顺序栈的关键)

top的初始值为-1,指向栈底,表明该栈为一个空栈。入栈操作,top指针的值加1,入栈元素放到top指针指向的位置。出栈操作,先删除栈顶元素,top指针的值减去1

1、初始化

top初始化值为-1,指向栈底,当top==-1时,表明该栈为一个空栈。

public class ArraySequenceStack<T> implements SequenceStack<T> {
    public final int maxSize=10;  //无参构造时,数组的默认长度
    private int top;  //top指针
    private T[] arrayStack;  //使用数组声明栈

    public ArraySequenceStack() {
        top=-1;
        arrayStack=(T[])new Object[maxSize];
    }

    public ArraySequenceStack(int n) {
        if(n<=0){
            System.out.println("数组的长度大于0,否则退出程序");
            System.exit(1);
        }
        this.top = -1;
        arrayStack=(T[])new Object[n];
    }

2、入栈 

入栈算法:

  • 如果栈满,需对数组进行扩容,长度原来的两倍。
    • 定义一个长度为原数组长度两倍的数组
    • 把原数组中的值复制到新定义的数组当中
    • 把指向原数组的指针指向新的数组
  • top值加1
  • 把入栈元素插入top指针指向的位置
    public void push(T obj) {
        if(top+1==arrayStack.length){
            T[] p=(T[])new Object[(top+1)*2];
            for(int i=0;i<arrayStack.length;i++){
                p[i]=arrayStack[i];
            }
            arrayStack=p;
        }
        top++;
        arrayStack[top]=obj;
    }

3、出栈

出栈算法

  • 如果为空栈,则无法进行出栈操作
  • 备份栈顶元素
  • 删除栈顶元素,top减去1,同时返回备份的栈顶元素
    public T pop() {
        if(isEmpty()){
            System.out.println("空栈,出栈操作失败");
            return null;
        }
        T pop=arrayStack[top];  //备份栈顶元素
        arrayStack[top]=null; //移除栈顶数据元素,方便已移除数据进行垃圾回收
        top--;
        return pop;
    }

4、获取栈顶元素

栈空,获取失败,返回null。不为空,返回栈顶元素

    public T getHead() {
        if(isEmpty()){
            System.out.println("空栈,获取栈顶元素失败");
            return null;
        }

        return arrayStack[top];
    }

5、判空

当top==-1时。为空栈

    public boolean isEmpty() {
        return top==-1;
    }

6、获取数组长度

数组长度为top+1。不要以为长度为top+2。当元素入栈时,top会加1,指向栈顶元素

    public int size() {
        return top+1;
    }

7、正序遍历

依次输出数组中的值,队尾元素对应栈顶元素

  public void nextOrder() {
        for(int i=0;i<=top;i++){
            System.out.print(arrayStack[i]+"  ");
        }
        System.out.println();
    }

8、销毁

top设置为-1,同时数组设置为null

    public void clear() {
        top=-1;
        arrayStack=null;
    }

链表实现

链栈:栈的连接存储结构。对于链式栈,无满栈问题,空间可扩充,插入与删除操作仅在栈顶执行,链式栈的栈顶在链头。

链栈的链表示意图

由于栈只能对栈顶元素(p)进行操作。所以入栈操作为:p.next=top;top=p;  出栈操作为:p=top;top=top.next;

栈的链表实现类泛型定义如下:

public class LinkedSequenceStack<T> implements SequenceStack<T> {
    public Node<T> top;
    public int length;

    public LinkedSequenceStack() {
        this.top = null;
        this.length = 0;
    }

    class Node<T>{
        T obj;
        Node<T> next;

        public Node(T obj, Node<T> next) {
            this.obj = obj;
            this.next = next;
        }

        public Node(T obj){
            this.obj=obj;
            this.next=null;
        }
    }

    @Override
    public void push(T obj) { //入栈
        top=new Node<T>(obj,top);
        length++;
    }

    @Override
    public T pop() {  //出栈
        if(length==0){
            System.out.println("空栈,出栈操作失败");
            return null;
        }
        T obj=top.obj;
        top=top.next;
        length--;
        return obj;
    }

    @Override
    public T getHead() { //获取头节点
        if(length==0){
            System.out.println("空栈,获取栈顶元素操作失败");
            return null;
        }
        return top.obj;
    }

    @Override
    public boolean isEmpty() {  //判空
        return length==0;
    }

    @Override
    public int size() {  //求长度
        return length;
    }

    @Override
    public void nextOrder() { //正序遍历
        Node<T> temp=top;
        for(int i=0;i<length;i++){
            System.out.print(temp.obj+" ");
            temp=temp.next;
        }
        System.out.println();
    }

    @Override
    public void clear() { //销毁
        length=0;
        top=null;
    }

    public static void main(String[] args) {
        //数组反转
        String str="abcdefg";
        char[] strChar=str.toCharArray();
        LinkedSequenceStack stack=new LinkedSequenceStack();
        for(int i=0;i<strChar.length;i++){  //依次字符串的字符压入栈中
            stack.push(strChar[i]);
        }
        for(int i=0;i<strChar.length;i++){ //栈中的元素依次出栈
            strChar[i]=(char)stack.pop();
        }
        String str1=new String(strChar);
        System.out.println(str1);
    }
}

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值