线性表是一种抽象数据类型(Abstract Data Type),它提供了一种有用的方式来组织我们的日常生活。每一个线性表都有一个首元素、一个尾元素,通常还有中间元素。线性表中,除第一个元素外,每一个元素均有唯一的前继;除最后一个元素外,每一个元素均有唯一的后继。日常使用的线性表,例如待办事务线性表、礼品线性表、杂货物线性表等,对这些线性表进行的常用操作就是插入(add)、删除(remove)、替换(replace)、包含(contain)、显示(display)等。
线性表的具体实现有数组方式和链表方式。他们各有自己的优缺点,数组方式的线性表(ArrayList)允许直接访问任何元素,只要知道元素的索引即可。因此线性表的获取操作getEntry很容易编写,执行也很迅速;另一方面,使用定长数组会限制线性表的长度,而使用动态扩展数组可以增加数组的长度,但需要复制数据(可用System.arraycopy)。最后,不管数组的长度是固定的还是动态的,在其他元素之间插入或删除元素都需要在数组中移动元素,这种数据移动降低了这些操作的时间效率。链表方式的线性表(LinkedList),它的最大的优点就是,链表乃至线性表可以根据需要来增长,只要内存足够,就可以再链表中随心所欲地插入结点。此外,链表还使得在插入与删除结点时不需要移动线性表中的任何一个元素。但从链表中检索一个已有的元素,需要类似的遍历以查找想得到的元素,而且链表比数组需要更多的内存。虽然这两种数据结构包含的都是对数据对象的引用,但链表中的每个节点还包含了对另一个节点的引用。
下面是我自己根据线性表的特点实现的自己的线性表(myList)并与Java实现的线性表进行比较:
import java.util.ArrayList;
public class MyArrayList<T> {
public T[] entry;
private int length;
private static final int MAX_SIZE=50;
/**
* 默认构造函数
*/
public MyArrayList()
{
this(MAX_SIZE);
}// end default constructor
/**
* 带参数的构造函数
* @param maxSize 要初始化的线性表的大小
*/
public MyArrayList(int maxSize)
{
length=0;
entry=(T[])new Object[maxSize];
}//end constructor
/**
* 默认在线性表的表尾新增一个元素
* @param newEntry 新增元素的值
* @return
*/
public boolean add(T newEntry)
{
boolean isSuccessful=true;
if(!isFull())
entry[length++]=newEntry;
else
isSuccessful=false;
return isSuccessful;
}//end add
/**
* 在线性表中的某位置,新增元素
* @param newPosition 新增元素将在线性表中的位置
* @param newEntry 新元素的值
* @return
*/
public boolean add(int newPosition,T newEntry)
{
boolean isSuccessful=true;
if(!isFull()&&newPosition>0&&newPosition<=(length+1))
{
makeRoom(newPosition);
entry[newPosition-1]=newEntry;
length++;
}else
isSuccessful=false;
return isSuccessful;
}//end add
/**
* 为新增元素在某位置腾出空间
* @param newPosition 新增元素在线性表中的位置
*/
public void makeRoom(int newPosition)
{
for(int i=length;i>=newPosition;i--)
entry[i]=entry[i-1];
}// end makeRoom
/**
* 删除线性表中某个位置的元素
* @param givePosition 要删除元素在线性表中的位置
* @return
*/
public Object remove(int givePosition)
{
Object givenEntry=null;
if(givePosition>0&&givePosition<=length)
{
assert !isEmpty();
givenEntry=entry[givePosition-1];
removeGap(givePosition);
entry[length-1]=null;
length--;
}
return givenEntry;
}//end remove
/**
* 删除线性表中某个元素后,将该元素的空间补齐
* @param givePosition 要删除元素在线性表中的位置
*/
public void removeGap(int givePosition)
{
for(int i=givePosition-1;i<length-1;i++)
entry[i]=entry[i+1];
}
/**
* 将线性表进行清空
*/
public void clear()
{
length=0;
for(int i=0;i<entry.length;i++)
entry[i]=null;
}//end clear
/**
* 判定线性表是否包含某元素
* @param anEntry 判定线性表中是否要包含的元素
* @return
*/
public boolean contains(T anEntry)
{
boolean found=false;
for(int index=0;!found&&index<entry.length;index++)
{
if(anEntry.equals(entry[index]))
found=true;
}
return found;
}
/**
* 对线性表中的某位置的元素进行替换
* @param givenPosition 替换元素在线性表的位置
* @param newEntry 新的元素
* @return
*/
public boolean replace(int givenPosition,T newEntry)
{
boolean isSuccessful=true;
if(!isEmpty()&&givenPosition>0&&givenPosition<=length)
entry[givenPosition-1]=newEntry;
else
isSuccessful=false;
return isSuccessful;
}
/**
* 获取某个索引的元素的值
* @param index 线性表中的索引
* @return
*/
public T get(int index)
{
if(index>=0&&index<length)
return entry[index];
else
return null;
}
/**
* 判断该线性表是否已达到最大长度
* @return
*/
public boolean isFull()
{
return length==entry.length;//entry.length在构造函数的时候就确定了,不能使用length==MAX_SIZE
}
/**
* 判断该线性表是否为空
* @return
*/
public boolean isEmpty()
{
return length==0;
}
/**
*
* @return 返回线性表的长度,即线性表中元素的个数
*/
public int length()
{
return length;
}
public static void main(String args[])
{
MyArrayList<Integer> myArrayList=new MyArrayList<Integer>();
ArrayList<Integer> arrayList=new ArrayList<Integer>();
myArrayList.add(5);
arrayList.add(5);
myArrayList.add(6);
arrayList.add(6);
myArrayList.remove(2);//我这边是位置从1开始
arrayList.remove(1);//系统是索引
myArrayList.add(1,7);
arrayList.add(0,7);
System.out.print("我的ArrayList的元素:");
for(int i=0;i<myArrayList.length;i++)
System.out.print(myArrayList.get(i)+" ");
System.out.print("java中的ArrayList的元素:");
for(int i=0;i<arrayList.size();i++)
System.out.print(arrayList.get(i)+" ");
}
}
链表实现LinkedList主要里面,加了一个内部类Node,由于采用的是头插法,所以只有一个firstNode表示头结点,如果是尾插法的话,就要再加一个尾结点lastNode。
其实现如以下代码所示:
public class MyLinkedList<T> {
MyLinkedList()
{
clear();
}
public boolean Add(T newEntry)
{
Node newNode=new Node(newEntry);
if(isEmpty())
{
firstNode=newNode;
}else{
Node lastNode=getNodeAt(length);
lastNode.next=newNode;
}
length++;
return true;
}//end add
public boolean Add(int position,T newEntry)
{
boolean isSuccessful=true;
if(position>0&&position<=(length+1))
{
Node currentNode=new Node(newEntry);
if(isEmpty()||position==1)
{
currentNode.next=firstNode;
firstNode=currentNode;
}
else{
Node nodeBefore=getNodeAt(position-1);
Node nodeAfter=nodeBefore.next;
nodeBefore.next=currentNode;
currentNode.next=nodeAfter;
}
}else
isSuccessful=false;
length++;
return isSuccessful;
}//end add
public Object remove(int position)
{
Object result=null;
if(!isEmpty()&&position>0&&position<=length)
{
if(position==1)
{
result=firstNode.data;
firstNode=firstNode.next;
}
else{
Node currentNode=getNodeAt(position-1);
result=currentNode.next.data;
currentNode.next=currentNode.next.next;
}
}
length--;
return result;
}//end remove
public boolean replace(int position,T newEntry)
{
boolean isSuccessful=true;
if(!isEmpty()&&position>0&&position<=length)
{
Node currentNode=getNodeAt(position);
currentNode.data=newEntry;
}else
isSuccessful=false;
return isSuccessful;
}//end replace
public T getEntry(int givenPosition)
{
if(!isEmpty()&&givenPosition>0&&givenPosition<=length)
{
Node currentNode=getNodeAt(givenPosition);
return currentNode.data;
}
return null;
}//getEntry
public boolean contains(T newEntry)
{
boolean found=false;
Node currentNode=firstNode;
while(!found&¤tNode!=null)
{
if(newEntry.equals(currentNode.data))
found=true;
else
currentNode=currentNode.next;
}//end while
return found;
}
public void display()
{
Node currentNode=firstNode;
for(int i=0;i<length;i++)
{
System.out.println("第"+(i+1)+"个结点是"+currentNode.data);
currentNode=currentNode.next;
}
}
public void clear()
{
length=0;
firstNode=null;
}
public boolean isEmpty()
{
return length==0;
}
private Node getNodeAt(int givenPosition)
{
Node result=null;
if(!isEmpty()&&givenPosition>0&&givenPosition<=length)
{
Node currentNode=firstNode;
for(int i=1;i<givenPosition;i++)
currentNode=currentNode.next;
result=currentNode;
}
return result;
}//getNodeAt
private class Node
{
private T data;
private Node next;
private Node(T dataPortion)
{
this.data=dataPortion;
next=null;
}
private Node(T dataPortion,Node nextNode)
{
this.data=dataPortion;
next=nextNode;
}
}//end Node
private Node firstNode; //指向第一个结点的引用
private int length; //链表的长度
}