栈和队列


  1. 1.1概念
    栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的元素遵循先进后出的原则。
    入栈:栈的插入操作叫做入栈/压栈/进栈
    出栈:栈的删除操作叫做出栈
    入数据和出数据都是在栈顶
    1.2实现
    1.2.1顺序表实现
    顺序表使用尾插操作来表示“入栈”,尾删来表示“出栈”,根据下标获取元素的操作“取栈顶元素”。
    如果使用头插来表示“入栈”,头删来表示“出栈”,是否可行?
    可以使用,但效率较低
package java03_09;
//使用顺序表实现栈的一系列操作
public class MyStack {
    private int[] data = new int[100];
    private int size = 0;


//使用尾插来表示入栈
public void push(int val) {
    if(size >= data.length) {
        return;
    }
    data[size] = val;
    size++;
  }
  //尾删表示出栈
  public Integer pop(){
    if(size == 0) {
        return null;
    }
    int ret = data[size - 1];
    size--;
    return ret;
 }
 //取栈顶元素
 public Integer peek() {
    if(size == 0) {
        return null;
    }
     return data[size - 1];
 }
}

1.2.2链表实现
链表使用头插操作来表示“入栈”,头删操作来表示“出栈”,直接取到头结点,就是“取栈顶元素”

package java03_09;
class Node{
    int val;
    Node next;
    public Node(int val){
        this.val = val;
    }
}
//链表实现栈的一系列操作
public class MyStack2 {
    private Node head = null;
    //头插表示入栈
    public void push(int val){
        Node newNode = new Node(val);
        if(head == null) {
            head = newNode;
            return;
        }
        newNode.next = head;
        head = newNode;
    }
        //头删表示出栈
        public Integer pop() {
            if (head == null) {
                return null;
            }
            if (head.next == null) {
                int ret = head.val;
                head = null;
                return ret;
            }
            int ret = head.val;
            head = head.next;
            return ret;
        }
        //取栈顶元素
    public Integer peek(){
        if(head == null) {
            return null;
        }
        return head.val;
    }


如果使用尾插来表示“入栈”,尾删来表示“出栈”,是否可行?
可以做到高效的实现,但是需要记录额外的信息,代码也会更复杂。
1.3栈的核心操作
1.入栈:把元素放到栈里面
2.出栈:把最后进来的元素给删掉
3.取栈顶元素:获取到最后一个进来元素的结果
2. 队列
2.1 概念
队列:只允许在一端进行插入数据,在另一端进行删除数据操作的特殊线性表。具有先进先出的原则
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队首
2.2 实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率较低
顺序表:可以使用特殊的方式来实现
链表:使用尾插操作来表示“入队列”,使用头删操作来表示“出队列”,直接获取到头结点,就是取队首元素

package java03_09;
class Node1{
    int val;
    Node1 next;
    public Node1(int val){
        this.val = val;
    }

}
//使用链表来完成队列的一系列操作
public class MyQueue {
    private Node1 head = null;
    private Node1 tail = null;

    //尾插操作表示“入队列”
    public boolean offer(int val) {
        Node1 newNode = new Node1(val);
        if (head == null) {
            head = newNode;
            tail = newNode;
            return true;
        }
        tail.next = newNode;
        tail = tail.next;
        return true;
    }


   //头删操作表示“出队列”
    public Integer poll() {
        if (head == null) {
            return null;
        }
        int ret = head.val;
        if (head.next == null) {
            head = null;
            return ret;
        }
        head = head.next;
        return ret;
    }

    //取队首元素
    public Integer peek() {
        if (head == null) {
            return null;
        }
        return head.val;
    }
}

2.3 循环队列
队列的有效元素的区间[head,tail)
环形队列这个版本的队列相比于链表版本来说,更快,局限性是空间是固定大小的,扩容成本高
入队列:就把新的元素给放到tail对应的下标上,同时tail++
出队列:就把head++,也就意味着把原来的head指向的元素就排除到有效区间之外了

package java03_09;
//使用数组来实现循环队列的一系列操作
public class MyQueue2<head> {
    private int[] data = new int[100];
    private int head = 0;
    private int tail = 0;
    private int size = 0;

    //入队列
    public boolean offer(int val) {
        if (size == data.length) {
            //这时队列已满
            return false;
        }
        //把新元素放到tail对应的下标上
        data[tail] = val;
        tail++;
        //一旦tail到达了数组的末尾,这时就应让tail从0开始
        if (tail == data.length) {
            tail = 0;
        }
        size++;
        return true;
    }


        //出队列
        public Integer poll() {
            if (size == 0) {
                return null;
            }
            int ret = data[head];
            head++;
            if (head == data.length) {
                head = 0;
            }
            size--;
            return ret;
        }

        //取队首元素
    public Integer peek() {
        if (head == 0) {
            return null;
        }
        return data[head];
    }
}

环形队列为空的时候,head和tail的位置是重合的;环形队列为满的时候,head和tail的位置也是重合的。如何解决此问题
环形队列如何区分空和满
方案:

  1. 不要把这个环形队列压榨的那么干净,故意浪费一个空间
    和tail用head重合表示空队列
    使用tail==head-1表示满队列
  2. 不浪费空间,专门搞一个size变量记录队列的元素个数。size0就是空,size数组长度就是满
    2.4 双端队列deque
    两端都可以入队列和出队列
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值