数据结构(7)--队列
2016-09-03 18:19
120 查看
对于Queue这个词大家熟悉么?我相信学习Android对于这个词熟悉的程度可谓是极深,毕竟Android内部很多的实现都是靠着队列.Handler、service内部实现也是.其实在我们生活当中,队列的作用就类似于说,我们去排队打饭(原谅我这个吃货),肯定是有人从前面打完饭走了,有人从后面排队进来…这样就是一个队列,那么大家都可以看出其中的特点了吧.
队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作。
队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头。队列的插入操作通常称作入队列,队列的删除操作通常称作出队列。
英文为:FIFO—>First In First Out,先进先出,后进后出
注意:队列也是有有着头结点(front)和队尾结点(rear)的.
队列的顺序存储:
在顺序存储里面,我们会经常发生”假溢出”现象.
front指向头元素,rear指向尾元素的下一个位置.因为顺序队列是限定个数,所以一旦前面的全部出去了,front后移,但是后面的插进来,会发现越界,但是实际上前面还有空位.这就是假溢出.
解决假溢出,就需要通过循环队列,循环队列的意思就是头尾相接,但是头尾相接又会出现一个循环有可能为空的问题,所以我们的解决方法是通过计数器的方法,来判定.
代码:
相信大家在查询的时候,会遇到一些类似与优先队列,其实优先队列的实现是差不多的,基本上就是我们逻辑上会多出一个优先级变量来设定优先级.
面试题:
设计含最小函数min()的栈,要求min、push、pop、的时间复杂度都是O(1)?
思路:
这里需要加一个辅助栈,用空间换取时间。辅助栈中,栈顶永远保存着当前栈中最小的数值。具体是这样的:原栈中,每次添加一个新元素时,就和辅助栈的栈顶元素相比较,如果新元素小,就把新元素的值放到辅助栈中,如果新元素大,就把辅助栈的栈顶元素再copy一遍放到辅助栈的栈顶;
重点方法:
minStack.peek()—>获取栈顶元素.
队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作。
队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头。队列的插入操作通常称作入队列,队列的删除操作通常称作出队列。
英文为:FIFO—>First In First Out,先进先出,后进后出
注意:队列也是有有着头结点(front)和队尾结点(rear)的.
队列的顺序存储:
在顺序存储里面,我们会经常发生”假溢出”现象.
front指向头元素,rear指向尾元素的下一个位置.因为顺序队列是限定个数,所以一旦前面的全部出去了,front后移,但是后面的插进来,会发现越界,但是实际上前面还有空位.这就是假溢出.
解决假溢出,就需要通过循环队列,循环队列的意思就是头尾相接,但是头尾相接又会出现一个循环有可能为空的问题,所以我们的解决方法是通过计数器的方法,来判定.
代码:
public class ListQueue { static final int defaultSize = 10; //默认队列的长度 int front; //队头 int rear; //队尾 int count; //统计元素个数的计数器 int maxSize; //队的最大长度 Object[] queue; //队列 public ListQueue() { init(defaultSize); } public ListQueue(int size) { init(size); } public void init(int size) { maxSize = size; front = rear = 0; count = 0; queue = new Object[size]; } public void append(Object obj) throws Exception { // TODO Auto-generated method stub if (count > 0 && front == rear) { throw new Exception("队列已满!"); } //添加到尾节点 queue[rear] = obj; rear = (rear + 1) % maxSize; count++; } //从头结点删除,并且作为一个循环了实用front public Object delete() throws Exception { // TODO Auto-generated method stub if (isEmpty()) { throw new Exception("队列为空!"); } Object obj = queue[front]; front = (front + 1) % maxSize; count--; return obj; } public Object getFront() throws Exception { // TODO Auto-generated method stub if (!isEmpty()) { return queue[front]; } else { return null; } } public boolean isEmpty() { // TODO Auto-generated method stub return count == 0; } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub ListQueue queue = new ListQueue(); queue.append("a"); queue.append("b"); queue.append("c"); queue.append("d"); queue.append("e"); queue.append("f"); queue.delete(); queue.delete(); while (!queue.isEmpty()) { System.out.println(queue.delete()); } } } 链式队列: 链式队列其实就是特殊的单链表,只不过它只能尾进头出而已.说到链式队列,我们第一想到的就是结点的不同,我们要安排结点的构造. 结点类我就不写了: 测试类:(主要关注我们的front rear的变化就好了) private QueueNode<T> front,rear;//声明两个结点 public LinkedQueue() { this(null); } //初始化结点 public LinkedQueue(T element) { if(element == null) { front = new QueueNode<T>(null); rear = front; }else { rear = new QueueNode<T>(element); front = new QueueNode<T>(null,rear); } } public int length(){ if(isEmpty()) return 0; int k=1; QueueNode<T> temp = front.getNext(); while(temp!=rear){ k++; temp=temp.getNext(); } return k; } //获取第一个元素 public T getHead() { if(isEmpty()) return null; return front.getNext().getData(); } //判断空 public boolean isEmpty() { return front == rear; } //加入元素,从后面加入 public boolean add(T element) { if(element == null) return false; QueueNode<T> temp = front; rear.setNext(new QueueNode<T>(element)); rear = rear.getNext(); return true; } //移除元素,前面走人,所以要对front进行修改 public T remove() { if(isEmpty()) return null; T element = front.getNext().getData(); if(length() == 1) rear = front; else{ front.setNext(front.getNext().getNext()); } return element; } //目标转换成字符串,拼接 public String toString() { if(isEmpty()) return "[ ]"; StringBuffer sb = new StringBuffer("[ "); QueueNode<T> temp = front.getNext(); while(temp != rear) { sb.append(temp+" "); temp = temp.getNext(); } sb.append(temp+" "); sb.append("]"); return sb.toString(); } public static void main(String[] args) { // TODO Auto-generated method stub LinkedQueue<String> queue = new LinkedQueue<String>("A"); System.out.println("queue="+queue+" queue.length="+queue.length()); queue.add("B"); System.out.println("queue="+queue+" queue.length="+queue.length()); System.out.println("the removint element="+queue.remove()); System.out.println("queue="+queue+" queue.length="+queue.length()); }
相信大家在查询的时候,会遇到一些类似与优先队列,其实优先队列的实现是差不多的,基本上就是我们逻辑上会多出一个优先级变量来设定优先级.
面试题:
设计含最小函数min()的栈,要求min、push、pop、的时间复杂度都是O(1)?
思路:
这里需要加一个辅助栈,用空间换取时间。辅助栈中,栈顶永远保存着当前栈中最小的数值。具体是这样的:原栈中,每次添加一个新元素时,就和辅助栈的栈顶元素相比较,如果新元素小,就把新元素的值放到辅助栈中,如果新元素大,就把辅助栈的栈顶元素再copy一遍放到辅助栈的栈顶;
重点方法:
minStack.peek()—>获取栈顶元素.
import java.util.Stack; /** * Created by smyhvae on 2015/9/9. */ public class MinStack { private Stack<Integer> stack = new Stack<Integer>(); private Stack<Integer> minStack = new Stack<Integer>(); //辅助栈:栈顶永远保存stack中当前的最小的元素 public void push(int data) { stack.push(data); //直接往栈中添加数据 //在辅助栈中需要做判断 if (minStack.size() == 0 || data < minStack.peek()) { minStack.push(data); } else { minStack.add(minStack.peek()); //【核心代码】peek方法返回的是栈顶的元素 } } public int pop() throws Exception { if (stack.size() == 0) { throw new Exception("栈中为空"); } int data = stack.pop(); minStack.pop(); //核心代码 return data; } public int min() throws Exception { if (minStack.size() == 0) { throw new Exception("栈中空了"); } return minStack.peek(); } public static void main(String[] args) throws Exception { MinStack stack = new MinStack(); stack.push(4); stack.push(3); stack.push(5); System.out.println(stack.min()); } }
相关文章推荐
- 数据结构——基本数据结构之队列
- 数据结构之顺序队列
- 【数据结构与算法基础】以数组实现的循环队列 / Circular Queue implemented by array
- 基础数据结构(栈,队列)
- [翻译]C#数据结构与算法 – 第五章栈与队列(Part 2)
- 数据结构之队列的实现(c语言)
- 数据结构:队列的实现
- 关于linux内核中 等待队列 数据结构之思考
- 关于linux内核中 等待队列 数据结构之思考
- 数据结构(三)——队列及实现、循环队列实现
- 数据结构:用队列模拟理发店的排队情况(C#)
- [翻译]C#数据结构与算法 – 第五章栈与队列(Part 1)
- 面向数据c++数据结构之基本数据结构(队列)--【美】Jan Harrington 陈博译
- 数据队列结构与操作
- [翻译]C#数据结构与算法 – 第五章栈与队列(Part 2)
- 数据结构之循环队列
- C#数据结构之队列
- 数据结构实现(队列类模板)
- 数据结构之表(7)队列的顺序实现
- 数据结构(五)——双链表、链式栈、链式队列 及实现