线性表

本文详细介绍了线性表的概念、抽象数据类型及接口定义,并通过数组和链表两种存储方式实现线性表,包括单链表和双向链表的节点定义与操作实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线性表指的事n个类型相同数据元素的有限序列,通常记作(A0,A1,…..Ai…..An-1)。在数据元素的有限集中,除第一个元素无直接前驱,最后一个元素无直接后续以外,每个数组元素有且仅有一个直接前驱元素和直接后继元素。


1.抽象数据类型

ADT List{
这里写图片描述
这里写图片描述
}


2.List接口

public interface List {
    //返回线性表大小
    public int getSize();
    //线性表为空返回true,否则返回false
    public boolean isEmpty();
    //是否包含e
    public boolean contains(Object e);
    //e的位置
    public int indexOf(Object e);
    //e插入到i的位置
    public void insert(int i, Object e) throws OutBoundaryException;
    //e插到obj前
    public boolean insertBefore(Object obj,Object e);
    //e插到obj后
    public boolean insertAfter(Object obj,Object e);
    //删除序号i的元素并返回值
    public Object remove(int i) throws OutBoundaryException;
    //删除第一个与e相同的元素
    public boolean remove(Object e);
    //替换i位置的元素为e,并返回原值
    public Object replace(int i,Object e) throws OutBoundaryException;
    //返回i位置元素
    public Object get(int i) throws OutBoundaryException;
}

/**
 * 异常类
 *
 */
class OutBoundaryException extends RuntimeException{
    public OutBoundaryException(String err){
        super(err);
    }
}

/**
 * 比较策略接口
 *
 */
interface Strategy{
    //判断两元素数据是否相等
    public boolean equal(Object obj1,Object obj2);
    /*
     * 比较两个数据元素大小
     * obj1 < obj2 返回-1
     * obj1 = obj2 返回0
     * obj1 > obj2 返回1
     */
    public int compare(Object obj1,Object obj2);
}

/**
 * 默认比较策略
 *
 */
class DefaultStrategy implements Strategy{

    @Override
    public boolean equal(Object obj1, Object obj2) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public int compare(Object obj1, Object obj2) {
        // TODO Auto-generated method stub
        return 0;
    }

}

3.线性表顺序存储结构与实现

这里写图片描述
这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述

/**
 * 线性表的数组实现
 *
 */
public class ListArray implements List {

    private final int LEN = 8;//数组默认大小
    private Strategy strategy;//数据元素比较策略
    private int size;//线性表中数据元素个数
    private Object[] elements;//数据元素数组

    //构造方法
    public ListArray(){
        this(new DefaultStrategy());
    }
    public ListArray(Strategy strategy){
        this.strategy = strategy;
        size = 0;
        elements = new Object[LEN];
    }


    @Override
    public int getSize() {
        return size;
    }

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

    @Override
    public boolean contains(Object e) {
        for(int i=0;i<size;i++){
            if(strategy.equal(e, elements[i])){
                return true;
            }
        }
        return false;
    }

    @Override
    public int indexOf(Object e) {
        for(int i=0;i<size;i++){
            if(strategy.equal(e, elements[i])){
                return i;
            }
        }
        return -1;
    }

    @Override
    public void insert(int i, Object e) throws OutBoundaryException {
        if(i<0 || i>size){
            throw new OutBoundaryException("错误,指定的插入序号越界。");
        }

        if(size >= elements.length){
            expandSpace();
        }
        //后方位置向后移动
        for(int j=size;j>i;j--){
            elements[j] = elements[j-1];
        }
        elements[i] = e;
        size++;
        return;
    }
    //扩容数组
    private void expandSpace(){
        Object[] a = new Object[elements.length*2];
        for(int i=0;i<elements.length;i++){
            a[i] = elements[i];
        }
        elements = a;
    }

    @Override
    public boolean insertBefore(Object obj, Object e) {
        int i = indexOf(obj);
        if(i<0){
            return false;
        }
        insert(i,e);
        return true;
    }

    @Override
    public boolean insertAfter(Object obj, Object e) {
        int i = indexOf(obj);
        if(i<0){
            return false;
        }
        insert(i+1,e);
        return true;
    }

    @Override
    public Object remove(int i) throws OutBoundaryException {
        if(i<0 || i>size){
            throw new OutBoundaryException("错误,指定的插入序号越界。");
        }
        Object obj = elements[i];
        //后方数据向前移动
        for(int j=i;j<size-1;j++){
            elements[j] = elements[j+1];
        }
        elements[--size] = null;
        return obj;
    }

    @Override
    public boolean remove(Object e) {
        int i = indexOf(e);
        if(i<0){
            return false;
        }
        remove(i);
        return true;
    }

    @Override
    public Object replace(int i, Object e) throws OutBoundaryException {
        if(i<0 || i>size){
            throw new OutBoundaryException("错误,指定的插入序号越界。");
        }
        Object obj = elements[i];
        elements[i] = e;
        return obj;
    }

