一、表
表有两种实现方式:数组实现和链表实现。
数组实现:表是通过在高端进行插入操作建成,且建成后主要是对表进行访问(查询)操作,而非插入、删除;
!!ArrayList类提供了可增长数组的实现。其优点:对get和set的调用花费常数时间;缺点:新项的插入和现有项的删除代价昂贵(除非变动在末端)。
链表实现:对表的操作主要是插入和删除,访问操作较少。
!!LinkedList类提供了List ADT的双链表实现。其优点:新项的插入和现有项的删除开销小(假设变动项位置已知);其缺点:不易于做索引,对get的调用代价昂贵。
补充Java Collections API中表的知识点:
(1)Collection接口扩展了Iterable接口。
实现Iterable接口的类可拥有增强的for循环;
实现Iterable接口的集合必须提供iterator方法(返回Iterator类型的对象)。
如果对正在被迭代的集合进行结构上的改变(除非调用迭代器自己的remove方法),那么迭代器将不再合法。
public static void removeEvensVer2(List<Integer> lst){
for(Integer x:lst){
if(x%2==0)
lst.remove(x);//抛出异常
}
}
(2)如果ArrayList的大小有早期估计,那么ensureCapacity可设置容量为足够大的量,避免后期扩展;再有,trimToSize可在所有的添加操作完成后使用,避免浪费空间。
(3)ListIterator扩展了List的Iterator功能。previous和hasPrevious使得对表从后向前遍历。
1.表的数组实现
1)数组是由固定容量创建的,但在需要时,可以扩展其容量;
int[] arr = new int[10];
//扩展数组arr
int[] newArr = new int[arr.length*2];
for(int i=0;i<arr.length;i++){
newArr[i] = arr[i];
}
arr = newArr;
2)实现代码
public class MyArrayList<Type> implements Iterable<Type> {
private static final int DEFAULT_CAPACITY = 10;//默认大小
private int theSize;
private Type[] theItems;
public MyArrayList(){
clear();
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return theSize==0;
}
//初始化
public void clear(){
theSize = 0;
ensureCapacity(DEFAULT_CAPACITY);
}
//查找
public Type get(int id){
if(id>=theSize || id<0){ //注意判断范围
throw new ArrayIndexOutOfBoundsException();
}
return theItems[id];
}
//更新
public Type set(int id,Type t){ //返回被替换的值
if(id>=theSize || id<0){ //注意判断范围
throw new ArrayIndexOutOfBoundsException();
}
Type old = theItems[id];
theItems[id] = t;
return old;
}
//删除
public Type remove(int id){
if(id>=theSize || id<0){ //注意判断范围
throw new ArrayIndexOutOfBoundsException();
}
Type old = theItems[id];
for(int i=id;i<theSize-1;i++){
theItems[i] = theItems[i+1];
}
theSize--;
return old;
}
//添加
public boolean add(Type t){
add(theSize,t);
return true;
}
public void add(int id,Type t){
/*while(id>=theItems.length){ //此处有疑问
ensureCapacity(2*theItems.length);
}*/
if(theItems.length == size()){
ensureCapacity(2*size()+1);
}
for(int i=theSize-1;i>=id;i--){
theItems[i+1] = theItems[i];
}
theItems[id] = t;
theSize++;
}
//设置容量
public void ensureCapacity(int newCapacity){
if(newCapacity<theSize){ //注意 判断适用性
return;
}
Type[] old = theItems;
//theItems = new Type[newCapacity];
theItems = (Type[]) new Object[newCapacity]; //注意 引用新数组 的创建
for(int i=0;i<theSize;i++){
theItems[i] = old[i];
}
}
public java.util.Iterator<Type> iterator(){
return new ArrayListIterator();
}
//内部类(编译器编写使内部类对象和外部类对象相关联所需的附加代码)
private class ArrayListIterator implements java.util.Iterator<Type>{
private int current = 0;
public boolean hasNext(){
//return current!=theSize;
return current<size();
}
public Type next(){
if(!hasNext()){ //判断
throw new java.util.NoSuchElementException();
}
return theItems[current++];
}
public void remove(){
MyArrayList.this.remove(--current);
}
}
}
2.表的链表实现(双链表)
public class MyLinkedList<AnyType> implements Iterable<AnyType> {
//Node类是private的,因此数据成员的可见性是无关紧要的。MyLinkedList外面的类不能访问Node类
private static class Node<AnyType>{
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
public Node(AnyType d,Node<AnyType> p,Node<AnyType> n){
data = d; prev = p; next = n;
}
}
private int theSize;
private int modCount = 0;//对链表所做改变的次数(add、remove)
private Node<AnyType> beginMarker;//头节点
private Node<AnyType> endMarker;//尾节点
public MyLinkedList(){
clear();
}
//初始化
public void clear(){
theSize = 0;
modCount++;
beginMarker = new Node<AnyType>(null,null,null);
endMarker = new Node<AnyType>(null,beginMarker,null);
beginMarker.next = endMarker;
/*endMarker = new Node(null,null,null);
beginMarker = new Node(null,null,endMarker);
endMarker.prev = beginMarker;*/
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return theSize == 0;
}
//添加
public boolean add(AnyType x){
add(theSize,x);
return true;
}
public void add(int idx,AnyType x){
addBefore(getNode(idx),x);
}
//查找
public AnyType get(int idx){
return getNode(idx).data;
}
//更新
public AnyType set(int idx,AnyType newVal){
AnyType old = getNode(idx).data;
getNode(idx).data = newVal;
return old;
}
//删除
public AnyType remove(int idx){
return remove(getNode(idx));
}
private void addBefore(Node<AnyType> p,AnyType x){
if(p.prev==null){
throw new IndexOutOfBoundsException();
}
Node<AnyType> q = new Node<AnyType>(x,p.prev,p);
//p.prev.next = q;
q.prev.next = q;
p.prev = q;
theSize++;
modCount++;//添加操作,更改值
}
private AnyType remove(Node<AnyType> p){
p.next.prev = p.prev;
p.prev.next = p.next;
theSize--;
modCount++;//删除操作,更改值
return p.data;
}
private Node<AnyType> getNode(int idx){
Node<AnyType> p;
if(idx<0||idx>theSize){ //not (theSize-1).
throw new IndexOutOfBoundsException();
}
if(idx<size()/2){ //由前向后遍历
p = beginMarker.next;
for(int i=0;i<idx;i++){
p = p.next;
}
}
else{ //由后向前遍历
p = endMarker;
for(int i=theSize;i>idx;i--){
p = p.prev;
}
}
return p;
}
//迭代器(non-Javadoc)
public java.util.Iterator<AnyType> iterator(){
return new LinkedListIterator();
}
private class LinkedListIterator implements java.util.Iterator<AnyType>{
private Node<AnyType> current = beginMarker.next;
private int expectedModCount = modCount;
private boolean okToRemove = false;
public boolean hasNext(){
return current != endMarker;
}
public AnyType next(){
if(expectedModCount != modCount){
throw new java.util.ConcurrentModificationException();
}
if(!hasNext()){
throw new java.util.NoSuchElementException();
}
AnyType d = current.data;
current = current.next;
okToRemove = true;
return d;
}
public void remove(){
if(expectedModCount != modCount){
throw new java.util.ConcurrentModificationException();
}
if(!okToRemove){
throw new IllegalStateException();
}
MyLinkedList.this.remove(current.prev);
okToRemove = false;
expectedModCount++;
}
}
}
二、栈
栈的插入和删除只在一个位置操作;
栈是后进先出表;
1.栈的数组实现
public class MyArrayStack<Type> {
private static final int DEFAULT_LENGTH = 10;
private int topOfStack;//栈顶
private int theSize;
private Type[] items;
public MyArrayStack(){
clear();
}
//初始化
public void clear(){
theSize = 0;
topOfStack = -1;
//items = new Type[DEFAULT_LENGTH]; //error!!
//items = (Type[]) new Object[DEFAULT_LENGTH];
ensureArray(DEFAULT_LENGTH);
}
//入栈
public void push(Type t){
if(theSize>=DEFAULT_LENGTH){
ensureArray(2*size()-1);
}
items[theSize++] = t;
topOfStack++;
}
//出栈
public Type pop(){
if(topOfStack<0){
throw new ArrayIndexOutOfBoundsException();
}
theSize--;
return items[topOfStack--];
}
public void ensureArray(int newLength){
if(newLength<size()){
return;
}
/*Type[] old = (Type[]) new Object[newLength];
for(int i=0;i<theSize;i++){
old[i] = items[i];
}
items = old;*/
Type[] old = items;
items = (Type[]) new Object[newLength];
for(int i=0;i<theSize;i++){
items[i] = old[i];
}
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return theSize==0;
}
}
//下面是两个应用:进制转换和符号匹配检测
/**
* 进制转换
* num:十进制数 ;n:进制数
* @param args
*/
public String conver(int num,int n){
MyArrayStack<Integer> stack = new MyArrayStack<Integer>();
while(num!=0){
stack.push(num%n);
num = num/n;
}
StringBuilder sb = new StringBuilder();
while(stack.size()>0){
sb.append(stack.pop());
}
return sb.toString();
}
/**
* 检测 符号 是否匹配:([])
* @param args
*/
public boolean isMatch(String str){
MyArrayStack<Character> test = new MyArrayStack<Character>();
char[] chs = str.toCharArray();
for(char ch:chs){
if(test.size()==0 && (ch=='('||ch=='[')){
test.push(ch);
}
else if(test.size()==0){
return false;
}
else{
char temp = test.pop();
if(temp=='(' && ch==')'){
}
else if(temp=='[' && ch==']'){
}
else{
test.push(temp);
test.push(ch);
}
}
}
return test.isEmpty();
}
2.栈的链表实现(单链表)
public class MyLinkedStack<Type> {
//私有内部类
private class Node<Type>{
public Type data;
public Node<Type> next;
public Node(Type data,Node<Type> next){
this.data = data;
this.next = next;
}
public Node(){
data = null;
next = null;
}
}
//数据域
private int theSize;
private Node<Type> begin;
public MyLinkedStack(){
theSize = 0;
begin = new Node<Type>(null,null);
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return theSize==0;
}
public void push(Type x){
Node<Type> p = new Node<Type>(x,begin.next);
begin.next = p;
theSize++;
}
public Type pop(){
Type old = begin.next.data;
begin.next = begin.next.next;
theSize--;
return old;
}
}
三、队列
队列是一种先入先出表;
队列在队头删除元素,在队尾添加元素。
像栈一样,对于每种操作,链表实现和数组实现都给出快速的O(1)运行时间。
1.队列的链表实现
public class MyLinkedQueue<T> {
//私有内部类
private class Node{
public T data;
public Node next;
public Node(){
}
public Node(T data,Node next){
this.data = data;
this.next = next;
}
}
private Node front;//队头
private Node rear;//队尾
private int size = 0;
public MyLinkedQueue(){
Node p = new Node(null,null);
front = rear = p;
}
/**
* 队列入队
* @param data 待入队元素
* @author yulong
*/
public void enqueue(T data){
Node p = new Node(data,null);
rear.next = p;
rear = p;
size++;
}
/**
* 队列出队
* @return 出队元素
*/
public T dequeue(){
if(rear==front){
return null;
}
else{
Node p = front.next;
T x = p.data;
front.next = p.next;
if(p.next==null)
rear = front;
p = null;
size--;
return x;
}
}
public int size(){
return size;
}
public boolean isEmpty(){
return size==0;
}
}
2.队列的循环数组实现
public class MyArrayQueue<Type> {
private final static int FULL = 10;
private int rear;
private int front;
private int size;
private Type[] theItems;
public MyArrayQueue(){
rear = -1;
front = -1;
size = 0;
theItems = (Type[]) new Object[FULL];
}
public int size(){
return size;
}
public boolean isEmpty(){
return size==0;
}
public void enqueue(Type x){
rear++ ;
theItems[rear%FULL] = x;
if(size<10){
size++;
}else{
front++;//覆盖
}
}
public Type dequeue(){
if(rear==front){
return null;
}
else{
front++;
front = front%FULL;
size--;
return theItems[front];
}
}
}