线性表之顺序表

1.顺序存储结构

    用一组连续的内存单元依次存放线性表的数据元素,元素在内存的物理存储次序与他们在线性表中的逻辑次序相同。

    线性表的数据元素属于同一数据类型,设每个元素占用c字节,a(0)的存储地址为Loc(a(0)),则a(i)的存储地址Loc(a(i))为

                                             Loc(a(i)) = Loc(a(0)) + i * c

   可见,顺序表元素a(0)的存储地址是它在线性表中位置i的线性函数,与线性表的长度n没有关系;而计算一个元素地址所需的时间是一个常量,与元素位置i无关。因此,存取任何一个元素的时间复杂度都是O(1)。即,顺序表是一种随机存储结构。

    顺序表通常采用数组来存储数据元素,数组一旦占用一片存储空间,地址和长度就是确定的,不能更改,因此,数组只能进行赋值和取值两种操作,不能进行插入和删除,这也就决定了顺序表的插入和删除只能间接进行,即移动数据元素。


2.顺序表类的java实现

package linearList;

public class SeqList<E> implements LList<E>{
	private Object[] table;//对象数组
	private int n;//顺序表长度
	
	/*
	 * 构造方法,创建指定容量的空表
	 */
	public SeqList(int capacity){
		this.table = new Object[Math.abs(capacity)];//Math.abs(i)返回i的绝对值
		this.n = 0;
	}
	
	/*
	 * 构造方法,指定空表的默认容量
	 */
	public SeqList(){
		this(16);
	}
	
	/*
	 * 判断是否为空,若为空,返回true
	 */
	public boolean isEmpty(){
		return this.n == 0;
	}
	
	/*
	 * 返回线性表长度
	 */
	public int length(){
		return this.n;
	}
	
	/*
	 * 返回序号为index的对象
	 */
	public E get(int index){
		if(index>=0&&index<this.n){
			return (E)this.table[index];
		}else{
			return null;
		}
	}
	
	/*
	 * 设置序号为index的对象的值为element,返回原对象
	 */
	public E set(int index,E element){
		if(index>=0&&index<this.n&&element!=null){
			E old = (E)this.table[index];
			this.table[index] = element;
			return old;
		}else{
			return null;
		}
	}
	
	/*
	 * 插入element对象,插入位置序号为index
	 */
	public boolean add(int index,E element){
		//不能插入null
		if(element==null){
			return false;
		}
		
		//数组扩容
		if(this.n==table.length){
			Object[] temp = this.table;
			this.table = new Object[temp.length*2];
			for(int i=0;i<temp.length;i++){
				this.table[i] = temp[i];
			}
		}
		
		//下标容错,增强程序的健壮性
		if(index<0){
			index = 0;
		}
		if(index>this.n){
			index = this.n;
		}
		
		//插入元素,元素后移
		for(int i=this.n-1;i>=index;i--){
			table[i+1] = table[i];
		}
		table[index] = element;
		this.n++;
		return true;
	}
	
	/*
	 * 插入element对象,位置没有约定,即在顺序表最后插入
	 */
	public boolean add(E element){
		this.add(this.n, element);
		return true;
	}
	
	/*
	 * 移除序号为index的对象,返回被移除的对象
	 */
	public E remove(int index){
		if(this.n!=0&&index>=0&&index<this.n){
			E old = (E)table[index];
			for(int i=index;i<this.n-1;i++){
				this.table[i] = this.table[i+1];
			}
			this.table[this.n-1] = null;
			this.n--;
			return old;
		}
		return null;
	}
	
	/*
	 * 清空线性表
	 */
	public void clear(){
		if(this.n!=0){
			for(int i=0;i<this.n;i++){
				this.table[i] = null;
			}
			this.n = 0;
		}
	}
	/*
	 * 返回所有元素值
	 */
	public String toString(){
		String str = "(";
		if(this.n!=0){
			for(int i=0;i<this.n-1;i++){
				str += this.table[i].toString()+",";
			}
			str += this.table[this.n-1].toString();
		}
		return str+")";
	}
	
	//方法调用,即操作顺序表(增删改查)
	public static void main(String[] args) {
		
	}

}
3.效率分析

        由于顺序表是一种随即结构,存取任何一个元素的get(),set()方法的时间复杂度都是O(1)

        对顺序表的增加和删除操作时,主要的时间消耗是移动元素时发生的,设表长度为n,在第i个位置插入元素的概率是p(i),则插入一个元素的平均移动次数为

                                                                (n-1)* p(i)的连加和

如果在各个位置插入元素的概率相同,即p(0)=p(1)=.......=p(n)=1/(n+1),则时间复杂度为O(n),删除一个元素也是O(n).

        综上所述,我们发现顺序表有两个特点,第一:元素的物理存储顺序直接反映了元素的逻辑顺序,可以随机存取元素;第二:插入和删除的操作效率很低。因此我们在需要频繁查询的场合适于用顺序存储结构,但是当需要频繁的添加和删除操作时就不能用顺序存储结构了,我们需要另寻他法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值