数据结构和算法分析 表、栈和队列
表是ArrayList,LinkedList,Stack,Queue的抽象定义。我理解为有序的单数据存储。
remove方法对LinkedList类的使用
模拟一个场景,遍历一个LinkedList,将其中存储的数值是偶数的都删除。
- 方法一:通过下标i进行for循环,如果发现是偶数,然后使用remove(i)进行删除。这种方法的时间复杂度是O(N2),因为外层遍历的复杂度是N,内存要进行get(i)和remove(i)他们的复杂度都是N。
- 方法二:使用增强for循环,会产生异常:增强for循环在循环的过程中,使用iterator,但是由于没有在iterator中使用remove,而是使用list.remove方法,这种是不会被iterator识别到的。所以有如下要求:增强型的for循环过程中,不能删除数据。
- 方法三:使用iterator。iterator.hashNext, iterator.next, iterator.remove,因为iterator在remove的时候,已经定位到了要删除的链表元素位置,所以删除操作的复杂度为O(1),整个实现的时间复杂度为O(N)。
ListIterator
ListIterator在Iterator(hasNext,next,remove)的基础上增加了hasPrevious,previous,add,set方法。
ArrayList的iterator方法返回一个ListIterator对象,是通过内部类来实现的。整个private的私有(非static)内部类可以访问外部类的数组和size等属性,可以简单的实现,next,hashnext等各种操作。
java的LinkedList是双向链表实现。在做get(i)操作的时候,会判断i和size/2的比较,然后选择从head还是tail开始进行遍历。
栈
java集合库中设计的栈没有接口,就是一个Stack类,而且它继承自Vector类,是使用监视器锁实现的。比较重量级。如下是Stack的反编译后的代码:
如果不想使用这么重量级的,可以使用ArrayList和LinkedList模拟Stack的操作,或者使用Deque接口来模拟也可以。
如果要自定义一个Stack类,可以通过数组和链表来实现。
简单是数组实现:
-
package com.zjf;
-
-
public class MyArrayStack<E> {
-
-
public final static int initSize = 32;
-
private Object[] arr;
-
private int top = 0;
-
-
public static void main(String[] args) {
-
// TODO Auto-generated method stub
-
-
}
-
-
public MyArrayStack() {
-
arr = new Object[initSize];
-
}
-
-
public void push(E element) {
-
if ((top + 1) >= initSize) {
-
resizeArray();
-
}
-
arr[top] = element;
-
top++;
-
}
-
-
public E pop() {
-
if (top == 0) {
-
throw new RuntimeException("没有数据");
-
}
-
E element = (E) arr[top];
-
top--;
-
return element;
-
}
-
-
// 如果超出空间
-
private void resizeArray() {
-
-
}
-
-
}
栈的应用:
平衡符号:编译器检查程序的语法错误。
表达式求值:用于计算中:中缀表达式向后缀表达式的转换。
队列
队列的数组实现,我的大概思路:
使用循环数组,维护int变量head和tail,标识头尾,arr数组用来存储数据,插入到++tail位置,取出从head—中取。如果插入到了数组最后一个,空间不足,那么从0开始循环(要判断head的位置 如果空间不足就要扩充)。
我们习惯用自己的行为准则审视他人,并时刻准备加以指摘。