线性表的数组实现


分别实现3种类型的链表,这一篇用数组来实现线性表---

有序链表:链表元素或节点始终保持有序,链表元素为Comparable对象,主要体现在插入操作要插入在相应的序列位置

无序链表:无序,每次指定插入在哪(表头,尾,or指定元素之后)

索引链表:提供了许多与索引相关的操作

将三种实现的都有的公共操作定义在一个接口ADT中,对应于各自特征所特有的操作扩展在自己的类中,可以看到,其实就是插入操作(add)不同而已。


以上说明具体见下列ADT定义中的注释:

链表ADT:

ContractedBlock.gif ExpandedBlockStart.gif ListADT
 
   
package List;


/* 1,我们将实现3中类型的链表:有序链表的元素是可比较对象,在插入删除时始终维持链表有序;无序链表是无序的,
* 插入时指定插入位置(链表首,尾,或指定元素之后);索引链表可以根据索引来存取元素(例如返回某个元素的索引,
* 返回某个索引上的元素,在某个索引处删除或插入元素等等)。他们的区别就在于插入的操作不一样。
* 2,将有序链表,无序链表,索引链表的公共操作定义为接口,不同的操作在类中扩展
*/


public interface ListADT { // 3种链表的公共操作

public int size();

public boolean isEmpty();

public Object first();

public Object last();

public Object removeFirst();

public Object removeLast();

public Object remove(Object element);

public boolean contains(Object element);

}


1,有序链表的数组实现

成员定义:

 
  
private Object[] contents;
private int rear; // 将链表的一端固定在0,rear表示下一个可用单元的下标(也表示长度)
private static int SIZE = 10 ;


构造方法和数组动态扩展:

 
  
public ArrayOrderedList()
{
contents
= new Object[SIZE];
rear
= 0 ;
}

public void expand()
{
Object[] larger
= new Object[size() * 2 ];
for ( int index = 0 ;index < rear;index ++ )
larger[index]
= contents[index];
contents
= larger;
}


有序链表的实现:

ContractedBlock.gif ExpandedBlockStart.gif ArrayOrderedList
 
   
package List;

public class ArrayOrderedList implements ListADT { // 有序链表

private Object[] contents;
private int rear; // 将链表的一端固定在0,rear表示下一个可用单元的下标(也表示长度)
private static int SIZE = 10 ;


public ArrayOrderedList()
{
contents
= new Object[SIZE];
rear
= 0 ;
}

public void expand()
{
Object[] larger
= new Object[size() * 2 ];
for ( int index = 0 ;index < rear;index ++ )
larger[index]
= contents[index];
contents
= larger;
}




// 三种链表的接口公共操作(实现是一样的)

public int size() {
return rear;
}

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

public boolean contains(Object element) {
for ( int index = 0 ;index < rear;index ++ )
if (element.equals(contents[index]))
return true ;
return false ;
}

public Object first() {
return contents[ 0 ];
}


public Object last() {
return contents[rear - 1 ];
}


public Object removeFirst() {
if (size() == 0 )
{
System.out.println(
" 表现在为空!!!不能删除 " );
return null ;
}
Object result
= contents[ 0 ];
for ( int index = 0 ;index < rear - 1 ;index ++ )
contents[index]
= contents[index + 1 ];
rear
-- ;
return result;
}

public Object removeLast() {
if (size() == 0 )
{
System.out.println(
" 表现在为空!!!不能删除 " );
return null ;
}
Object result
= contents[rear - 1 ];
contents[rear
- 1 ] = null ; // 也可以不置空,下次覆盖
rear -- ;
return result;
}

public Object remove(Object element) {
if (size() == 0 )
{
System.out.println(
" 表现在为空!!!不能删除 " );
return null ;
}

for ( int index = 0 ;index < rear;index ++ )
if (contents[index].equals(element))
{
Object result
= contents[index];
for ( int i = index;i < rear - 1 ;i ++ )
{
contents[i]
= contents[i + 1 ];
// rear--;错误
}
rear
-- ;
return result;
}

return null ;
}



// 有序链表扩展的操作

public void add(Comparable element){
if (rear == contents.length)
expand();
for ( int index = 0 ;index < rear;index ++ )
if (element.compareTo(contents[index]) < 0 ) // 找到插入位置
{
for ( int i = rear;i > index;i -- )
contents[i]
= contents[i - 1 ];
contents[index]
= element;
rear
++ ;
return ;
}
contents[rear]
= element;
rear
++ ;
}

}




2,无序链表的数组实现

就是add操作不一样,其他完全相同,只贴出扩展部分不同的几个操作:

ContractedBlock.gif ExpandedBlockStart.gif ArrayUnorderedList
 
   
// 无序链表扩展的操作

public void addToFront(Object element){
if (rear == contents.length)
expand();
for ( int index = rear;index > 0 ;index -- )
contents[index]
= contents[index - 1 ];
contents[
0 ] = element;
rear
++ ;
}


public void addToRear(Object element){
if (rear == contents.length)
expand();
contents[rear]
= element;
rear
++ ;
}


public void addAfter(Object after,Object element){
if (rear == contents.length)
expand();
for ( int index = 0 ;index < rear;index ++ )
if (contents[index].equals(after))
{
for ( int i = rear;i > index + 1 ;i -- )
contents[i]
= contents[i - 1 ];
contents[index
+ 1 ] = element;
rear
++ ;
return ;
}
}




3,索引链表的数组实现

扩展的不同操作:

ContractedBlock.gif ExpandedBlockStart.gif ArrayIndexedList
 
   
// 索引链表扩展的操作

public void add(Object element){ // 在表尾插入
if (rear == contents.length)
expand();
contents[rear]
= element;
rear
++ ;
}

public void add( int index,Object element){ // 在指定索引上插入,后面的元素要后移
if (rear == contents.length)
expand();
for ( int i = rear;i > index;i -- )
contents[i]
= contents[i - 1 ];
contents[index]
= element;
rear
++ ;
}

public void set( int index,Object element){ // 设置某个索引上的元素(覆盖原来的,不需要移动元素)
if (index >= rear)
{
System.out.println(
" 只能在表的范围内设置 " );
return ;
}
contents[index]
= element;
}

public Object get( int index){ // 返回某个索引上的元素
return contents[index];
}

public int indexOf(Object element){ // 返回某个元素的索引
for ( int i = 0 ;i < rear;i ++ )
if (element.equals(contents[i]))
{
int index = i;
return index;
}
return - 1 ;
}

public Object remove( int index){ // 移除指定索引上的元素
for ( int i = index;i < rear;i ++ )
{
Object result
= contents[index];
contents[index]
= contents[index + 1 ];
rear
-- ;
return result;
}
return null ;
}



 数组实现的很多地方都在移动元素,在插入和删除上没有优势,它的优势在于随机存取。


转载于:https://www.cnblogs.com/jmzz/archive/2011/05/04/2036326.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值