栈和队列

  • 栈是一种线性结构,相比数组
  • 他对应的操作是数组的子集
  • 只能从一端进入,也只能从一端取出
  • 这一端成为栈顶

栈是一种先进后出的数据结构,Last In First Out(LIFO)

  • 程序调用的系统栈
  • 栈的应用:无处不在的Undo操作(撤销)

栈的实现

Stack<E>

  • void push(E)
  • E pop()
  • E peek()
  • int getSize()
  • boolean isEmpty()

将自己写的栈设置为接口,然后用第一天的动态数组实现这个接口。因为有了上一个自己做的动态数组,所以栈的形

成是非常方便的。

public class ArrayStack<E> implements Stack<E> {

    DynamicArray<E> array;

    public ArrayStack(int capacity){
array = new DynamicArray<E>(capacity);
} public ArrayStack(){
array = new DynamicArray<E>();
} @Override
public int getSize() {
return array.getSize();
} @Override
public void push(E e) {
array.addLast(e);
} @Override
public boolean isEmpty() {
return array.isEmpty();
} @Override
public E pop() {
return array.removeLast();
} @Override
public E peek() {
return array.getLast();
} public int getCapacity(){
return array.capacity();
} @Override
public String toString(){
StringBuilder builder = new StringBuilder();
builder.append("stack:");
builder.append("[");
for (int i = 0; i < array.getSize(); i++) {
builder.append(array.get(i));
if(i != array.getSize()-1){
builder.append(", ");
}
}
builder.append("] top");
return builder.toString();
}

时间复杂度都是O(1),其中,push和pop都是均摊为O(1)

队列

队列也是一个线性结构,有队首和队尾。先进先出。我们自己去编写一个队列。要实现以下方法

  • void enqueue(E)
  • E dequeue()
  • E getFront()
  • int getSize()
  • boolean isEmpty()
public interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
} public class ArrayQueue<E> implements Queue<E>{ private DynamicArray array; public ArrayQueue(int capacity) {
array = new DynamicArray<>(capacity);
} public ArrayQueue() {
array = new DynamicArray();
} @Override
public int getSize() {
return array.getSize();
} @Override
public boolean isEmpty() {
return array.isEmpty();
} @Override
public void enqueue(E e) {
array.addLast(e);
} public int getCapacity(){
return array.capacity();
} @Override
public E dequeue() {
return (E) array.removeFirst();
} @Override
public E getFront() {
return null;
} @Override
public String toString(){
StringBuilder builder = new StringBuilder();
builder.append("Queue:");
builder.append("front [");
for (int i = 0; i < array.getSize(); i++) {
builder.append(array.get(i));
if(i != array.getSize()-1){
builder.append(", ");
}
}
builder.append("]");
return builder.toString();
}
}

写完这个队列我们发现,这个队列,出队列的时间复杂度是O(n),严重的影响了运算效率,所以我们利用指针,指出

首尾指针,所以维护指针就可以了。所以,基于这样的想法,我们就想出了循环队列的队列。

front == tail 队列为空

( tail +1 )% c== front 队列满

在capacity中,浪费了一个空间。

package Queue;

/**
* @author shkstart
* @create 2019-11-25 20:05
*/
public class LoopQueue<E> implements Queue<E> { private E[] data; private int front, tail; private int size; public LoopQueue(int capacity) {
data = (E[]) new Object[capacity + 1];
front = 0;
tail = 0;
size = 0;
} public LoopQueue() {
this(10);
} public int getCapacity() {
return data.length - 1;
} @Override
public int getSize() {
return size;
} /**
* 判断是否为空的条件
*
* @return
*/
@Override
public boolean isEmpty() {
return tail == front;
} /**
* 如队列的操作!一定不要忘了循环队列维护
*
* @param e
*/
@Override
public void enqueue(E e) {
if ((tail + 1) % data.length == front) {//队列满
resize(getCapacity() * 2);
} data[tail] = e;
tail = (tail + 1) % data.length;
size++;
} private void resize(int newCapacity) {
E[] newdata = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newdata[i] = data[(front + i) % data.length]; data = newdata;
front = 0;
tail = size;
}
} @Override
public E dequeue() { if (isEmpty()) {
throw new IllegalArgumentException("Cannot dequeue from an empty queue");
}
E ret = data[front];
data[front] = null;
front = (front + 1) % data.length;
size--;
if (size == getCapacity() / 4 && getCapacity() / 2 != 0) {
resize(getCapacity() / 2);
}
return ret;
} @Override
public E getFront() {
if (isEmpty()) {
throw new IllegalArgumentException("Cannot dequeue from an empty queue");
}
return data[front];
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
res.append(String.format("Queue: size = %d , capacity = %d\n", size, getCapacity()));
res.append("front [");
for(int i = front ; i != tail ; i = (i + 1) % data.length){
res.append(data[i]);
if((i + 1) % data.length != tail)
res.append(", ");
}
res.append("] tail");
return res.toString();
}
public static void main(String[] args) {
LoopQueue<Integer> arrayQueue = new LoopQueue<Integer>();
for (int i = 0; i < 10; i++) {
arrayQueue.enqueue(i);
System.out.println(arrayQueue);
if(i % 3 == 2){
arrayQueue.dequeue();
System.out.println(arrayQueue);
}
}
}
}

