数据结构之栈和队列
发布日期:2021-08-16 13:27:51 浏览次数:49 分类:技术文章

本文共 6102 字,大约阅读时间需要 20 分钟。

  其实栈和队列是特殊的线性表,特殊之处在于插入和删除的位置受到限制,如果插入和删除只在一端进行,那么这就是栈,如果插入在尾部进行,删除在头部进行就是队列,下面我们具体来看看栈和队列的实现。

1:栈

定义:栈是一种特殊的线性表,其插入和删除只能在一端进行,允许操作的一端叫做栈顶,不允许操作的一端叫做栈底。插入元素我们叫做进栈(push),删除元素我们叫做出栈(pop)。下面我们定义栈的接口

public interface SStack
{ /** * 验证是否是空栈 * @return */ boolean isEmpty(); /** * 进栈 * @param x */ void push(T x); /** * 出栈 * @return */ T pop(); /** * 取栈顶元素 * @return */ T get();}

2:顺序表实现栈

要实现栈,首先我们需要一个变量来记录栈顶的位置,这个变量我们设置top。我们定义top初始值为-1,也就是说当栈空的时候top就是-1。栈的特点就是先进后出,那么进栈就很简单了,我们只需要让top++即可,然后取得时候只需要去top对应的元素,后进去的就先出来,先进去的后出来。代码如下

private Object[] elements;    private int top;//记录栈顶元素位置    public SeqStack() {        this(64);    }    public SeqStack(int size) {        this.elements = new Object[size];        this.top = -1;    }    public boolean isEmpty() {        return this.top == -1;    }    public void push(T x) {        if (x == null) {            return;        }        if (this.top == this.elements.length - 1) {            Object[] temp = this.elements;            this.elements = new Object[2 * this.elements.length * 2];            for (int i = 0; i < this.top; i++) {                this.elements[i] = temp[i];            }        }        this.top++;        this.elements[this.top] = x;    }    public T pop() {        return this.top == -1 ? null : (T) this.elements[this.top--];    }    public T get() {        return this.top == -1 ? null : (T) this.elements[this.top];    }

3:链式表实现栈

链式实现更新的简单了,同样我们只需要用一个头节点来记录栈顶即可,如果头节点为空说明是空栈,出栈的时候只需求去头节点,入栈的时候,把新元素赋值给头元素,头元素的后继节点为原先的头节点即可。代码如下

public Node
top; public LinkedStack(){ top=new Node
(null,null); } public LinkedStack(T[] elements) { if (elements == null) { return; } for (int i = 0; i < elements.length; i++) { this.top = new Node
(elements[i], this.top); } } public boolean isEmpty() { return this.top == null; } public void push(T x) { if (x==null){ return; } this.top=new Node
(x,this.top); } public T pop() { if (this.top != null) { T old = this.top.data; this.top = this.top.next; return old; } return null; } public T get() { return this.top == null ? null : this.top.data; }

4:栈的应用

我们经常写代码应该知道当我们写方法的时候少一个}编译器会立马报异常,现在我们考虑是如何实现的。

假设这个一个字符串,我们遇到{号的时候把它放入栈中,如果遇到}号的时候就出栈,如果出栈的是{则说明一对{}匹配成功,如果栈空,或者不是{表示缺少与}相匹配的{符合,如果最后栈不为null,说明缺少}号。我们来实现下。

public static boolean isValid(String str) {        SStack
characterSStack = new SeqStack
(str.length()); boolean result=true; for (int i = 0; i < str.length(); i++) { char ch = str.charAt(i); switch (ch) { case '{': characterSStack.push(ch); break; case '}': boolean a = characterSStack.isEmpty(); boolean b = characterSStack.get() != '{'; if (a || b) { result = false; } characterSStack.pop(); break; } if (!result) { break; } } if (!characterSStack.isEmpty()) { result=false; } return result; }

 5:队列

队列我们说了只可以在队列和队尾操作,队尾我们加入元素,队列我们删除元素,没有元素我们称为空队列。下面先定义接口

public interface Queue
{ /** * 验证队列是否为空 * @return */ boolean isEmpty(); /** * 入队 * @param x */ void enQueue(T x); /** * 出队 * @return */ T deQueue();}

6:顺序表实现队列

既然我们分别是在头和尾进行操作,那么我们就需要2个变量值来记录队列和队尾。我们分别用front、rear分别表示对列和队尾,如果我们加入第一个一个元素,rear和front都+1,其他的我们只需要rear+1,如果出对列同样我们让front+1,这样一来就满足我们的条件,但是问题是如果加入5个元素后rear=4,然后在出对列2个元素那么front=1;这样一来我们的队列就无法全部运用上,出现了假溢出。所以我们考虑采用循环的队列模式。具体实现如下

public class SeqQueue
implements Queue
{ private Object[] elements; private int rear;//队尾 private int front;//队头 public SeqQueue() { this(64); } public SeqQueue(int length) { if (length <= 0) { return; } this.elements = new Object[length]; this.front = rear = 0; } public boolean isEmpty() { return this.front == this.rear; } public void enQueue(T x) { if (x == null) { return; } if ((this.rear + 1) % this.elements.length == this.front) { Object[] temp = this.elements; this.elements = new Object[2 * this.elements.length * 2]; int i = this.front, j = 0; while (i != this.rear) { this.elements[j] = temp[i]; i = (i + 1) % temp.length; j++; } this.front = 0; this.rear = j; } this.elements[this.rear] = x; this.rear = (this.rear + 1) % this.elements.length; } public T deQueue() { if (this.isEmpty()) { return null; } T old = (T) this.elements[this.front % this.elements.length]; this.front = this.front + 1 * this.elements.length; return old; }

7:链式实现对列

链式的就比较简单了,如果是队尾的话我们直接可以把rear的后继节点赋值为新元素,然后在把rear节点赋值为新元素。但是我们要考虑的是空表插入,这个时候就没有后继节点了,这个时候我们直接把新元素赋值给front即可。如果出队就更简单了,直接获取front即可。我们看下源码

public class LinkedQueue
implements Queue
{ private Node
front; private Node
rear; public boolean isEmpty() { return this.front == this.rear && this.front == null; } public void enQueue(T x) { if (x == null) { return; } Node
p = new Node
(x, null); if (this.front == null) { this.front = p; } else { this.rear.next = p; } this.rear = p; } public T deQueue() { if (this.front == null) { return null; } T old = this.front.data; this.front = this.front.next; return old; }

 

转载于:https://www.cnblogs.com/LipeiNet/p/6417752.html

转载地址:https://blog.csdn.net/weixin_30807779/article/details/98213787 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:java.io.IOException: Incompatible clusterIDs
下一篇:python的面向对象的特性(继承、封装、多态)

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月03日 01时19分59秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章