数据结构-线性表(1)

线性表

线性表的定义

  • 线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列.

  • 线性表是一种抽象数据 类型;数组是一种具体的数据结构。线性表与数组的逻辑结构是不一样的,线性表是元素之 间具有1对1的线性关系的数据元素的集合,而数组是一组数据元素到数组下标的一一映射。 并且从物理性质来看,数组中相邻的元素是连续地存储在内存中的;线性表只是一个抽象的 数学结构,并不具有具体的物理形式,线性表需要通过其它有具体物理形式的数据结构来实 现。在线性表的具体实现中,表中相邻的元素不一定存储在连续的内存空间中,除非表是用 数组来实现的。对于数组,可以利用其下标在一个操作内随机存取任意位置上的元素;对于 线性表,只能根据当前元素找到其前驱或后继,因此要存取序号为i的元素,一般不能在一 个操作内实现,除非表是用数组实现的。

线性表的顺序存储与实现

1.1List接口

package cn.wjy.list;

public interface List {

	/**
	 * 返回线性表的大小,及数据元素的个数
	 *
	 * @return
	 */
	public int getSize();

	/**
	 * 判断线性表是否为空
	 *
	 * @return
	 */
	public boolean isEmpty();

	/**
	 * 判断线性表是否包含数据元素e
	 *
	 * @param e
	 * @return
	 */
	public boolean contains(Object e);

	/**
	 * 返回数据元素e在线性表中的序号
	 *
	 * @param e
	 * @return
	 */
	public int indexOf(Object e);

	/**
	 * 将数据元素e插入到线性表中i号位置
	 *
	 * @param i
	 * @param e
	 * @throws OutOfBoundaryException
	 */
	public void insert(int i, Object e) throws OutOfBoundaryException;

	/**
	 * 将数据元素e插入到元素obj之前
	 *
	 * @param obj
	 * @param e
	 * @return
	 */
	public boolean insertBefore(Object obj, Object e);

	/**
	 * 将数据元素e插入到元素obj之后
	 *
	 * @param obj
	 * @param e
	 * @return
	 */
	public boolean insertAfter(Object obj, Object e);

	/**
	 * 删除线性表中序号为i的元素,并返回之
	 *
	 * @param i
	 * @return
	 * @throws OutOfBoundaryException
	 */
	public Object remove(int i) throws OutOfBoundaryException;

	/**
	 * 删除线性表中第一个与e相同的元素
	 *
	 * @param e
	 * @return
	 */
	public boolean remove(Object e);

	/**
	 * 替换线性表中序号为i的数据元素为e,返回原数据元素
	 *
	 * @param i
	 * @param e
	 * @return
	 * @throws OutOfBoundaryException
	 */
	public Object replace(int i, Object e) throws OutOfBoundaryException;

	/**
	 * 返回线性表中序号为i的数据元素
	 *
	 * @param i
	 * @return
	 * @throws OutOfBoundaryException
	 */
	public Object get(int i) throws OutOfBoundaryException;
}

1.2出现序号越界时抛出异常

public class OutOfBoundaryException extends RuntimeException {

	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	public OutOfBoundaryException(String err) {
		super(err);
	}

}

1.3 Strategy 接口

  • 所有数据元素的类型都使用 Object 来替代,这样做是 为了程序的通用性,即一种抽象数据类型的实现可以用于所有数据元素。但是这样做带来了 另一个需要解决的问题,即完成数据元素之间比较大小或是否相等的问题。在使用 Object 类型的变量指代了所有数据类型之后,那么所有种类的数据元素的比较就都需要使用 Object 类型的变量来完成,但是不同数据元素的比较方法或策略是不一样的。例如字符串的比较是 使用 java.lang.String 类的 compareTo 和 equals 方法;而基本的数值型数据是使用关系运算符 来完成的;其他各种不同的类的比较方法就更加千差万别多种多样了,即使同一个类的比较 方法在不同的情况下也会不同,例如两个学生之间的比较有时可以用学号的字典顺序来进 行,有时可能又需要使用成绩来比较。因此我们无法简单的在两个 Object 类型的变量之间 使用"= ="、"<"等关系运算符来完成各种不同数据元素之间的比较操作,同时 Java 也不提供 运算符的重载.

  • 使用 Strategy 接口可以实现各种不同数据元素相互之间独立的比较策略。在实现各种抽 象数据类型时,例如线性表,可以使用 Strategy 接口变量来完成形式上的比较,然后在创建 每个抽象数据类型的实例时,例如一个具体的用于学生的线性表时,可以引入一个实际实现了 Strategy 接口的策略类对象,例如实现了 Strategy 接口的学生比较策略类对象。使用这一策略的另一优点在于,一旦不想继续使用原先的比较策略对象,随时可以使用另一个比较 策略对象将其替换,而不用修改抽象数据类型的具体实现。

