数据结构-链表的Java实现

顺序表的Java实现

1.链式存储结构

顺序存储结构要求所有元素依次存放在一片连续的存储空间中,而链式存储结构,无需占用一整块存储空间。但为表示结点之间的关系,需要给每个结点附加指针字段,用于存放后继元素的存储地址。

仍然使用我们在学习顺序表时使用的ElemType作为数据元素。建一个新的LinkNode类作为结点,结点包含一个ElemType作为数据域,附加一个LinkNode作为指针域,用于存放后继结点的地址。
数据元素和结点
ElemType封装类的代码见 顺序表的Java实现
LinkNode封装类的代码如下

public class LinkNode{
    private ElemType e;
    private LinkNode next;

    public LinkNode(){}//无参构造方法
    public LinkNode(ElemType e){//以数据为参数构造结点
        this.e=e;
    }

    public ElemType getE() {
        return e;
    }
    public void setE(ElemType e) {
        this.e = e;
    }

    public LinkNode getNext() {
        return next;
    }
    public void setNext(LinkNode next) {
        this.next = next;
    }
}

链式存储结构如图:
链式存储结构

2.链表的构造

和顺序表一样,我们将链表封装为一个类,这个类同样实现了我们在 顺序表的Java实现 中定义的抽象数据类型(ADT)接口。

在顺序表中,定义一个ELemType类型的数组来存放数据,通过有参数的构造方法来创建固定长度的数组;
而在链表中,只需要定义一个LinkNode结点,用这个结点来作为我们存储和操作的对象,new一个链表,就是初始化一个头结点。

public class LinkList implements MyList {
    private LinkNode linkList;

    public LinkList(){
        linkList=new LinkNode();
        linkList.setNext(null);
    }
    /*链表的相关方法见下文*/
}

3.链表的清空

链表的头结点携带者链表的全部信息,因此判断链表是否为空,或者将链表清空都只需要访问或者操作头结点。

    @Override
    public void clear() {
        linkList.setNext(null);
    }

    @Override
    public boolean isEmpty() {
        return linkList.getNext()==null;
    }

4.链表的长度

获得链表的长度就是要从头结点开始不断访问下一个结点,直到结点为null。
1.用p=头结点;i=0
2.p=p.getNext();i++
3.不断重复2,直到p==null;
4.返回i.

    @Override
    public int listLength() {
        LinkNode p=linkList;
        int i;
        for(i=0;p.getNext()!=null;i++){
            p=p.getNext();
        }
        return i;
    }

5.链表的访问、遍历与查询

访问

1.用p=头结点;j=0
2.p=p.getNext();j++
3.不断重复2,直到j==i;判读i是否合理(写的时候忘了判断和抛出异常)
4.返回p.getE().

遍历

1.用p=头结点;
2.p=p.getNext(); 打印数据域p.getE();
3.不断重复2,直到p.getNext()=null

查询

1.用p=头结点;
2.p=p.getNext();
3.不断重复2,直到p.getE().equal(x);判读i是否合理(忘了判断)
4.返回p.getE().

    @Override
    public ElemType getElem(int i) throws Exception {
        LinkNode p=linkList;
        int j;
        for(j=0;j<i||p!=null;j++){
            p=p.getNext();
        }
        return p.getE();
    }
    
    @Override
    public void display() {
        LinkNode p=linkList.getNext();
        System.out.print(p.getE().toString());
        p=p.getNext();
        while(p!=null){
            System.out.print(" -> ");
            System.out.print(p.getE().toString());
            p=p.getNext();
        }
        System.out.println();
    }
    
    @Override
    public int getIndex(ElemType x) throws Exception {
        LinkNode p=linkList;
        for(int i=0;p!=null;i++){
            p=p.getNext();
            if (p.getE().toString().equals(x.toString())){
                return i;
            }
        }
        return 0;
    }

5.链表的插入与删除

插入

1.新建p=头结点; 建立以参数x为数据域的新结点xNode; j=0;
2.p=p.getNext();j++
3.不断重复2,直到j==i;判读是否越界,是则抛出异常
4.xNode的指针域置位p.getNext();
5.p的指针域置位xNode
链表的插入

删除

1.新建p=头结点 ; j=0;
2.p=p.getNext();j++
3.不断重复2,直到j==i;判读是否越界,是则抛出异常
4.新建q=p.getNext();
5.把p的next设置为q.getNext().
在这里插入图片描述

 @Override
    public void insert(int i, ElemType x) throws Exception {
        LinkNode p=linkList;
        LinkNode xNode=new LinkNode(x);
        for(int j=0;j<i;j++){
            if (i<0||p.getNext()==null){
                throw new Exception("越界了,无法插入");
            }
            p=p.getNext();
        }
        xNode.setNext(p.getNext());
        p.setNext(xNode);
    }

    @Override
    public void remove(int i) throws Exception {
        LinkNode p=linkList;
        for(int j=0;j<i;j++){
            if (i<0||p.getNext()==null){
                throw new Exception("越界了,无法删除");
            }
            p=p.getNext();
        }
        LinkNode q=p.getNext();
        p.setNext(q.getNext());
    }

6.链表的测试

和顺序表一样,我们创建一个测试的类来完成测试,结果如下:
测试结果
测试代码:

public class ListTest {
    public static void main(String[] args){   
        ElemType elem1=new ElemType("王",1);
        ElemType elem2=new ElemType("张",2);
        ElemType elem3=new ElemType("李",3);
        ElemType elem4=new ElemType("李",4);
        ElemType elem5=new ElemType("赵",5);
   
        System.out.println();
        System.out.println("/---创建链表:---/");
        LinkList linkList=new LinkList();
        System.out.println("是否为空:"+linkList.isEmpty());
        System.out.println();
        System.out.println("/---插入操作:---/");
        try {
            linkList.insert(0,elem1);
            linkList.insert(1,elem2);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("输出链表:");
        linkList.display();
        System.out.println("链表长度:"+linkList.listLength());

        System.out.println();
        System.out.println("/---查找索引:---/");
        try {
            System.out.println(elem2.toString()+"的下标为:"+linkList.getIndex(elem2));
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        System.out.println();
        System.out.println("/---删除操作:---/");
        try {
            linkList.remove(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("输出链表:");
        linkList.display();
        System.out.println("链表长度:"+linkList.listLength());
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值