线性表是同一数据类型的一个有限集合,数据之间在逻辑上存在线性关系。线性表中的元素的个数称为线性表的长度。
线性表的抽象数据类型由带结构的数据和操作组成。线性表接口List的定义如下:
<pre name="code" class="java">package list;
/**
* 线性表接口List的定义如下
*
*/
public interface List<E> {
public Object value(int pos);// 返回线性表中地pos个元素的值
boolean add(Object obj, int pos);// 向第pos个元素位置插入一个元素obj
void remove(int pos);// 删除第pos个元素并返回,若不存在返回空
int find(Object obj);// 从表头查找等于obj值的第一个元素,返回序号
boolean modify(Object obj, int pos);// 用obj修改线性表中给定序号pos的元素值
boolean isEmpty();// 判断线性表是否为空
int size();// 返回线性表的长度
String forward();// 正向遍历输出线性表中所有元素
String backward();// 反向遍历输出线性表中所有元素
void clear();// 清除线性表中所有元素
boolean add(Object obj);// 向线性表尾部插入元素
}
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">
</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">线性表运算举例</span>
假定学生类Student的定义如下:
package list;
public class Student implements Comparable<Object> {
private String numb;// 学号
private String name;// 姓名
private int grade;// 成绩
public Student(String numb, String name, int grade) {
this.numb = numb;
this.name = name;
this.grade = grade;
}
@Override
public String toString() {
return this.numb + "-->" + this.name + "-->" + this.grade;
}
public int compareTo(Object o) {
Student s = (Student) o;
return this.grade - s.getGrade();
}
public String getNumb() {
return numb;
}
public void setNumb(String numb) {
this.numb = numb;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + grade;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((numb == null) ? 0 : numb.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (grade != other.grade)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (numb == null) {
if (other.numb != null)
return false;
} else if (!numb.equals(other.numb))
return false;
return true;
}
}
定义一个线性表,并实现其中方法:
package list;
public class SequenceList<E> implements List<E> {
public static final int minSize = 10;// 数组初始长度
private Object[] listArray;// 声明数组,元素类型为Object
private int length;// 线性表的长度
public SequenceList() {// 无参构造
this.length = 0;// 线性表初始长度
listArray = new Object[minSize];// 初始化一个长度为10的空数组
}
public SequenceList(int n) {// 带初始长度的构造器
if (n < minSize)// 条件成立,将n修改为minSize
n = minSize;
this.length = 0;// 线性表初始长度
listArray = new Object[n];// 初始化一个长度为10的空数组
}
public Object value(int index) {// 返回线性表中第index个元素的值,index = 0表示在数组第一个位置放进元素
if (index >= 0 && index <= this.length - 1) {
return this.listArray[index];
}
return null;
}
/**
* 向线性表中指定位置插入一个元素 假定插入到第pos个元素的位置
*
* 1.检查插入位置是否有效
*
* 2.检查线性表的存储空间是否已占满
*
* 3.空出下标为pos的位置
*
* 4.把obj放到pos的位置
*
* 5.返回真,插入成功
*
* 平均时间复杂度为O(n)
*
* @param obj
* @param pos
* @return2
*/
public boolean add(Object obj, int pos) {
if (pos < 0 || pos > this.length) {// 检查插入的位置是否合法
return false;
}
if (this.length == listArray.length) {// 数组空间用完的情况下,进行再分配
Object[] p = new Object[this.length * 2];// 新数组的空间为原数组的2倍
for (int i = 0; i < this.length; i++) {
p[i] = listArray[i];// 复制原线性表
listArray = p;
}
}
for (int i = this.length - 1; i >= pos; i--) {// 为待插入元素空出位置,从第pos开始向后移动
listArray[i + 1] = listArray[i];
}
listArray[pos] = obj;
this.length++;
return true;
}
/**
* 从线性表中删除给定位置的元素
*
* 线性表中元素的位置:[0,length -1]
*
* 平均时间复杂度为O(n)
*/
public void remove(int pos) {
if (pos >= 0 && pos <= this.length - 1) {
int numMoved = this.length - 1 - pos;
if (numMoved > 0) {// 如果删除的位置不是线性表的最后一个元素的位置,需要移动线性表中元素
for (int i = 0; i < this.length; i++) {
listArray[i] = listArray[i + 1];
}
}
listArray[--this.length] = null;// 如果删除的位置是线性表的最后一个元素的位置,释放最后一个位置的
}
}
/**
* 从线性表中按顺序查找值为obj的元素,返回第一个匹配元素的位置
*/
public int find(Object obj) {
for (int i = 0; i < this.length; i++) {
if (listArray[i].equals(obj)) {
return i;
}
}
return -1;
}
/**
* 修改线性表中给定位置的元素值
*/
public boolean modify(Object obj, int pos) {
if (pos < 0 || pos > this.length - 1) {
return false;
}
listArray[pos] = obj;
return true;
}
/**
* 判断线性表是否为空
*/
public boolean isEmpty() {
return this.length == 0;
}
/**
* 求线性表的长度
*/
public int size() {
return this.length;
}
/**
* 正向遍历线性表中所有元素
*
* @return
*/
public String forward() {
String str = "";
for (int i = 0; i < this.length; i++) {
str += listArray[i].toString() + "\t";
}
return str;
}
/**
* 反向遍历线性表
*/
public String backward() {
String str = "";
for (int i = this.length - 1; i >= 0; i--) {
str += listArray[i].toString() + "\t";
}
return str;
}
/**
* 清除线性表中的元素
*/
public void clear() {
listArray = null;
this.length = 0;
}
/**
* 重载方法向线性表尾部插入元素
*
* 1.检查插入位置是否有效
*
* 2.检查线性表的存储空间是否已占满
*
* 3.把obj放到线性表尾部
*
* 4.返回真,插入成功
*
* 平均时间复杂度为O(n)
*
*/
public boolean add(Object obj) {
if (this.length == listArray.length) {// 数组空间用完的情况下,进行再分配
Object[] p = new Object[this.length * 2];// 新数组的空间为原数组的2倍
for (int i = 0; i < this.length; i++) {
p[i] = listArray[i];// 复制原线性表
listArray = p;
}
}
listArray[this.length] = obj;
this.length++;
return true;
}
}
测试所写的线性表:
package list;
public class TestList {
public static void main(String[] args) {
SequenceList<Student> list = new SequenceList<Student>();
Student stu1 = new Student("001", "张三", 80);
Student stu2 = new Student("002", "李四", 90);
Student stu3 = new Student("003", "王五", 100);
System.out.print("向线性表插入元素: ");
list.add(stu1);
list.add(stu2, 1);
list.add(stu3);
System.out.println(list.forward() + "\n" + "---------------------");
System.out.println("从线性表删除的元素: ");
list.remove(2);
System.out.println(list.forward());
System.out.println("从线性表查找指定元素的位置: ");
System.out.println(list.find(stu1) + "\n" + "---------------------");
System.out.println("修改线性表: ");
Student stu4 = new Student("004", "赵六", 60);
list.modify(stu4, 0);
System.out.println(list.forward() + "\n" + "---------------------");
System.out.println("判断线性表是否为空: ");
System.out.println(list.isEmpty() + "\n" + "---------------------");
System.out.println("判断线性表长度: ");
System.out.println(list.size() + "\n" + "---------------------");
System.out.println("反向遍历线性表: ");
System.out.println(list.backward() + "\n" + "---------------------");
System.out.println("清空线性表: ");
list.clear();
System.out.println(list.forward() + "\n" + "---------------------");
}
}