栈和队列

一、栈

1.栈的定义

     栈是一种线性表,一种抽象数据类型,它只允许在一端进行插入或删除操作。又叫做LIFO(后进先出)线性表。

     栈的基本操作有入栈push和出栈pop,栈顶top指的是进行操作的一端。如图,只有栈顶元素可以访问。进栈次序为a1、a2、a3、a4、a5,出栈次序为a5、a4、a3、a2、a1

 

2.栈的实现

     栈是受限的线性表,因此任何实现表的方法都能实现栈,主要就是顺序栈和链栈。

2.1 顺序栈

     使用数组存放栈的数据元素,设有一个头指针top执行栈顶,初始时为top=0,顺序栈的实现代码:

进栈:先放在top+1

public void push(T item){
    if(top >= capacity) return;
    items[top] = item;
    top ++;
}

出栈:先top-1再取

public T pop(){
    if(top < 0) return null;
    return (T) items[--top];
}

2.2 链栈

     通常采用单链表实现,所有的操作都在表头进行。栈节点为:

private class Node{
    T item;
    Node next;
}

     链栈的实现代码,有一个头指针top,只能用top指针执行push、pop(插入删除)

进栈:头插法

public void push(T item){
    Node old = top;
    top = new Node();
    top.item = item;
    top.next = old;
    count++;
}

出栈:取时只需把top节点指向下个节点即可

public T pop(){
    T item = top.item;
    top = top.next;
    count--;
    return item;
}

二、队列

1.队列

     只在一端插入,另一端删除的线性表,类似于日常的排队,特性是先进先出FIFO。其中有两个指针,头指针head和尾指针tail,在tail插入,在head读取。

 

2.队列的实现

2.1 顺序存储

      使用数组,初始状态时,head=tail=0;当tail==MaxSize时,并不能说明队列满了,当head指针为tail的前一个位置,此时队列中只有一个元素,但没满,这时入队出现上溢出,这时一种假溢出。

2.1.1 循环队列

      也称环形队列,环形缓冲区,臆造一个环状的空间,当队头或队首指针达到最大时,重置为零,可以使用取余运算实现,(也能不用取余)。

取余运算:

初始时,head = tail = 0;
队首加1,head = (head + 1) % MaxSize;
队尾加1,tail = (tail + 1) % MaxSize;
队列长度,(tail + MaxSize - head) % MaxSize;

不使用取余:

     以RingBuffer环形缓冲区为例,具体代码在GitHub,其中入队和出队的代码如下,没使用取模运算,(对计算机来说,加1减1比取模简单)

入队:

public boolean put(T item){
    int next = tail + 1;
    if(next >= bufferSize){
        next = 0;
    }
    if(next == head){
        lost++;
        return false;
    }
    rBuffer[next] = item;
    tail = next;
    return true;
} 

出队:

public T get(){
    if(head == tail){
        return null;
    }
    @SuppressWarnings("unchecked")
    T item = (T) rBuffer[head];
    rBuffer[head] = null;
    
    if(++head >= bufferSize){
        head = 0;
    }
    return item;
}

2.2 链式存储

链队列,使用一个带有队头head和队尾tail指针的单链表,在head读取,在tail插入。节点类型如下:

private Node head; // 队头
private Node tail; // 队尾
private class Node{ // 节点
    T item;
    Node next;
}

入队:

public void enqueue(T item){
    Node old = tail;
    tail = new Node();
    tail.item = item;
    tail.next = null;
    if(isEmpty()){
        head = tail;
    } else {
        old.next = tail;
    }
    count++;
}

出队:

public T dequeue(){
    T res = head.item;
    head = head.next;
    if(isEmpty()){
        tail = null;
    }
    count--;
    return res;
}

源码地址:https://github.com/cyhe/algorithm/tree/master/src/algo/linearlist/stack

 

posted @ 2016-05-14 09:45  创心coder  阅读(417)  评论(0编辑  收藏  举报