数据结构 第3章 笔记与总结
3.1 抽象数据类型 abstract data type
ADT = 数据结构 + 操作
3.2 表ADT
3.2.1 表的简单数组实现
数组 arr 在必要时候被扩展
1 int[] arr = new int[10]; 2 ... 3 // 扩大arr 4 int[] newArr = new int[arr.length * 2]; 5 for(int i = 0; i < arr.length; i++) 6 newArr[i] = arr[i]; 7 arr = newArr;
3.2.2 简单链表
3.3 Java Collections API 中的表
3.3.1 Collections 接口
Collections API位于java.util包中。集合的概念在Collections接口中得到抽象,它存储一组类型相同的对象。下面显示该接口一些最重要的部分(一些方法未被显示)
1 public interface Collections<AnyType> extends Iterable<AnyType> 2 { 3 int size(); 4 boolean isEmpty(); 5 void clear(); 6 boolean contains(AnyType x); 7 boolean add(AnyType x); 8 boolean remove(AnyType x); 9 java.util.Iterator<AnyType> iterator(); 10 }
Collection接口继承了Iterable接口。实现了Iterable接口的类可以拥有增强的for循环。如下:
1 public static<AnyType> void print(Collection<AnyType> coll){ 2 for(AnyType item : coll) 3 System.out.println(item); 4 }
3.3.2 Iterator接口
实现Iterable接口的集合必须提供一个iterator方法,该方法返回一个实现了Iterator接口的对象。该Iterator是在java.util包中定义的接口。
1 public interface Iterator<AnyType> 2 { 3 boolean hasNext( ); 4 AnyType next( ); 5 void remove( ); 6 }
【xyl整理思路】
Collection接口扩展了Iterable接口,实现了Iterable接口的集合必须要提供一个iterator方法,这个方法返回一个实现了Iterator接口的对象。【从下面代码的角度更好理解这段话】
1 public static <AnyType> void print( Collection<AnyType> coll ) 2 { 3 Iterator<AnyType> itr = coll.iterator( ); 4 while( itr.hasNext( ) ) { 5 AnyType item = itr.next( ); 6 System.out.println( item ); 7 } 8 }
Iterator接口的remove方法:
可以删除由next最近返回的项(删除一次后,我们不能再调用remove,只有再对next调用一次后才可以remove)
Iteraror的remove方法和Collection的remove方法:
Iterator的remove方法的优点:
1、Collection的remove方法必须首先找出要被删除的项。
2、使用Iterator的一个基本法则:如果对正在被迭代的集合进行结构上的改变(即add、remove、clear方法),那么迭代器不再合法。Iterator的remove的方法除外。
3.3.3 List 接口、ArrayList 类和LinkedList 类
List 接口继承了 Collection 接口,它包含Collection接口的所有方法。下面解释了其中一些重要方法:
1 public interface List<AnyType> extends Collection<AnyType> { 2 AnyType get( int idx ); 3 AnyType set( int idx, AnyType newVal ); 4 void add( int idx, AnyType x ); 5 void remove( int idx ); 6 7 ListIterator<AnyType> listIterator( int pos ); 8 }
List 接口指定 listIterator 方法,它将产生比通常更复杂的迭代器,在 3.3.5 补充。
List ADT 有两种常见实现方式:1、ArrayList 类;2、LinkedList 类。
ArrayList 类
提供了 List ADT 的一种可增长数组的实现。
LinkedList 类
提供了 List ADT 的双链表实现。
本小节重点在于两者的区别:
ArrayList 类:查找快,增删慢;
LinkedList 类:增删快,查找慢。
3.3.4 例子:remove 方法对 LinkedList 类的使用
Iterator 接口的remove 方法,只花费线性时间。
public static void removeEvensVer3( List<Integer> lst ) { Iterator<Integer> itr = lst.iterator( ); while( itr.hasNext( ) ) if( itr.next( ) % 2 == 0 ) itr.remove( ); }
3.3.5 关于 ListIterator 接口
下面代码展示了 ListIterator 继承了 List 的 Iterator 的功能。方法 previous 和 hasPrevious 可以实现表从后向前的遍历。add 方法将一个新的项以当前位置放入表中。
public interface ListIterator<AnyType> extends Iterator<AnyType> { boolean hasPrevious( );
AnyType previous( );
void add( AnyType x );
void set( AnyType newVal );
}
3.4 ArrayList 类的实现
3.4.1 基本类
1 public class MyArrayList<AnyType> implements Iterable<AnyType> { 2 private static final int DEFAULT_CAPACITY = 10; 3 private int theSize; 4 private AnyType[] theItems; 5 6 public MyArrayList() { 7 doClear(); 8 } 9 10 public void clear() { 11 doClear(); 12 } 13 14 private void doClear() { 15 theSize = 0; 16 ensureCapacity(DEFAULT_CAPACITY); 17 } 18 19 public int size() { 20 return theSize; 21 } 22 23 public boolean isEmpty() { 24 return size() == 0; 25 } 26 27 public void trimToSize() { 28 ensureCapacity(size()); 29 } 30 31 public AnyType get(int idx) { 32 if (idx < 0 || idx >= size()) throw new ArrayIndexOutOfBoundsException(); 33 return theItems[idx]; 34 } 35 36 public AnyType set(int idx, AnyType newVal) { 37 if (idx < 0 || idx >= size()) 38 throw new ArrayIndexOutOfBoundsException(); 39 AnyType old = theItems[idx]; 40 theItems[idx] = newVal; 41 return old; 42 } 43 44 public void ensureCapacity(int newCapacity) { 45 if (newCapacity < theSize) return; 46 AnyType[] old = theItems; 47 theItems = (AnyType[]) new Object[newCapacity]; 48 for (int i = 0; i < size(); i++) theItems[i] = old[i]; 49 } 50 51 public boolean add(AnyType x) { 52 add(size(), x); 53 return true; 54 } 55 56 public void add(int idx, AnyType x) { 57 if (theItems.length == size()) 58 ensureCapacity(size() * 2 + 1); 59 for (int i = theSize; i > idx; i--) theItems[i] = theItems[i - 1]; 60 theItems[idx] = x; 61 theSize++; 62 } 63 64 public AnyType remove(int idx) { 65 AnyType removedItem = theItems[idx]; 66 for (int i = idx; i < size() - 1; i++) theItems[i] = theItems[i + 1]; 67 theSize--; 68 return removedItem; 69 } 70 71 public java.util.Iterator<AnyType> iterator() { 72 return new ArrayListIterator(); 73 } 74 75 private class ArrayListIterator implements java.util.Iterator<AnyType> { 76 private int current = 0; 77 78 public boolean hasNext() { 79 return current < size(); 80 } 81 82 public AnyType next() { 83 if (!hasNext()) 84 throw new java.util.NoSuchElementException(); 85 return theItems[current++]; 86 } 87 88 public void remove() { 89 MyArrayList.this.remove(--current); 90 } 91 } 92 }
ArrayListIterator 这里有一个 Java 结构,它是 MyArrayList 的内部类。
下面则是 嵌套类
1 public class MyArrayList<AnyType> implements Iterable<AnyType> { 2 private int theSize; 3 private AnyType[] theItems; ... 4 5 public java.util.Iterator<AnyType> iterator() { 6 return new ArrayListIterator<AnyType>(this); 7 } 8 9 private static class ArrayListIterator<AnyType> implements java.util.Iterator<AnyType> { 10 private int current = 0; 11 private MyArrayList<AnyType> theList; ... 12 13 public ArrayListIterator(MyArrayList<AnyType> list) { 14 theList = list; 15 } 16 17 public boolean hasNext() { 18 return current < theList.size(); 19 } 20 21 public AnyType next() { 22 return theList.theItems[current++]; 23 } 24 } 25 }
嵌套类和内部类的区别是,必须使用 static 来表示是嵌套的;没有 static 则是内部类。
嵌套类可以被设计成 private
补充知识:内部类、外部类
内部类:类的第五个成员
1.定义:Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类.
2.内部类的分类:
成员内部类(静态、非静态 ) vs 局部内部类(方法内、代码块内、构造器内)
3.成员内部类的理解:
一方面,作为外部类的成员:
调用外部类的结构
可以被static修饰(嵌套类)
可以被4种不同的权限修饰
另一方面,作为一个类:
类内可以定义属性、方法、构造器等
可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
可以被abstract修饰
4.成员内部类:
4.1如何创建成员内部类的对象?(静态的,非静态的)
1 //创建静态的Dog内部类的实例(静态的成员内部类): 2 Person.Dog dog = new Person.Dog(); 3 4 //创建非静态的Bird内部类的实例(非静态的成员内部类): 5 //Person.Bird bird = new Person.Bird();//错误的 6 Person p = new Person(); 7 Person.Bird bird = p.new Bird();
4.2如何在成员内部类中调用外部类的结构?⭐
1 public class Person { 2 String name = "小明"; 3 public void eat(){ 4 } 5 //非静态成员内部类 6 class Bird{ 7 String name = "杜鹃"; 8 public void display(String name){ 9 System.out.println(name);//方法的形参 10 System.out.println(this.name);//内部类的属性 11 System.out.println(Person.this.name);//外部类的属性 12 //Person.this.eat(); 13 } 14 } 15 }
5.局部内部类的使用:
//返回一个实现了Comparable接口的类的对象 public Comparable getComparable(){ //创建一个实现了Comparable接口的类:局部内部类 //方式一: // class MyComparable implements Comparable{ // // @Override // public int compareTo(Object o) { // return 0; // } // } // return new MyComparable(); //方式二: return new Comparable(){ @Override public int compareTo(Object o) { return 0; } }; }
注意点:
在局部内部类的方法中(比如:show如果调用局部内部类所声明的方法(比如:method)中的局部变量(比如:num)的话,要求此局部变量声明为final的。
jdk 7及之前版本:要求此局部变量显式的声明为final的
jdk 8及之后的版本:可以省略final的声明
总结:
成员内部类和局部内部类,在编译以后,都会生成字节码文件。
格式:成员内部类:外部类$内部类名.class
局部内部类:外部类$数字 内部类名.class
3.5 LinkedList 类的实现
1 public class MyLinkedList<AnyType> implements Iterable<AnyType> { 2 private static class Node<AnyType> {/* Figure 3.25 */ 3 } 4 5 public MyLinkedList() { 6 doClear(); 7 } 8 9 public void clear() {/* Figure 3.26 */} 10 11 public int size() { 12 return theSize; 13 } 14 15 public boolean isEmpty() { 16 return size() == 0; 17 } 18 19 public boolean add(AnyType x) { 20 add(size(), x); 21 return true; 22 } 23 24 public void add(int idx, AnyType x) { 25 addBefore(getNode(idx, 0, size()), x); 26 } 27 28 public AnyType get(int idx) { 29 return getNode(idx).data; 30 } 31 32 public AnyType set(int idx, AnyType newVal) { 33 Node<AnyType> p = getNode(idx); 34 AnyType oldVal = p.data; 35 p.data = newVal; 36 return oldVal; 37 } 38 39 public AnyType remove(int idx) { 40 return remove(getNode(idx)); 41 } 42 43 private void addBefore(Node<AnyType> p, AnyType x) {/* Figure 3.28 */} 44 45 private AnyType remove(Node<AnyType> p) {/* Figure 3.30 */} 46 47 private Node<AnyType> getNode(int idx) {/* Figure 3.31 */} 48 49 private Node<AnyType> getNode(int idx, int lower, int upper) {/* Figure 3.31 */} 50 51 public java.util.Iterator<AnyType> iterator() { 52 return new LinkedListIterator(); 53 } 54 55 private class LinkedListIterator implements java.util.Iterator<AnyType> {/* Figure 3.32 */ 56 } 57 58 private int theSize; 59 private int modCount = 0; 60 private Node<AnyType> beginMarker; 61 private Node<AnyType> endMarker; 62 }
MyLinkedList 类的嵌套 Node 类
1 private static class Node<AnyType> { 2 public Node(AnyType d, Node<AnyType> p, Node<AnyType> n) { 3 data = d; 4 prev = p; 5 next = n; 6 } 7 8 public AnyType data; 9 public Node<AnyType> prev; 10 public Node<AnyType> next; 11 }
MyLinkedList 类的 clear 例程
1 public void clear(){ 2 doClear(); 3 } 4 private void doClear(){ 5 beginMarker = new Node<AnyType>(null,null,null); 6 endMarker = new Node<AnyType>(null,beginMarker,null); 7 beginMarker.next = endMarker; 8 9 theSize=0; 10 modCount++; 11 }
MyLinkedList 类的 add 例程
1 /** 2 * Adds an item to this collection, at specified position p. 3 * Items at or after that position are slid one position higher. 4 * @param p Node to add before. 5 * @param x any object. 6 * @throws IndexOutOfBoundsException if idx is not between 0 and size(),. 7 */ 8 private void addBefore(Node<AnyType> p, AnyType x) { 9 Node<AnyType> newNode = new Node<>(x, p.prev, p); 10 newNode.prev.next = newNode; 11 p.prev = newNode; 12 theSize++; 13 modCount++; 14 }
MyLinkedList 类的 remove 例程
MyLinkedList 类的 getNode 例程
MyLinkedList 类的的内部 Iterator 类
3.6 栈 ADT

浙公网安备 33010602011771号