首页 > 编程语言 >【数据结构与算法 | 基础篇】单向链表模拟栈

【数据结构与算法 | 基础篇】单向链表模拟栈

时间:2024-05-25 19:29:42浏览次数:28  
标签:return 单向 value public 链表 next push 数据结构 stack

1. 前言

  • 前文我们先后用单向循环链表,环形数组来模拟了队列. 队列的特点是先进先出. 队头移除元素,队尾添加元素. 所以需要两个指针控制.
  • 本文我们接下来提及如果和单向链表来模拟栈. 栈的特点是后进先出. 在栈顶压栈或弹栈. 另一侧不动的是栈底. 我们可以初始化哨兵节点,自哨兵节点之后对元素进行压栈弹栈操作.(即压栈操作是头插法)

2. 单向链表模拟栈

(1). 栈接口

public interface stack<E> {
    //压栈
    boolean push(E value);
    //弹栈, 栈非空返回栈顶元素

    E pop();
    //返回栈顶元素, 但不弹栈
    E peek();
    //判断栈是否为空
    boolean isEmpty();
    //判断栈是否已满
    boolean isFull();
}

(2). 单向链表模拟栈

//单向链表模拟栈
public class LinkedListStack<E> implements stack<E>, Iterable<E>{
    //链表的容量
    private int capacity;
    //栈的实际大小, 成员变量默认值是0
    private int size;
    Node<E> dummy;

    public LinkedListStack() {
        //初始化头节点
        dummy = new Node<>(null, null);
    }

    public LinkedListStack(int capacity) {
        this();
        this.capacity = capacity;
    }
    private static class Node<E> {
        Node<E> next;
        E value;

        public Node(Node<E> next, E value) {
            this.next = next;
            this.value = value;
        }
    }
    @Override
    public boolean push(E value) {
        //如果栈满, 则不能添加元素
        if (isFull()) {
            return false;
        }
        Node<E> p = new Node<>(dummy.next, value);
        dummy.next = p;
        size++;
        return true;
    }

    @Override
    public E pop() {
        //如果栈空, 则弹栈失败
        if(isEmpty()) {
            return null;
        }
        Node<E> p = dummy.next;
        dummy.next = p.next;
        size--;
        return p.value;
    }

    @Override
    public E peek() {
        if(isEmpty()) {
            return null;
        }
        return dummy.next.value;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == capacity;
    }
    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            Node<E> p = dummy.next;
            @Override
            public boolean hasNext() {
                return p != null;
            }

            @Override
            public E next() {
                E value = p.value;
                p = p.next;
                return value;
            }
        };
    }
}

3. 单元测试

public class LinkedListStackTest {
    @Test
    public void test1() {
        LinkedListStack<Integer> stack = new LinkedListStack<>(10);
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
        stack.push(6);
        stack.push(7);
        for (Integer element : stack) {
            System.out.print(element + " ");
        }
        //7 6 5 4 3 2 1
    }
    @Test
    public void test2() {
        LinkedListStack<Integer> stack = new LinkedListStack<>(10);
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
        stack.push(6);
        stack.push(7);
        //7, 输出栈顶元素, 但不弹栈, 输出7
        System.out.println(stack.peek());
        //7, 输出栈顶元素, 同时弹栈, 所以弹出7
        System.out.println(stack.pop());
        //6
        System.out.println(stack.peek());
    }
}

标签:return,单向,value,public,链表,next,push,数据结构,stack
From: https://blog.csdn.net/2301_80912559/article/details/139196696

相关文章

  • 【数据结构与算法 | 基础篇】数组模拟栈
    1.前言前文我们刚提及了如何用单向链表来模拟栈.我们还可以用数组来模拟栈.使用栈顶指针top来进行栈顶的操作.2.数组模拟栈(1).栈接口publicinterfacestack<E>{//压栈booleanpush(Evalue);//弹栈,栈非空返回栈顶元素Epop();//返回栈......
  • 复习数据结构的第五天(栈)
    上次我们复习了静态链表,它需要系统提前分配一定大小的内存空间,同时它和单链表一样有一个指针(游标)指向下一个节点的数组下标索引。它不具有顺序表随机访问的功能,但它可以像单链表一样插入删除时不需要移动其他元素,只需要改变游标就可以实现。栈的概念栈是一种只能在一端进行插......
  • Day 4 | 24. 两两交换链表中的节点 、 19.删除链表的倒数第N个节点 、面试题 02.07.
    24.两两交换链表中的节点用虚拟头结点,这样会方便很多。本题链表操作就比较复杂了,建议大家先看视频,视频里我讲解了注意事项,为什么需要temp保存临时节点。题目链接/文章讲解/视频讲解:https://programmercarl.com/0024.两两交换链表中的节点.html思考需要设置一个虚拟头节点,方......
  • C语言数据结构栈的概念及结构、栈的实现、栈的初始化、销毁栈、入栈、出栈、检查是否
    文章目录前言栈的概念及结构栈的实现一、栈结构创建二、初始化结构三、销毁栈四、入栈五、出栈六、检查是否为空七、获取栈顶元素八、获取有效元素的个数九、测试1十、测试2总结前言C语言数据结构栈的概念及结构、栈的实现、栈的初始化、销毁栈、入栈、出栈、检......
  • leetcode以及牛客网单链表相关的题、移除链表元素、链表的中间节点、合并两个有序链表
    文章目录前言一、移除链表元素二、链表的中间节点三、合并两个有序链表四、反转链表五、链表分割六、倒数第k个节点七、链表的回文结构八、相交链表九、判断链表是否有环十、判断环形链表的入口点十一、随机链表的复制总结前言leetcode以及牛客网单链表相关的题、移......
  • Redis基本数据结构
    String数据结构如果存储的是整型,直接把值存储在RedisObject里面,数据类型为int。如果存储的数据量不大(早期版本,32字节),采用动态字符串SDS存储,存储类型是embstr。超过32字节,采用动态字符串SDS进行存储,存储类型是raw。embstr和raw类型的区别在于,RedisObject和embstr是连续存......
  • Java数据结构与算法(平衡二叉树)
    前言平衡二叉树是为了提高二叉树的查询速度,通过满足特定的条件来保持其平衡性。平衡二叉树具有以下特点:左子树和右子树的高度差不会大于1,这是为了确保树的高度不会过大,从而减少查询时的磁盘I/O开销,提高查询速度。平衡二叉树上的所有结点的平衡因子(左子树深度减去右子树深度的......
  • 数据结构(栈)
    1.栈的概念和结构概念:栈是一种线性表,它只能从固定的一端进行数据的插入和删除,这一端称为栈顶,另一端称为栈底。栈遵循先入后出的原则。压栈:栈的插入操作可以称为进栈/压栈/入栈,入数据在栈的顶部。出栈:栈的删除操作叫出栈,出的数据也是在栈顶。进栈:出栈:2.栈的实现栈的实......
  • 数据结构(树)
    1.树的概念和结构树,顾名思义,它看起来像一棵树,是由n个结点组成的非线性的数据结构。下面就是一颗树:树的一些基本概念:结点的度:一个结点含有的子树的个数称为该结点的度;如上图:A的为6叶结点或终端结点:度为0的结点称为叶结点;如上图:B、C、H、I...等结点为叶结点非终端结点或......
  • PTA 6-18 循环链表的追加
    单链表的结点存储结构如下所示:structNode{intdata;structNode*next;};请编写函数,将一个构造好的新结点p(结点地址),添加到指针rear指向的循环单链表的尾部(rear指向的是循环单链表尾的地址,循环单链表无附加头结点),并确保rear始终指向最后一个结点(如果有的话)。函数接口定......