    @Override
    public Object get(int i) throws OutBoundaryException {
        if(i<0 || i>size){
            throw new OutBoundaryException("错误,指定的插入序号越界。");
        }
        return elements[i];
    }

}

4.线性表的链式存储与实现

4.1 单链表

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

/**
 * 单链表结点定义
 *
 */
public class SLNode implements Node{

    private Object element;
    private SLNode next;

    //构造器
    public SLNode() {
        this(null,null);
    }
    public SLNode(Object element, SLNode next) {
        this.element = element;
        this.next = next;
    }

    //get/set方法
    public SLNode getNext() {
        return next;
    }
    public void setNext(SLNode next) {
        this.next = next;
    }

    @Override
    public Object getData() {
        return element;
    }

    @Override
    public void setData(Object obj) {
        element = obj;
    }

}

/**
 * 结点接口
 *
 */
interface Node{
    //获取结点数据域
    public Object getData();
    //设置结点数据域
    public void setData(Object obj);
}
4.2 双向链表

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

/**
 * 双向链表结点定义
 *
 */
public class DLNode implements Node {

    private Object element;
    private DLNode pre;
    private DLNode next;


    public DLNode() {
        this(null,null,null);
    }

    public DLNode(Object element, DLNode pre, DLNode next) {
        this.element = element;
        this.pre = pre;
        this.next = next;
    }


    public DLNode getPre() {
        return pre;
    }

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

    public DLNode getNext() {
        return next;
    }

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

    @Override
    public Object getData() {
        return element;
    }

    @Override
    public void setData(Object obj) {
        element = obj;
    }

}

4.3 线性表的单链表实现

这里写图片描述

/**
 * 线性表的单链表实现
 *
 */
public class ListSLinked implements List {

    private Strategy strategy;//数据元素比较策略
    private SLNode head;//单链表首结点引用
    private int size;//表中数据元素个数


    public ListSLinked() {
        this(new DefaultStrategy());
    }

    public ListSLinked(Strategy strategy) {
        this.strategy = strategy;
        head = new SLNode();
        size = 0;
    }

    //获取前驱结点
    private SLNode getPreNode(Object e){
        SLNode p = head;
        while(p.getNext() != null){
            if(strategy.equal(p.getNext().getData(), e)){
                return p;
            }else{
                p = p.getNext();
            }
        }
        return null;
    }
    //获取序号i[0,size)的前驱结点
    private SLNode getPreNode(int i){
        SLNode p = head;
        for(;i>0;i--){
            p = p.getNext();
        }
        return p;
    }
    //获取序号i[0,size)的结点
    private SLNode getNode(int i){
        SLNode p = head.getNext();
        for(;i>0;i--){
            p = p.getNext();
        }
        return p;
    }


    @Override
    public int getSize() {
        return size;
    }

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

    @Override
    public boolean contains(Object e) {
        SLNode p = head.getNext();
        while(p != null){
            if(strategy.equal(p.getData(), e)){
                return true;
            }
        }
        return false;
    }

    @Override
    public int indexOf(Object e) {
        SLNode p = head.getNext();
        int index = 0;
        while(p != null){
            if(strategy.equal(p.getData(), e)){
                return index;
            }else{
                index++;
                p=p.getNext();
            }
        }
        return -1;
    }

    @Override
    public void insert(int i, Object e) throws OutBoundaryException {
        if(i<0 || i>size){
            throw new OutBoundaryException("错误,指定的插入序号越界。");
        }
        SLNode p = getPreNode(i);
        SLNode q = new SLNode(e,p.getNext());
        p.setNext(q);
        size++;
        return;
    }

    @Override
    public boolean insertBefore(Object obj, Object e) {
        SLNode p = getPreNode(obj);
        if(p!=null){
            SLNode q = new SLNode(e,p.getNext());
            p.setNext(q);
            size++;
            return true;
        }
        return false;
    }

    @Override
    public boolean insertAfter(Object obj, Object e) {
        SLNode p = head.getNext();
        while(p!=null){
            if(strategy.equal(p.getData(), obj)){
                SLNode q = new SLNode(e,p.getNext());
                p.setNext(q);
                size++;
                return true;
            }
        }
        return false;
    }

    @Override
    public Object remove(int i) throws OutBoundaryException {
        if(i<0 || i>size){
            throw new OutBoundaryException("错误,指定的插入序号越界。");
        }
        SLNode p = this.getPreNode(i);
        Object obj = p.getNext().getData();
        p.setNext(p.getNext().getNext());
        size--;
        return obj;
    }

    @Override
    public boolean remove(Object e) {
        SLNode p = this.getPreNode(e);
        if(p != null){
            p.setNext(p.getNext().getNext());
            size--;
            return true;
        }
        return false;
    }

    @Override
    public Object replace(int i, Object e) throws OutBoundaryException {
        if(i<0 || i>size){
            throw new OutBoundaryException("错误,指定的插入序号越界。");
        }
        SLNode p = getNode(i);
        Object obj = p.getData();
        p.setData(e);
        return obj;
    }

