暑假打算学一下数据结构,顺序表这个东西看着思路这么简单,没想到实现起来却有这么多细节。
首先声明一个接口,包括线性表所有需要的方法。这是线性表的基本部分。
public interface List<T> {
boolean isEmpty(); //判断是否为空
int size(); //线性表元素个数(长度)
T get(int i); //返回第i个元素
void set(int i,T x); //设置第i个元素为x
String toString(); //返回线性表所有元素为字符串
int insert(int i,T x); //插入x作为第i和元素,x!=null返回值为x的序号
int insert(T x); //在表的最后插入x,返回值为x的序号
T remove(int i); //删除第i个元素,返回值为删除的元素
void clear(); //清除这个表
int search(T key); //查找首次和key相等的元素,返回值为其下标
boolean contains(T key); //查询是否包含key
int insertDifferent(T x); //插入不重复元素
int remove(T key); //删除首次出现和key相等的元素,返回其下标
boolean equals(Object obj); //判断两个线性表是否相等
void addAll(List<T> list); //在这个单链表中添加list所有元素,集合并运算
}
然后线性表内容继承前面的接口,实现里面的基本功能。
public class SeqList <T> implements List<T>{
protected Object[] element; //存储元素
protected int n; //存储现在元素的个数
public SeqList(){
this(64);
}
public SeqList(T[] values){
this(values.length);
for(int i=0;i<values.length;i++){
element[i]=values[i];
n=element.length;
}
}
public SeqList(int length){
element=new Object[length];
}
public boolean isEmpty() { //判断是否为空
return n==0; //如果是0返回true
}
public int size() { //线性表元素个数(长度)
return n; //返回n的值
}
public T get(int i) { //返回第i个元素
if(i>=0&&i<n)return (T) element[i];
return null; //如果在0-n范围内,返回这个元素,否则返回null
}
//设置第i个元素为x,如果x是null或者i不在范围内都抛出异常
public void set(int i, T x) {
if(x==null)throw new NullPointerException("x==null");
else if(i>=0&&i<n)element[i]=x;
else throw new java.lang.IndexOutOfBoundsException(i+"");
}
public String toString(){ //返回这个链表的所有元素
String str=this.getClass().getName()+"(";
if(this.n>0)str+=element[0].toString();
for(int i=1;i<n;i++){
str+=","+element[i].toString();
}
str+=")";
return str;
}
public int insert(int i, T x) { //设置第i个元素为x
if(x==null)throw new NullPointerException("x==null"); //如果x为空直接抛出异常
i=i<0?0:i>n?n:i; //如果x超出边界值,x取边界值
Object[] source=element; //把这个数组拷贝给另一个数组
if(n==element.length){ //如果数据数量到了数组的范围,那数组长度扩大二倍,然后把刚才拷贝的数组第i位以前的赋值过去。
element=new Object[source.length*2];
for(int j=0;j<i;j++)element[j]=source[j];
}
for(int j=n-1;j>=i;j--)
element[j+1]=source[j]; //后面的数据需要移项
n++; //既然是插入元素,那元素个数是一定要增加的
element[i]=x; //然后把第i个设置为x
return i;
}
public int insert(T x) { //在顺序表的最后插入一个元素,调用上一个函数
int n=this.n;
insert(n,x);
return n;
}
public T remove(int i) { //删除第i个元素
if(n>=0&&i>=0&&i<n){ //如果i在范围之内执行这个操作
T old=(T)element[i]; //先把第i个元素储存起来
for(int j=i;j<n;j++)
element[j]=element[j+1]; //把第i个元素后面的都往前移动一格
element[n-1]=null; //把初始的最后一个元素清空
n--; //因为是删除操作,自然要把长度减1啦
return old; //把刚才储存起来的元素返回过去
}
return null;
}
public void clear() {
for(int i=0;i<n;i++)element[i]=null;
n=0;
}
public int search(T key) { //查找首个和key相等的元素,返回下标,如果没有返回-1
for(int i=0;i<n;i++){
if(key.equals(element[i]))return i;
}
return -1;
}
public boolean contains(T key) { //查询顺序表是否包含key,调用search函数,看其是否为-1
return search(key)!=-1;
}
public int insertDifferent(T x) { //插入不重复元素,查找不成功时候,尾插入
int i=search(x);
if(i==-1){
i=n;
insert(x);
}
return i;
}
public int remove(T key) { //删除首次出现和key相等的元素,返回其下标
int i=search(key); //先查找其下标
if(i!=-1)remove(i); //如果存在就删除
return i;
}
public void addAll(List<T> list) {
if(list==null)throw new NullPointerException("x==null"); //如果list为空抛出异常
int length=list.size();
Object[] source=element;
if(element.length<n+length){ //如果添加后超过范围,那element范围扩大
element=new Object[n+length];
for(int i=0;i<n;i++)
element[i]=source[i];
}
for(int i=0;i<length;i++){
element[i+n]=list.get(i);
}
n+=length;
}
}
最后是测试类,测试里面一些函数是否完善。
public class SeqListTest {
public static void main(String[] args) {
List l=new SeqList<Integer>();
for(int i=0;i<10;i++)l.insert(i);
System.out.println(l.toString());
l.remove(5);
l.remove(6);
System.out.println(l.toString());
l.set(1, 2);
l.set(2, 1);
System.out.println(l.toString());
List l2=new SeqList<Integer>();
l2.addAll(l);
l.clear();
System.out.println(l.toString());
System.out.println(l2.toString());
}
}
发现写的还行O(∩_∩)O
参考书籍《数据结构JAVA版》第四版。