《Java数据结构和算法》学习笔记(3)——栈和队列
来源:互联网 发布:js数组怎么删除元素 编辑:程序博客网 时间:2024/05/21 22:55
每篇笔记都会附上随书的Applet演示程序,有算法看不明白的,可以下载Applet运行起来(直接打开html文件即可),可以很容易地看清楚算法的每一步。
栈是一种先进后出(FILO)的线性数据结构,先进后出的意思就是……举个例子吧,我先把1放进一个栈里,再把2放进去,最后把3放进去,取出来的时候只能先得到3,再取能得到2,最后是1。栈一次只允许访问一个数据项(最顶端的那个),常用操作有入栈(push,把数据压入栈里)和出栈(pop,把顶端的数据从栈里弹出),peek用于查看栈顶数据。
下面是一个简单的栈的实现
- package dsaa.array;
- import java.util.EmptyStackException;
- /**
- * @(#)Stack.java 2008-12-26 下午03:41:57
- *
- * @author Qiu Maoyuan
- * Stack
- */
- public class Stack<E> {
- private Object[] stackArray;
- private int topIndex = -1;
- private int size = 0;
- public Stack(){
- stackArray = new Object[10];
- }
- public Stack(int size){
- stackArray = new Object[size];
- }
- public void push(E value){
- ensureCapacity();
- stackArray[++topIndex] = value;
- size++;
- }
- @SuppressWarnings("unchecked")
- public E peek(){
- if(topIndex==-1)
- throw new EmptyStackException();
- return (E)stackArray[topIndex];
- }
- public E pop(){
- E value = peek();
- topIndex--;
- size--;
- return value;
- }
- public boolean isEmpty(){
- return size==0;
- }
- private void ensureCapacity() {
- if(size==stackArray.length){
- Object[] newArray = new Object[size * 3 / 2 + 1];
- System.arraycopy(stackArray, 0, newArray, 0, size);
- stackArray = newArray;
- }
- }
- }
在给一个数组或者字符串进行反向排序的时候,栈是一个不错的工具:
- Stack<Character> stack = new Stack<Character>();
- String input = "hello stack!";
- for(int i=0; i<input.length(); i++)
- stack.push(input.charAt(i));
- StringBuilder buffer = new StringBuilder();
- while(!stack.isEmpty()){
- buffer.append(stack.pop().charValue());
- }
- String output = buffer.toString();
- System.out.println(output);
利用栈还可以实现回文判断、词法分析等功能。
显而易见,栈的push和pop操作的时间复杂度为O(1)。
队列是一种先进先出(FIFO)的线性数据结构,常用操作有插入(insert)和删除(remove)。
一个简单的队列实现如下:
- package dsaa.array;
- /**
- * @(#)Queue.java 2008-12-27 上午01:21:46
- *
- * @author Qiu Maoyuan
- * Queue
- */
- public class Queue<E> {
- private Object[] queueArray;
- private int head = 0;
- private int tail = -1;
- public Queue(int size){
- queueArray = new Object[size];
- }
- @SuppressWarnings("unchecked")
- public E peek(){
- if(isEmpty())
- throw new IllegalStateException("Queue is empty");
- return (E)queueArray[head];
- }
- public void insert(E value){
- if(isFull())
- throw new IllegalStateException("Queue is full");
- queueArray[++tail] = value;
- }
- public E remove(){
- E value = peek();
- head++;
- return value;
- }
- public boolean isEmpty(){
- return tail - head == -1;
- }
- public boolean isFull(){
- return tail == queueArray.length-1;
- }
- }
以上队列存在一个问题,队列满了以后,无论删除掉多少个数据项,甚至清空这个队列,仍然不能插入新的数据。其实有一种解决方法就是,在删除数据项的时候,后面的所有数据项都往前移动,但这样效率很低。
为了避免队列不满却不能插入新数据项的问题,可以让队头队尾指针绕回到数组开始的位置,这样的队列叫循环队列。
改进后的代码如下:
- package dsaa.array;
- /**
- * @(#)Queue.java 2008-12-27 上午01:21:46
- *
- * @author Qiu Maoyuan
- * Queue
- */
- public class Queue<E> {
- private Object[] queueArray;
- private int head = 0;
- private int tail = -1;
- private int elementsCount = 0;
- public Queue(int size){
- queueArray = new Object[size];
- }
- @SuppressWarnings("unchecked")
- public E peek(){
- if(isEmpty())
- throw new IllegalStateException("Queue is empty");
- return (E)queueArray[head];
- }
- public void insert(E value){
- if(isFull())
- throw new IllegalStateException("Queue is full");
- if(tail == queueArray.length - 1){
- tail = 0;
- queueArray[tail] = value;
- }else{
- queueArray[++tail] = value;
- }
- elementsCount++;
- }
- public E remove(){
- E value = peek();
- if(head == queueArray.length - 1){
- head = 0;
- }else{
- head++;
- }
- elementsCount--;
- return value;
- }
- public boolean isEmpty(){
- return elementsCount == 0;
- }
- public boolean isFull(){
- return elementsCount == queueArray.length;
- }
- }
队列的效率和栈一样,插入和删除数据项的时间复杂度均为O(1)。
还有一种队列叫做双端队列,顾名思义就是对两端都可以进行插入、删除操作的队列。如果封闭了其中一端,它就变成了一个栈;如果只允许一端插入,另一端删除,那它就成了一个普通队列。
优先级队列和普通队列的不同之处是:它在插入数据时是有序的。所以优先级队列的插入效率会比较低,时间复杂度为O(N),删除操作则为O(1)。
- package dsaa.array;
- /**
- * @(#)PriorityQueue.java 2008-12-27 下午01:03:01
- *
- * @author Qiu Maoyuan
- * Priority Queue
- */
- public class PriorityQueue {
- private int[] queueArray;
- private int head = -1;
- public PriorityQueue(int initialCapacity){
- queueArray = new int[initialCapacity];
- }
- public void insert(int value){
- if(isFull())
- throw new IllegalStateException("Queue is full");
- if (isEmpty()){
- queueArray[++head] = value;
- } else {
- int i=head;
- while (i>-1){
- if (queueArray[i]>value){
- queueArray[i + 1] = queueArray[i];
- } else {
- break;
- }
- i--;
- }
- queueArray[i + 1] = value;
- head++;
- }
- }
- public boolean isFull(){
- return head == queueArray.length - 1;
- }
- public boolean isEmpty(){
- return head == -1;
- }
- public int remove(){
- int value = peek();
- head--;
- return value;
- }
- public int peek(){
- if(isEmpty())
- throw new IllegalStateException("Queue is empty");
- return queueArray[head];
- }
- }
- 《Java数据结构和算法》学习笔记(3)——栈和队列
- Java数据结构和算法——队列
- Java之数据结构基础、线性表、栈和队列、数组和字符串,树—学习笔记
- Java之数据结构基础、线性表、栈和队列、数组和字符串,树—学习笔记
- [算法学习笔记]数据结构之栈和队列
- 数据结构与算法(java)——栈和队列
- Java 数据结构和算法 栈和队列
- 数据结构学习笔记——栈和队列
- Java数据结构和算法--栈与队列
- Java数据结构和算法--栈与队列
- Java数据结构和算法--栈与队列
- Java数据结构和算法-栈和队列(2-队列)
- 数据结构之队列和栈学习笔记
- JAVA数据结构——队列和栈
- 【Java】Java数据结构和算法(二)——栈和队列
- Java数据结构和算法(五)——队列
- Java数据结构和算法(五)——队列
- Java数据结构和算法-栈和队列(3-优先级队列)
- 写给奔三的80后们
- SAP Deployment supporting Engineer 访谈录
- linq to sql 详
- 一道趣味数学题 c# 版 欢迎拍砖
- SQL语句学习手册实例版
- 《Java数据结构和算法》学习笔记(3)——栈和队列
- 进嵌入式的建议
- 求职的建议
- 关于BREW中回调函数的一些讲解
- 内部试用 dog food
- ./mysql/user is marked as crashed 解决办法
- 转载 语言与思想
- Ajax中send参数
- Oracle索引管理常用操作