    @Override
    public Object get(int i) throws OutBoundaryException {
        if(i<0 || i>size){
            throw new OutBoundaryException("错误,指定的插入序号越界。");
        }
        SLNode p = getNode(i);
        return p.getData();
    }

}

以上都是针对线性表中的数据元素及其序号来操作实现的,下面基于结点操作。

5.链接表

/**
 * 链接表接口
 *
 */
public interface LinkedList {
    //返回线性表大小
    public int getSize();
    //线性表为空返回true,否则返回false
    public boolean isEmpty();
    //返回第一个结点
    public Node first() throws OutBoundaryException;
    //返回最后一个结点
    public Node last() throws OutBoundaryException;
    //返回p之后结点
    public Node getNext(Node p) throws InvalidNodeException,OutBoundaryException;
    //返回p之前结点
    public Node getPre(Node p) throws InvalidNodeException,OutBoundaryException;
    //e作为第一个元素插入,并返回所在结点
    public Node insertFirst(Object e);
    //e作为最后一个元素插入,并返回所在结点
    public Node insertLast(Object e);
    //e插入p后位置,返回e所在结点
    public Node insertAfter(Node p,Object e) throws InvalidNodeException;
    //e插入p前位置,返回e所在结点
    public Node insertBefore(Node p,Object e) throws InvalidNodeException;
    //删除给定位置的元素并返回值
    public Object remove(Node p) throws InvalidNodeException;
    //删除第一个元素,并返回值
    public Object removeFirst() throws OutBoundaryException;
    //删除最后一个元素,并返回值
    public Object removeLast() throws OutBoundaryException;
    //替换给定位置的元素为e,并返回原值
    public Object replace(Node p,Object e) throws InvalidNodeException;
    //元素迭代器
    public Iterator elements();
}

/**
 * InvalidNodeException异常类
 *
 */
class InvalidNodeException extends RuntimeException{
    public InvalidNodeException(String err){
        super(err);
    }
}

这里写图片描述

/**
 * 基于双向链表实现的链接表
 *
 */
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);
    }

    //判断结点p是否合法,如合法转换为DLNode
    protected DLNode checkPosition(Node p) throws InvalidNodeException {
        if(p == null){
            throw new InvalidNodeException("错误,p为空");
        }
        if(p == head){
            throw new InvalidNodeException("错误,p为头结点,非法");
        }
        if(p == tail){
            throw new InvalidNodeException("错误,p为尾结点,非法");
        }
        DLNode node = (DLNode) p;
        return node;
    }

    @Override
    public int getSize() {
        return size;
    }

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

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

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

    @Override
    public Node getNext(Node p) throws InvalidNodeException,
            OutBoundaryException {
        DLNode node = checkPosition(p);
        node = node.getNext();
        if(node == tail){
            throw new OutBoundaryException("错误,已经是链接表尾端");
        }
        return node;
    }

    @Override
    public Node getPre(Node p) throws InvalidNodeException,
            OutBoundaryException {
        DLNode node = checkPosition(p);
        node = node.getPre();
        if(node == head){
            throw new OutBoundaryException("错误,已经是链接表首端");
        }
        return node;
    }

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

    @Override
    public Node insertLast(Object e) {
        DLNode node = new DLNode(e,tail.getPre(),tail);
        tail.getPre().setNext(node);
        tail.setPre(node);
        size++;
        return node;
    }

    @Override
    public Node insertAfter(Node p, Object e) throws InvalidNodeException {
        DLNode node = checkPosition(p);
        DLNode newNode = new DLNode(e,node,node.getNext());
        node.getNext().setPre(newNode);
        node.setNext(newNode);
        size++;
        return newNode;
    }

    @Override
    public Node insertBefore(Node p, Object e) throws InvalidNodeException {
        DLNode node = checkPosition(p);
        DLNode newNode = new DLNode(e,node.getPre(),node);
        node.getPre().setNext(newNode);
        node.setPre(newNode);
        size++;
        return newNode;
    }

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

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

    @Override
    public Object removeLast() throws OutBoundaryException {
        return remove(tail.getPre());
    }

    @Override
    public Object replace(Node p, Object e) throws InvalidNodeException {
        DLNode node = checkPosition(p);
        Object obj = node.getData();
        node.setData(e);
        return obj;
    }

    @Override
    public Iterator elements() {
        return new LinkedListIterator(this);
    }

}

6.迭代器

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

class LinkedListIterator implements Iterator{

    private LinkedList list;//链接表
    private Node current;//当前结点


    public LinkedListIterator(LinkedList list) {
        this.list = list;
        if(list.isEmpty()){
            current = null;
        }else{
            current = list.first();
        }
    }

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

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

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

    @Override
    public Object currentItem() throws OutBoundaryException{
        if(isDone()){
            throw new OutBoundaryException("错误,已经没有元素");
        }
        return current.getData();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值