栈和队列的实现

之前学习数据结构的时候,是使用C++实现各种数据结构,现在初学Java,所以想尝试用Java语言实现一遍曾经学习过的数据结构。两种语言实现的方式差别并不大,只是把C++里的指针变成了Java中对对象的引用而已。


栈的实现

栈是一种线性数据结构,其特点就是数据只能从它的一端进入和弹出,符合“先进后出”的规则。

在Oracle给出的JDK 11的文档中,栈中共有以下几个函数:

Modifier and TypeMethodDescription
booleanempty()Tests if this stack is empty.
Epeek()Looks at the object at the top of this stack without removing it from the stack.
Epop()Removes the object at the top of this stack and returns that object as the value of this function.
Epush(E item)Pushes an item onto the top of this stack.
intsearch(Object o)Returns the 1-based position where an object is on this stack.

分别实现判断是否为空、查看栈顶元素、弹出栈顶元素、压栈和输出指定对象位置的功能。


在《Java编程思想》的“持有对象”这一章,给出了使用LinkedList简单实现栈的代码:

import java.util.LinkedList;

public class Stack<T> {
    private LinkedList<T> storage = new LinkedList<T>();
    public void push(T v) {
        storage.addFirst(v);
    }
    public T peek() {
        return storage.getFirst();
    }
    public T pop() {
        return storage.removeFirst();
    }
    public boolean empty() {
        return storage.isEmpty();
    }
    public String toString() {
        return storage.toString();
    }
}

栈和队列都可以用顺序存储和链式存储来实现,官方的栈是继承与Vector类实现的。本文中使用链式存储实现栈。

首先定义节点Node类,其中的指针域、数据域和构造方法都采用默认的包访问权限:

public class Node<E> {
    Node<E> next;   // 指针域
    E data;     // 数据域
    Node() {}
    Node(Node<E> next, E data) {
        this.next = next;
        this.data = data;
    }
}

然后便是Stack类,实现了文档中给出的几个方法:

public class Stack<E> {
    private Node<E> top;   // 指向栈顶的指针
    private int size;   // 栈的大小
    public boolean empty() {
        return size == 0;
    }
    public E peek() {
        return top.data;
    }
    public E push(E item) {
        Node<E> tempNode = new Node<E>();
        tempNode.data = item;
        tempNode.next = top;
        top = tempNode;
        size++;
        return item;
    }
    public E pop() {
        if(size > 0) {
            E temp = top.data;
            top = top.next;
            size--;
            return temp;
        }
        return null;
    }
    public int search(Object o) {
        int i = 1;
        for(Node<E> cur = top; cur.data != o; cur = cur.next)
            i++;
        if(i == 0) return -1;
        return i;
    }
}

进行测试:

public class Test {
    public static void main(String[] args) {
        Stack<Integer> s = new Stack<Integer>();
        for(int i=0;i<5;i++)
            System.out.print(s.push(i)+" ");
        System.out.println();
        System.out.println(s.search(3));
        while(!s.empty()) {
            System.out.print(s.peek()+" "+s.pop()+" ");
        }
    }
}
// 输出结果:
0 1 2 3 4 
2
4 4 3 3 2 2 1 1 0 0 



队列的实现

队列也是一种典型的线性数据结构,数据只能从队尾插入,从队头弹出,符合“先进先出”的规则。

JDK 11的文档显示,Queue只是一个接口(interface),如果要使用可以用LinkedList向上转型而来,其中需要实现的方法有:

Modifier and TypeMethodDescription
booleanadd(E e)Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions, returning true upon success and throwing an IllegalStateException if no space is currently available.
Eelement()Retrieves, but does not remove, the head of this queue.
booleanoffer(E e)Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions.
Epeek()Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
Epoll()Retrieves and removes the head of this queue, or returns null if this queue is empty.
Eremove()Retrieves and removes the head of this queue.

节点使用和Stack中相同的节点类,这里只实现了比较基本的功能。Queue类:

package Linear;

public class Queue<E> {
    private Node<E> front, rear;    // 指向队首和队尾的指针
    private int size;   // 队列的大小
    public boolean empty() {
        return size == 0;
    }
    public E peek() {   // 返回队首数据
        return front.data;
    }
    public void offer(E e) {    // 在队尾添加元素
        Node<E> tempNode = new Node<E>();
        tempNode.data = e;
        if(size == 0) { // 队列为空的情况
            front = rear = tempNode;
        }
        else {
            rear.next = tempNode;
            rear = tempNode;
        }
        size++;
    }
    public E poll() {
        if(size > 0) {
            E temp = front.data;
            if(front == rear) { // 只有一个元素的情况
                front = rear = null;
            }
            else {
                front = front.next;
            }
            size--;
            return temp;
        }
        return null;
    }
}

测试:

package Linear;

public class Test {
    public static void main(String[] args) {
        Queue<Integer> q = new Queue<Integer>();
        for(int i=0;i<5;i++)
            q.offer(i);
        while(!q.empty()) {
            System.out.print(q.peek()+" "+q.poll()+" ");
        }
    }
}
//  输出结果:
0 0 1 1 2 2 3 3 4 4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值