线性表的分析及实现

(一)概念

线性表在内存中是一块连续的存储空间。

只要知道第一个元素在内存中的位置,其他元素的位置就不难知道。


访问第N个元素的时间是o(1),但是要在数组中查找指定的数据则时间复杂度为O(N),当向数组中插入或者删除某个数据时的事件复杂度为O(n),因为插入或者删除任意元素后面的元素都要做出相应的移动。、

(二)特性

(1)同一性。保存的是同一类型的元素

(2)序偶性。除了第一个元素,其他元素有且仅有唯一一个直接前驱,除了最后一个元素,其他元素有且仅有唯一一个直接后继;

(3)索引性。元素的下标唯一确定了该元素在表中的位置;

(三)与链表的区别

链表是在非连续的内存空间中保存数据,当查找某个数据的时候,事件复杂度为O(N),因为链表中保存的是数据以及指向下一元素的链接信息。


但是插入和删除操作的事件复杂度是O(1)


因为只要改变相应位置的指针信息,而不用移动位置。

(四)线性表的实现

(1)数组实现线性表

/**
 * 自己用数组实现的线性表
 */
public class ArrayList<E> {
	Object[] data = null;// 用来保存此队列中内容的数组
	int current;// 保存当前为第几个元素的指标
	int capacity;// 表示数组大小的指标
	 
	/**
	 * 如果初始化时,未声明大小,则默认为10
	 */
	public ArrayList() {
		this(10);
	}

	/**
	 * 初始化线性表,并且声明保存内容的数组大小
	 * @param initalSize
	 */
	public ArrayList(int initalSize) {
		if (initalSize < 0) {
			throw new RuntimeException("数组大小错误:" + initalSize);
		} else {
			this.data = new Object[initalSize];
			this.current = 0;
			capacity = initalSize;
		}
	}

	/**
	 * 添加元素的方法 添加前,先确认是否已经满了
	 * @param e
	 * @return
	 */
	public boolean add(E e) {
		ensureCapacity(current);// 确认容量
		this.data[current] = e;
		current++;
		return true;
	}

	/**
	 * 确认系统当前容量是否满足需要,如果满足,则不执行操作 如果不满足,增加容量
	 * @param cur 当前个数
	 */
	private void ensureCapacity(int cur) {
		if (cur == capacity) {
			// 如果达到容量极限,增加10的容量,复制当前数组
			this.capacity = this.capacity + 10;
			Object[] newdata = new Object[capacity];
			for (int i = 0; i < cur; i++) {
				newdata[i] = this.data[i];
			}
			this.data = newdata;
		}
	}

	/**
	 * 得到指定下标的数据
	 * @param index
	 * @return
	 */
	public E get(int index) {
		validateIndex(index);
		return (E) this.data[index];
	}
     
   /**
    * 返回当前队列大小
    * @return
    */
	public int size() {
		return this.current;
	}

	/**
	 * 更改指定下标元素的数据为e
	 * @param index 
	 * @param e
	 * @return
	 */
	public boolean set(int index, E e) {
		validateIndex(index);
		this.data[index] = e;
		return true;
	}
   
	/**
	 *  验证当前下标是否合法,如果不合法,抛出运行时异常
	 * @param index 下标
	 */
	private void validateIndex(int index) {
		if (index < 0 || index > current) {
			throw new RuntimeException("数组index错误:" + index);
		}
	}

	/**
	 * 在指定下标位置处插入数据e
	 * @param index 下标
	 * @param e 需要插入的数据
	 * @return 
	 */
	public boolean insert(int index, E e) {
		validateIndex(index);
		Object[] tem = new Object[capacity];// 用一个临时数组作为备份
		//开始备份数组
		for (int i = 0; i < current; i++) {
			if (i < index) {
				tem[i] = this.data[i];
			}else if(i==index){
				tem[i]=e;
			}else if(i>index){
				tem[i]=this.data[i-1];
			}
		}
		this.data=tem;
		return true;
	}
<br><br>/**<br>	 * 删除指定下标出的数据<br>	 * @param index<br>	 * @return<br>	 */<br>	public boolean delete(int index){<br>		validateIndex(index);<br>		Object[] tem = new Object[capacity];// 用一个临时数组作为备份<br>		//开始备份数组<br>		for (int i = 0; i < current; i++) {<br>			if (i < index) {<br>				tem[i] = this.data[i];<br>			}else if(i==index){<br>				tem[i]=this.data[i+1];<br>			}else if(i>index){<br>				tem[i]=this.data[i+1];<br>			}<br>		}<br>		this.data=tem;<br>		return true;<br>	}<br><br>}
(2)链表的实现

 思路:1.链表采用链式存储结构,在内部只需要将一个一个结点链接起来。(每个结点中有关于此结点下一个结点的引用)

         链表操作优点:1.,因为每个结点记录下个结点的引用,则在进行插入和删除操作时,只需要改变对应下标下结点的引用即可

                     缺点:1.要得到某个下标的数据,不能通过下标直接得到,需要遍历整个链表。

/**
 * 自己用链式存储实现的线性表
 */
public class LinkedList<E> {

	private Node<E> header = null;// 头结点
	int size = 0;// 表示数组大小的指标

	public LinkedList() {
		this.header = new Node<E>();
	}

	public boolean add(E e) {
		if (size == 0) {
			header.e = e;
		} else {
			// 根据需要添加的内容,封装为结点
			Node<E> newNode = new Node<E>(e);
			// 得到当前最后一个结点
			Node<E> last = getNode(size-1);
			// 在最后一个结点后加上新结点
			last.addNext(newNode);
		}
		size++;// 当前大小自增加1
		return true;
	}

	public boolean insert(int index, E e) {
		Node<E> newNode = new Node<E>(e);
		// 得到第N个结点
		Node<E> cNode = getNode(index);
		newNode.next = cNode.next;
		cNode.next = newNode;
		size++;
		return true;

	}

	/**
	 * 遍历当前链表,取得当前索引对应的元素
	 * 
	 * @return
	 */
	private Node<E> getNode(int index) {
		// 先判断索引正确性
		if (index > size || index < 0) {
			throw new RuntimeException("索引值有错:" + index);
		}
		Node<E> tem = new Node<E>();
		tem = header;
		int count = 0;
		while (count != index) {
			tem = tem.next;
			count++;
		}
		return tem;
	}

	/**
	 * 根据索引,取得该索引下的数据
	 * 
	 * @param index
	 * @return
	 */
	public E get(int index) {
		// 先判断索引正确性
		if (index >= size || index < 0) {
			throw new RuntimeException("索引值有错:" + index);
		}
		Node<E> tem = new Node<E>();
		tem = header;
		int count = 0;
		while (count != index) {
			tem = tem.next;
			count++;
		}
		E e = tem.e;
		return e;
	}

	public int size() {
		return size;
	}

	/**
	 * 设置第N个结点的值
	 * 
	 * @param x
	 * @param e
	 * @return
	 */
	public boolean set(int index, E e) {
		// 先判断索引正确性
		if (index > size || index < 0) {
			throw new RuntimeException("索引值有错:" + index);
		}
		Node<E> newNode = new Node<E>(e);
		// 得到第x个结点
		Node<E> cNode = getNode(index);
		cNode.e = e;
		return true;
	}

	/**
	 * 用来存放数据的结点型内部类
	 */
	class Node<e> {
		private E e;// 结点中存放的数据

		Node() {
		}

		Node(E e) {
			this.e = e;
		}

		Node<E> next;// 用来指向该结点的下一个结点

		// 在此结点后加一个结点
		void addNext(Node<E> node) {
			next = node;
		}
	}

}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值