• 数据结构-线性表(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];
    	}
    
    }
    
  • 相关阅读:
    emacs 集成astyle
    git reflog
    rpm 打包的时候 不进行strip
    gmock
    如何对正在运行的进程,进行heap profile
    linux性能压测工具
    默认宏定义
    gdb fabs错误输出
    基于Clang的缓存型C++编译器Zapcc
    grep 多行 正则匹配
  • 原文地址:https://www.cnblogs.com/Onlywjy/p/6260304.html
Copyright © 2020-2023  润新知