栈和队列的实现

本文主要讲栈和队列的实现方法,所以仅简单介绍栈和队列的概念,如果有疑问可以去查有关栈和队列的详细资料。

栈 Stack(LIFO线性表):
栈是一种特殊的线性表,满足后进先出,它限定仅可以在表尾进行删除和增加。push(), pop(), peek(),empty()是它的三个重要的方法。push()是往栈里压入一个元素;pop()是弹出栈顶元素,栈顶指针指向下一个元素;peek()是返回栈顶元素,但不删除栈顶元素;empty是判断栈是否为空。

队列 Queue(FIFO线性表):
队列也是一种特殊的线性表,与栈的规则相反,它满足先进先出原则,它限定只能在表尾添加元素,在表头删除元素。它的基本操作有offer(),poll(),peek()。offer()为在表尾添加一个元素,poll()为在表头删除一个元素,peek()为得到表头的元素,但不删除此元素。对于队列对应的还有三个操作 add(),remove(),element(),这三个操作可以完成相同的功能,但是如果后者操作失败会抛出异常,而前者返回具体的值(null,false等,要看具体的操作)。

***
不过请大家记住一点,不是所有的队列都是FIFO,比如优先队列,它是根据各元素的优先级来决定顺序的。

了解了栈和队列的基本操作,下面我们学习它们的具体实现。

1. Stack类的实现
JDK中写道,Stack类是继承了Vector类, Vector类在java中可以实现自动增长的动态数组。在这里我们用一个普通的对象数组来实现Stack类。代码如下:

public class Stack {

private int top;
private Object[] data;

//初始化堆栈
public Stack(int size){
data = new Object[size];
top = -1;
}

public boolean empty(){
return top == -1;
}

public void push(Object object) {
if(top == data.length-1){
System.out.println("栈满");
}
data[++top] = object;
}

public Object pop() {
if(top == -1){
System.out.println("栈空");
return null;
}
return data[top--];
}

public Object peek() {
if(data == null || data.length == 0)
return null;
return data[data.length-1];
}
}


这是堆栈最基本的实现,可能面试中可能会遇到其他问题,比如实现一个动态堆栈,当然在JDK中用vector类实现的堆栈本身就是动态堆栈,因为vector类可以实现可变长数组。对于普通对象数组长度是不可变的,上面的代码仅仅实现了一个固定长度的堆栈,如需改成动态堆栈,我们只需要改进push()方法,其他方法保持一致。改进后的push()方法:

public void push(Object object) {
if(top == data.length-1){
Object temp[] = new Object[data.length * 2]; // 把数组的容量增加一倍
for(int i=0; i<data.length; i++) temp[i] = data[i];
data = temp;
data[++top] = object;
}
data[++top] = object;
}


我们还可以用链表来实现堆栈,代码如下:
//首先定义一个链表类

class ListNode{
Object object;
ListNode next;
ListNode(Object object){
this.object = object;
}
}

public class Stack {
ListNode head;

public void push(Object object) {
ListNode node = new ListNode(object);
node.next = head;
head = node;
}

public Object pop() {
if(head != null) {
Object element = head.object;
head = head.next;
return element;
}
return null;
}

public Object peek() {
return head.object;
}

public boolean empty() {
return head == null;
}
}


2. 队列的实现
首先我们要搞清楚,队列是接口不是类,它不可以实例化,也就是不可以new queue(),接口的使用必须依赖于实现它的类,对于接口的引用,采用的是实例化实现该接口的类。下面我们用链表来实现一个队列。

class ListNode{
Object object;
ListNode next;
ListNode(Object object){
this.object = object;
}
}
public class QueueDemo {
ListNode head;
ListNode tail;

public void offer(Object object) {
if(head == null){
tail = new ListNode(object);
head = tail;
} else {
tail.next = new ListNode(object);
tail=tail.next;
}
}

public Object poll() {
if(head != null) {
Object element = head.object;
head = head.next;
if(head == null) tail = null;
return element;
}
return null;
}

public Object peek() {
if(head == null)
return null;
return head.object;
}
}


总结:我们用数组实现了固定长度的堆栈和动态堆栈,然后用链表分别实现了堆栈和队列。堆栈和队列之间也可以相互实现,只要记住队列是先进先出,只可以在队尾添加元素,在对头删除元素;堆栈是后进先出,只可以在表尾添加或删除元素。

以上只是个人总结,希望朋友们多多交流,共同进步!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值