美文网首页
特殊的线性表--栈和队列

特殊的线性表--栈和队列

作者: 斌斌爱学习 | 来源:发表于2019-10-09 00:28 被阅读0次

大厂之路的第四篇 栈和队列(Stack and Queue)

前面三篇我们都在讲线性表,今天我们介绍两种特殊的线性表来做为线性表专题的结尾。----队列

先看一下这两者的定义(来源百度百科):
: 栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

上学的时候就特别不爱背定义,我想用张图来描述可能会更清晰一些:


栈.png

队列:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

同样,我们也用一张图来解释队列的特点:

队列.png

概念讲完了,我们就从java源码的角度来进一步了解它们。

首先,我们看,即Stack
我们先看一下jdk中对Stack的注释

 * The <code>Stack</code> class represents a last-in-first-out
 * (LIFO) stack of objects. It extends class <tt>Vector</tt> with five
 * operations that allow a vector to be treated as a stack. The usual
 * <tt>push</tt> and <tt>pop</tt> operations are provided, as well as a
 * method to <tt>peek</tt> at the top item on the stack, a method to test
 * for whether the stack is <tt>empty</tt>, and a method to <tt>search</tt>
 * the stack for an item and discover how far it is from the top.

今天我打算翻译一下这段话,又学编程又学英语,还不错!!

Stack这个类代表着一堆后进先出的对象集合。Stack继承自Vector,如果一个Vector对象有以下五种行为,那么它就可以被看作是Stack:

  1. 含有pushpop这两个函数
  2. 提供peek方法以获取栈顶部的item
  3. 提供empty方法以校验Stack是否为空
  4. 提供search方法以在栈中寻找一个item以及判断它距离栈顶有多远

之前我们有提到过Vector,它跟ArrayList是很类似的,最根本的区别在于它是线程安全的。既然Stack继承自Vector,那么首先它也是线程安全的。

接着又提到了Stack的特殊之处在于它所特有的五个函数:
push,pop,peek,empty, search

那么,我们就来分别看一下这五个函数:

1.push函数

    public E push(E item) {
        addElement(item);

        return item;
    }
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }

push函数特别的简单:
1.判断是否需要扩容。因为VectorArrayList一样,底层都是动态数组,所以第一步需要判断是否需要对数组进行扩容。
2.将要添加的元素添加至线性表的尾部。由于我们之前分析过ArrayList的增删改查,Vector其实也差不多,所以我们就不再解释了。

2.peek函数
由于在pop函数中有用到peek,所以我们先看peek函数

 public synchronized E peek() {
        int     len = size();

        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }
 public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }

        return elementData(index);
    }
  E elementData(int index) {
        return (E) elementData[index];
    }

不难看出,peek函数其实就是取线性表的队尾元素,并将其返回。

3.pop函数

 public synchronized E pop() {
        E       obj;
        int     len = size();

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    }
  public synchronized void removeElementAt(int index) {
        modCount++;
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = elementCount - index - 1;
        if (j > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }

同样很简单,先拿到队尾的元素作为返回值,再将队尾元素置为null,同时改变线性表的长度。

4.empty函数

public boolean empty() {
        return size() == 0;
    }

这个就更简单了,判断size是否为0。

5.search函数

   public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
      }

    public synchronized int lastIndexOf(Object o) {
        return lastIndexOf(o, elementCount-1);
    }

    public synchronized int lastIndexOf(Object o, int index) {
        if (index >= elementCount)
            throw new IndexOutOfBoundsException(index + " >= "+ elementCount);

        if (o == null) {
            for (int i = index; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

search函数一样也很简单,就是从队尾开始遍历查找线性表中是否包含指定元素,并将其距离栈顶的距离返回。

栈看完了,接着看队列,即Queue
通过Queue的源码我们可以看到,它是一个接口。那所有继承他的类都必须实现以下几个方法(特有的方法):
element,offer,peek,poll,remove

由于我们前面分析过LinkedList的源码,而又由于LinkedList其实是实现了Deque也就是双端队列,而Deque又是实现自Queue,所以在此我们就不再展开了。

今天,栈和队列我们就看到这里了。下一篇我们看另一个特别重要的集合,hash表。

相关文章

  • 栈和队列(一)

    栈和队列 栈和队列是两种特殊的线性表,是操作受限的线性表,称限定性DS。 栈和队列是限定插入和删除只能在表的“端点...

  • 栈和队列 学习总结 (一)栈

    栈和队列 学习总结 (一)栈 概述: 栈和队列是两种特殊的线性表,特殊之处在于插入和删除操...

  • 栈和队列—什么是栈

    栈和队列是两种重要的数据结构 从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子...

  • 栈和队列—什么是队列

    栈和队列是两种重要的数据结构 从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子...

  • 数据结构与算法 — 栈

    栈和队列是两种重要的现行结构。从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子...

  • 数据结构

    线性表 线性表分为顺序表与链表 栈和队列 栈:先进后出队列:先进先出栈和队列都是线性表的特征形式 二叉树 对于相对...

  • 第四章栈与队列

    知识大纲 栈和队列的数据结构 相同点 栈和队列都是对删除和插入做了限制的线性表 栈和队列的都是建立在线性表的...

  • 栈和队列

    栈和队列 栈由于是一种特殊的线性表,它也分为顺序存储和链式存储。 顺序栈。类比数组,数组的尾巴模拟栈顶 链栈。 ...

  • 计算机二级选择题干货(五)——数据结构和算法

    1、线性表、栈和队列等数据结构所表达和处理的数据以线性结构为组织形式。栈是一种特殊的线性表,这种线性表只能在固定的...

  • 数据结构(线性结构 栈与队列)

    栈与队列都是特殊的线性表,它们也是线性结构。用户可以采用顺序存储结构和链式存储结构两种方式来存储。栈和队列结构是各...

网友评论

      本文标题:特殊的线性表--栈和队列

      本文链接:https://www.haomeiwen.com/subject/rqtwpctx.html