线性表是存储顺序牌类的数据时最常用的数据结构。
实现线性表有两种方式。第一种是使用数组存储线性表的元素。数组是动态创建的。超过数组的容量时,创建一个
新的更大的数组,并且将当前数组中的元素复制到新建的数组中。另一种方法是用链表结构实现。链表由节点组成,每
个结点都是动态生成的,用来存储一个元素。所有的结点连接成一个线性表。
对于线性表的主要操作有:
1、提取线性表的元素
2、在线性表中插入一个新元素
3、从线性表中删除一个元素
4、获取线性表中元素的个数
5、查找线性表中是否包含某个元素
6、判断线性表是否为空
下面这个接口类定义了常用的操作。
package list_test;
public interface MyList {
public void add(Object o);
public void add(int index, Object o);
public void clear();
public boolean contains(Object o);
public Object get(int index);
public int indexOf(Object o);
public boolean isEmpty();
public int lastIndexOf(Object o);
public boolean remove(Object o);
public Object remove(int index);
public Object set(int index, Object o);
public int size();
}
然后用MyAbstractList实现其中一部分方法:
package list_test;
public abstract class MyAbstractList implements MyList {
protected int size = 0;
protected MyAbstractList() {
}
protected MyAbstractList(Object[] objects) {
for (int i = 0; i < objects.length; i++) {
this.add(objects[i]);
}
}
public void add(Object o) {
add(size, o);
}
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
public boolean remove(Object o) {
if (indexOf(o) >= 0) {
remove(indexOf(o));
return true;
} else {
return false;
}
}
}
接下来用数组实现线性表。数组的类型是Object[]类型,所以,数组中每个元素实际元素存储的是对象的引用。
package list_test;
/**
* @author
*/
public class MyArrayList extends MyAbstractList {
public static final int INITIAL_CAPACITY = 16;
private Object[] data = new Object[INITIAL_CAPACITY];
public MyArrayList() {
}
public MyArrayList(Object[] objects) {
data = objects;
size = objects.length;
}
@Override
public void add(int index, Object o) {
ensureCapacity();
for (int i = size - 1; i >= index; i--) {
data[i + 1] = data[i];
}
data[index] = 0;
size++;
}
private void ensureCapacity() {
if (size >= data.length) {
Object[] newData = new Object[data.length * 2];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
}
@Override
public void clear() {
// TODO Auto-generated method stub
data = new Object[INITIAL_CAPACITY];
}
@Override
public boolean contains(Object o) {
// TODO Auto-generated method stub
for (int i = 0; i < size; i++) {
if (o.equals(data[i])) {
return true;
}
}
return false;
}
@Override
public Object get(int index) {
// TODO Auto-generated method stub
return data[index];
}
@Override
public int indexOf(Object o) {
// TODO Auto-generated method stub
for (int i = 0; i < data.length; i++) {
if (o.equals(data[i])) {
return i;
}
}
return -1;
}
@Override
public int lastIndexOf(Object o) {
// TODO Auto-generated method stub
for (int i = size - 1; i >= 0; i--) {
if (o.equals(data[i])) {
return i;
}
}
return -1;
}
@Override
public Object remove(int index) {
// TODO Auto-generated method stub
Object o = data[index];
for (int i = index; i < size - 1; i++) {
data[i] = data[i + 1];
}
size--;
return o;
}
@Override
public Object set(int index, Object o) {
// TODO Auto-generated method stub
Object oldObject = data[index];
data[index] = o;
return oldObject;
}
public String toString(){
StringBuffer result = new StringBuffer("[");
for (int i = 0; i < size; i++) {
result.append(data[i]);
if (i < size -1) {
result.append(", ");
}
}
return result.toString() + "]";
}
}
栈可以看作是一种特殊的线性表,访问、插入和删除它的元素只能在栈的一端来进行。
队列表示一个排队等待的线性表。它的元素只能从队尾插入,从队首访问和删除。
由于栈只允许在栈顶进行插入和删除操作。所以用数组线性表来实现栈比用链表来实现效率高。由于删除是在线
性表的开头进行,所以,用链表来实现队列比用数组线性表效率高。
下面是用包装方式实现的栈类和队列类。
package queue_and_stack;
import list_test.MyLinkedList;
//栈
public class MyStack {
private MyLinkedList list = new MyLinkedList();
public void push(Object o) {
list.addLast(o);
}
public Object pop() {
return list.removeLast();
}
public int getSize() {
return list.size();
}
public String toString() {
return "Stack: " + list.toString();
}
}
package queue_and_stack;
import list_test.MyLinkedList;
//队列
public class MyQueue {
private MyLinkedList list = new MyLinkedList();
public void enqueue(Object o) {
list.addLast(o);
}
public Object dequeue() {
return list.removeFirst();
}
public int getSize() {
return list.size();
}
public String toString() {
return "Queue: " + list.toString();
}
}
下面是一个测试类。
package queue_and_stack;
public class TestStackQueue {
public static void main(String[] args) {
test stack
MyStack stack = new MyStack();
stack.push("a");
System.out.println("(1)" + stack);
stack.push("b");
System.out.println("(2)" + stack);
stack.push("c");
stack.push("d");
System.out.println("(3)" + stack);
System.out.println("(4)" + stack.pop());
System.out.println("(5)" + stack.pop());
System.out.println("(6)" + stack);
test queue
MyQueue queue = new MyQueue();
queue.enqueue("1");
System.out.println("(1) " + queue);
queue.enqueue("2");
System.out.println("(2) " + queue);
queue.enqueue("3");
queue.enqueue("4");
System.out.println("(3) " + queue);
System.out.println("(4) " + queue.dequeue());
System.out.println("(5) " + queue.dequeue());
System.out.println("(6) " + queue);
}
}
对于一个栈来说,push(o)方法是将一个元素添加到栈顶,pop()方法是将栈顶的元素删除并返回此元素。
对于一个队列来书,enqueue(o)方法是将一个元素添加到队尾,dequeue()方法是将队列头的元素删除。