package cn.wjy.list;
public interface Strategy {
	/**
	 * 判断两个数据元素是否相等
	 *
	 * @param obj1
	 * @param obj2
	 * @return
	 */
	public boolean equal(Object obj1, Object obj2);

	/**
	 * 判断两个数据元素的大小 obj1>obj2 return -1; obj1=obj2 return 0; obj1<obj2 reurn 1
	 *
	 * @param obj1
	 * @param obj2
	 * @return
	 */
	public int compare(Object obj1, Object obj2);

}


package cn.wjy.list;

public class DefaultStrategy implements Strategy {

	@Override
	public boolean equal(Object obj1, Object obj2) {
		return obj1.toString().equals(obj2.toString());
	}

	@Override
	public int compare(Object obj1, Object obj2) {
		int temp = obj1.toString().compareTo(obj2.toString());
		if (temp == 0) {
			return 0;
		} else if (temp > 0) {
			return 1;
		} else {
			return -1;
		}

	}

}


package cn.wjy.list;

public class StudentStrategy implements Strategy {

	@Override
	public boolean equal(Object obj1, Object obj2) {
		if (obj1 instanceof Student && obj2 instanceof Student) {
			Student s1 = (Student) obj1;
			Student s2 = (Student) obj2;
			return s1.getSId().equals(s2.getSId());
		} else {
			return false;
		}
	}

	@Override
	public int compare(Object obj1, Object obj2) {
		if (obj1 instanceof Student && obj2 instanceof Student) {
			Student s1 = (Student) obj1;
			Student s2 = (Student) obj2;
			return s1.getSId().compareTo(s2.getSId());
		} else {
			return obj1.toString().compareTo(obj2.toString());
		}
	}

}

2.线性表的数组实现

public class ListArray implements List {

	private final int LEN = 9;// 数组的默认大小
	private Strategy strategy; // 数据元素比较策略
	private int size;// 线性表中数据元素的个数
	private Object[] elements; // 数据元素数组

	public ListArray() {
		this(new DefaultStrategy());
	}

	public ListArray(Strategy strategy) {
		this.strategy = strategy;
		size = 0;
		elements = new Object[LEN];
	}

	@Override
	public int getSize() {
		return size;
	}

	@Override
	public boolean isEmpty() {
		return size == 0;
	}

	@Override
	public boolean contains(Object e) {
			return indexOf(e) != -1;
	}

	@Override
	public int indexOf(Object e) {
		for (int i = 0; i < size; i++)
			if (strategy.equal(e, elements[i]))
				return i;
		return -1;
	}

	/**
	 * 扩充数组
	 */
	private void expandSpace() {
		Object[] a = new Object[elements.length * 2];
		for (int i = 0; i < elements.length; i++)
			a[i] = elements[i];
		elements = a;
	}

	@Override
	public void insert(int i, Object e) throws OutOfBoundaryException {
		if (i < 0 || i > size)
			throw new OutOfBoundaryException("错误,指定的插入序号越界");
		if (size >= elements.length)
			expandSpace();
		for (int j = size; j > i; j--)
			elements[j] = elements[j - 1];
		elements[i] = e;
		size++;
		return;
	}

	@Override
	public boolean insertBefore(Object obj, Object e) {
		int i = indexOf(obj);
		if (i < 0)
			return false;
		insert(i, e);
		return true;
	}

	@Override
	public boolean insertAfter(Object obj, Object e) {
		int i = indexOf(obj);
		if (i < 0)
			return false;
		insert(i + 1, e);
		return true;
	}

	@Override
	public Object remove(int i) throws OutOfBoundaryException {
		if (i < 0 || i >= size)
			throw new OutOfBoundaryException("错误,指定的插入序号越界");
		Object obj = elements[i];
		for (int j = i; j < size - 1; j++)
			elements[j] = elements[j + 1];
		elements[--size] = null;
		return obj;
	}

	@Override
	public boolean remove(Object e) throws OutOfBoundaryException {
		int i = indexOf(e);
		if (i < 0)
			return false;
		remove(i);
		return true;
	}

	@Override
	public Object replace(int i, Object e) throws OutOfBoundaryException {
		if (i < 0 || i >= size)
			throw new OutOfBoundaryException("错误,指定的序号越界");
		Object obj = elements[i];
		elements[i] = e;
		return obj;
	}

	@Override
	public Object get(int i) throws OutOfBoundaryException {
		if (i < 0 || i >= size)
			throw new OutOfBoundaryException("错误,指定的序号越界");
		return elements[i];
	}

}
posted @ 2017-01-07 20:36  %hahahaha%  阅读(294)  评论(0编辑  收藏  举报