java实现链接表

链接表:
    1、基于节点的操作:在前面的对线性表抽象数据类型的操作中,其提供的操作主要是对线性表中的数据元素及其序号的。例如插入操作就是基于序号和元素进行的insert(int i,Object e); 是在序号为i的地方插入e,这种基于序号的操作实际上并不适合采用链表来实现,因为为了在链表中定位数据元素或序号,不得不沿着节点的引用,从链表前端开始扫描。它的时间复杂度O(n^2)。


定义链接表的接口:

package 线性表.lianjiebiao;


import 线性表.iterator.Iterator;
import 线性表.linkedlist.Node;
import 线性表.sunxu.OutOfBoundaryException;

/**
 * 链接表接口的定义
 * @author acer
 */
public interface LinkedList {

	//查询链接表当前的规模
	public int getSize();
	
	//判断列表是否为空
	public boolean isEmpty();
	
	//返回第一个节点
	public Node first() throws OutOfBoundaryException;
	
	//返回最后一个节点
	public Node last() throws OutOfBoundaryException;
	
	//返回p之后的节点
	public Node getNext(Node p) throws OutOfBoundaryException;
	
	//返回p之前的节点
	public Node getPre(Node p) throws OutOfBoundaryException;
	
	//将e作为第一个元素插入链接表,并返回e所在的节点
	public Node insertFirst(Object c);
	
	//将e作为最后一个元素插入链接表,并返回e所在的节点
	public Node insertLast(Object c);
	
	//将e插入p之后的位置,并返回节点
	public Node insertAfter(Node o,Object c);
	
	//将e插入p之前的位置,并返回节点
	public Node insertBefore(Node o,Object c);
	
	//删除给定位置的元素,并返回
	public Object remove(Node p);
	
	//删除首元素,并返回
	public Object removeFirst();
	
	//删除尾元素,并返回
	public Object removeLast();
	
	//将处于给定位置的元素替换为新元素,并返回被替换的元素
	public Object replace(Node p,Object c);
	
	//元素迭代器
	public Iterator elements() throws OutOfBoundaryException;
}

定义他的异常:

package 线性表.lianjiebiao;

/**
 * 定义节点的异常
 * @author acer
 * 1.p == null 2.p在链接表中不存在	 3.调用p.getPre(node p)时,p已经是第一个节点  4.调用p.getNext()时,p已经是最后一个节点
 */
public class InvalidNodeException extends RuntimeException{

	public InvalidNodeException(String err) {
		super(err);
	}
}

链接表的节点:它是双向链表:

package 线性表.linkedlist;

/**
 * 双向链表的实现结构
 * @author acer
 */
public class DLNode implements Node{

	private Object data;//数据域
	private DLNode next;//后续节点
	private DLNode pre;//前驱节点
	
	public DLNode(){
		
	}
	
	public DLNode(Object o,DLNode next,DLNode pre) {
		this.data = o;
		this.next = next;
		this.pre = pre;
	}

	public DLNode getNext() {
		return next;
	}

	public void setNext(DLNode next) {
		this.next = next;
	}

	public DLNode getPre() {
		return pre;
	}

	public void setPre(DLNode pre) {
		this.pre = pre;
	}

	@Override
	public Object getData() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setData(Object o) {
		// TODO Auto-generated method stub
		
	}
}

链接表的实现类:

package 线性表.lianjiebiao;

import 线性表.iterator.Iterator;
import 线性表.iterator.LinkedListIterator;
import 线性表.linkedlist.DLNode;
import 线性表.linkedlist.Node;
import 线性表.sunxu.OutOfBoundaryException;

/**
 * 基于双向链表实现的链接表
 * @author acer
 */
public class LinkedListDLNode implements LinkedList{

	private int size;//规模
	private DLNode head;//头节点
	private DLNode tail;//尾节点
	
	public LinkedListDLNode() {
		size = 0;
		//构建只有头尾节点的链表
		head = new DLNode();
		tail = new DLNode();
		
		head.setNext(tail);
		tail.setPre(head);
	}
	
	@Override
	public int getSize() {
		return size;
	}

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

	@Override
	public Node first() throws OutOfBoundaryException {
		if(isEmpty())
			throw new OutOfBoundaryException("错误:链接表为空");
		return head.getNext();
	}

	@Override
	public Node last() throws OutOfBoundaryException {
		if(isEmpty())
			throw new OutOfBoundaryException("错误:链接表为空");
		return tail.getPre();
	}

	@Override
	public Node getNext(Node p) throws OutOfBoundaryException {
		DLNode node = this.checkPosition(p);
		node = node.getNext();
		if(node == tail)
			throw new OutOfBoundaryException("已经到达链表的尾段");
		return node;
	}