学习数据结构Day3的更多相关文章

  1. SqList *L 和 SqList * &L的区别/学习数据结构突然发现不太懂 小祥我查找总结了一下

    小祥在学习李春葆的数据结构教程时发现一个小问题,建立顺序表和输出线性表,这两个函数的形参是不一样的. 代码在这里↓↓↓ //定义顺序表L的结构体 typedef struct { Elemtype d ...

  2. Spark菜鸟学习营Day3 RDD编程进阶

    Spark菜鸟学习营Day3 RDD编程进阶 RDD代码简化 对于昨天练习的代码,我们可以从几个方面来简化: 使用fluent风格写法,可以减少对于中间变量的定义. 使用lambda表示式来替换对象写 ...

  3. 在Object-C中学习数据结构与算法之排序算法

    笔者在学习数据结构与算法时,尝试着将排序算法以动画的形式呈现出来更加方便理解记忆,本文配合Demo 在Object-C中学习数据结构与算法之排序算法阅读更佳. 目录 选择排序 冒泡排序 插入排序 快速 ...

  4. 数据结构之Queue | 让我们一块来学习数据结构

    前面的两篇文章分别介绍了List和Stack,下面让我们一起来学习Queue 数据结构之List | 让我们一块来学习数据结构 数据结构之Stack | 让我们一块来学习数据结构 队列的概况 队列是一 ...

  5. 数据结构之LinkedList | 让我们一块来学习数据结构

    highlight: monokai theme: vue-pro 上一篇文章中使用列表(List)对数据排序,当时底层储存数据的数据结构是数组.本文将讨论另外一种列表:链表.我们会解释为什么有时链表 ...

  6. 数据结构之Set | 让我们一块来学习数据结构

    数组(列表).栈.队列和链表这些顺序数据结构对你来说应该不陌生了.现在我们要学习集合,这是一种不允许值重复的顺序数据结构.我们将要学到如何创建集合这种数据结构,如何添加和移除值,如何搜索值是否存在.你 ...

  7. MySQL 学习 --- 数据结构和索引

    本文参考了多篇文章集成的笔记,希望各位学习之前可以阅读以下参考资料先 概述 文章分几个部分 :第一部分介绍了B-Tree 和 B+Tree 这种数据结构作为索引:第二部分介绍索引的最左前缀原则和覆盖索 ...

  8. 省选算法学习-数据结构-splay

    于是乎,在丧心病狂的noip2017结束之后,我们很快就要迎来更加丧心病狂的省选了-_-|| 所以从写完上一篇博客开始到现在我一直深陷数据结构和网络流的漩涡不能自拔 今天终于想起来写博客(只是懒吧.. ...

  9. 学习数据结构Day1

    数据结构的分类: 线性结构 数组:栈:队列:链表:哈希表:... 树结构 二叉树:二分查找树:AVL;红黑树:Treap:Splay:堆:栈:Trie:线段树:K-D树:并查集:哈夫曼         ...

随机推荐

  1. 爬虫 - 解析库之Beautiful Soup

    了解Beautiful Soup 中文文档: Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式 ...

  2. Spring框架的JDBC模板技术和事物

    Spring框架的JDBC模板技术         技术分析之Spring框架的JDBC模板技术概述  1. Spring框架中提供了很多持久层的模板类来简化编程,使用模板类编写程序会变的简单     ...

  3. po模式

    一条测试用例可能需要多个步骤操作元素,将每一个步骤单独封装成一个方法,在执行测试用例时调用封装好的方法进行操作.PO模式可以把一个页面分为三个层级,对象库层.操作层.业务层. 对象库层:封装定位元素的 ...

  4. 限流神器之-Guava RateLimiter 实战

    前段时间,项目中需要对某些访问量较高的路径进行访问并发数控制,以及有些功能,比如Excel导出下载功能,数据量很大的情况下,用户不断的点击下载按钮,重复请求数据库,导致线上数据库挂掉.于是在这样的情况 ...

  5. vue子组件与子组件之前传值-----最简单办法

    1.在main.js中定义一个值(红色为重点) new Vue({ el: '#app', data: { Bus: new Vue() }, router, store, render: h =&g ...

  6. 缺陷的严重程度(Severity)

    该bug对用户造成的影响有多大.(1)Urgent 死机重启等致命bug(2)Veryhigh 非常严重的bug(3)High 严重的bug(4)Medium 中等程度的bug(5)Low 小的bug

  7. ELK平台搭建及日志监控

    一.使用背景 当生产环境有很多服务器.很多业务模块的日志需要每时每刻查看时 二.环境 系统:centos 6.5 JDK:1.8 Elasticsearch-5.0.0 Logstash-5.0.0 ...

  8. 2019 SDN第五次上机作业

    2019 SDN第五次上机作业 作业链接 1.浏览RYU官网学习RYU控制器的安装和RYU开发入门教程,提交对于教程代 码的理解,包括但不限于: 安装RYU控制器并测试 安装教程 安装过程及遇到各种问 ...

  9. Tomcat启动时,控制台和IDEA控制台中文乱码解决方案

    Tomcat启动时 控制台中文乱码 cmd控制台 IDEA控制台 解决方案 cmd乱码 打开Tomcat目录下的apache-tomcat-8.5.47\conf\logging.properties ...

  10. freeNAS nfs linux挂载

    新建存储块,设置权限为root wheel 备份修改/var/lib/nova 名称 新建/var/lib/nova 目录,修改目录的属主机权限 mv /var/lib/nova /var/lib/n ...