线性表是存储顺序牌类的数据时最常用的数据结构

实现线性表有两种方式。第一种是使用数组存储线性表的元素。数组是动态创建的。超过数组的容量时,创建一个

新的更大的数组,并且将当前数组中的元素复制到新建的数组中。另一种方法是用链表结构实现。链表由节点组成,每

个结点都是动态生成的,用来存储一个元素。所有的结点连接成一个线性表。

对于线性表的主要操作有:

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()方法是将队列头的元素删除。