	@Override
	public Node getPre(Node p) throws OutOfBoundaryException {
		DLNode node = this.checkPosition(p);
		node = node.getPre();
		if(node == head)
			throw new OutOfBoundaryException("错误:已经到达链表的头部");
		return node;
	}

	@Override
	public Node insertFirst(Object c) {
		DLNode node = new DLNode(c,head,head.getNext());
		head.getNext().setPre(node);
		head.setNext(node);
		size ++;
		return node;
	}

	@Override
	public Node insertLast(Object c) {
		DLNode node = new DLNode(c,tail.getPre(),tail);
		tail.getPre().setNext(node);
		tail.setPre(node);
		size ++;
		return node;
	}
	
	@Override
	public Node insertAfter(Node o, Object c) {
		DLNode node = this.checkPosition(o);
		DLNode newNode = new DLNode(c,node,node.getNext());
		node.setNext(newNode);
		node.getNext().setPre(newNode);
		size ++;
		return newNode;
	}

	@Override
	public Node insertBefore(Node o, Object c) {
		DLNode node = this.checkPosition(o);
		DLNode newNode = new DLNode(c,node.getPre(),node);
		node.setPre(newNode);
		node.getPre().setNext(newNode);
		size ++;
		return newNode;
	}

	@Override
	public Object remove(Node p) {
		DLNode node = this.checkPosition(p);
		node.getPre().setNext(node.getNext());
		node.getNext().setPre(node.getPre());
		size --;
		return node.getData();
	}

	@Override
	public Object removeFirst() {
		return this.remove(head.getNext());
	}

	@Override
	public Object removeLast() {
		// TODO Auto-generated method stub
		return this.remove(tail.getPre());
	}

	@Override
	public Object replace(Node p, Object c) {
		DLNode node = (DLNode)p;
		Object o = node.getData();
		node.setData(c);
		return o;
	}

	@Override
	public Iterator elements() throws OutOfBoundaryException {
		// TODO Auto-generated method stub
		return new LinkedListIterator(this);
	}

	
	//辅助方法,判断节点是否合法
	protected DLNode checkPosition(Node p) throws InvalidNodeException{
		if(p == null) 
			throw new InvalidNodeException("错误:节点为空");
		if(p == head)
			throw new InvalidNodeException("错误:指向头节点,非法");
		if(p == tail)
			throw new InvalidNodeException("错误:指向尾节点,非法");
		
		DLNode node = (DLNode)p;
		return node;
	}
}

上面的实现类中应用到了迭代器:下面实现迭代器:

迭代器:
    迭代器是程序设计的一种模式,它属于设计模式中的行为模式,它的功能是提供一种方法顺序访问一个聚集对象中的各个元素,而又不需要暴露该对象的内部实现。
    多个对象聚集在一起形成的总体称之为聚集(Aggregate),聚集对象是能够包容一组对象的容器对象。聚集依赖于聚集结构的抽象化,具有复杂性和多样性。数组就是一组最基本的聚集。
    聚集对象需要提供一种方法,允许用户按照一定的顺序访问其中所有元素。而迭代器提供了一个访问聚集对象中各个元素的统一接口,简单的说迭代器就是对遍历操作的抽象。
    

    迭代器的实现可以根据不同的聚集对象给出不同的实现。

package 线性表.iterator;

import 线性表.sunxu.OutOfBoundaryException;

/**
 * 迭代器的java接口
 * @author acer
 */
public interface Iterator {

	//移动到第一个元素
	public void first() throws OutOfBoundaryException;
	
	//移动到下一个元素
	public void next() throws OutOfBoundaryException;
	
	//检查迭代器中是否还有剩余元素
	public boolean isDone();
	
	//返回当前元素
	public Object currentItem();
}

迭代器的实现:

package 线性表.iterator;

import 线性表.lianjiebiao.*;
import 线性表.linkedlist.Node;
import 线性表.sunxu.OutOfBoundaryException;

public class LinkedListIterator implements Iterator{
	
	private LinkedList list;//链接表
	private Node current;//当前节点
	
	public LinkedListIterator(LinkedList list) throws OutOfBoundaryException {
		this.list = list;
		if(list.isEmpty())
			current = null;
		current = list.first();
	}

	@Override
	public void first() throws OutOfBoundaryException {
		if(list.isEmpty())
			current = null;
		current = list.first();
	}

	@Override
	public void next() throws OutOfBoundaryException {
		if(isDone())
			throw new OutOfBoundaryException("错误:已经没有元素");
		if(current == list.last())
			current = null;
		current = list.getNext(current);
	}

	@Override
	public boolean isDone() {
		return current == null;
	}

	@Override
	public Object currentItem() {
		return current.getData();
	}

}

以上便是链接表的实现,它的效率得到了极大的提高。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值