数据结构05:链表(4)

108 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

在上一篇中我们分析并设计了链表的删除、置空方法,本篇将继续与大家一起设计list(链表) 类的比较、深拷贝方法即链表的扩展。

到了本篇,我们也已逐步实现了链表的以下几种方法:

public class List{
    public Node head;   // 头节点,其value属性用以表示链表长度
    
    public List()   // 构造器方法,初始化一个空链表
    
    public void add(int value)  // 头插法public void append(int value)  // 尾插法
        
    public void delete(int index)   // 删除链表中的第 index 个节点
        
    public void setNull()   // 清空一个链表
}

我们首先来设计链表的equals(比较)方法,在Java中有两种比较方式:

  • 比较的双方是同一个对象;
  • 比较的双方值是否相等;

当比较的双方是是同一个对象时,那它们里面存储的值必然相等;所以我们的equals(比较)方法只需要要实现比较两个链表中所有元素的值是否完全相等就行了。

public boolean equals(List list)
{
    Node p = this.head;
    NOde q = list.head;
    while(p.next != null)
    {
        if(p.value != q.value)
            return false;
        p = p.next;
        q = q.next;
    }
    return true;
}

由于我们将链表的长度存储在head(头节点)value属性中,所以我们可以先判断链表的长度来排除大部分链表长度不相等的情况,这也是我们从头节点开始比较的原因(可以少写一个 if 比较语句)。

然后我们来构建深拷贝的方法,与在顺序表中相同,我们想要的是可以得到一个值相同但与原有链表完全完全无关的的新对象。

public List copy()
{
    List newList = new List();
    Node p = this.head.next;
    for(int i = 0; i < this.head.value; i++)
        newList.append(p.value);
    return newList;
}

链表的扩展:双链表

到现在为止,我们总共为List类分别设计了添加、删除、置空、比较等共计6个方法,但我们到现在为止使用的都是单链表即所有的节点中存储在一个指向其他节点的指针的链表

单链表的结构倒置了单链表在遍历时,只能不断向后遍历无法逆向遍历。这也使得我们在操作链表时,只能操作链表的后继节点而无法操作前驱节点。所以就出现了单链表的扩展——双链表

双链表的结构与单链表的结构基本一致,唯一不同的地方则在与单链表的节点相比双链表的节点都要多出一个指向前驱节点的指针,使得一个节点既能够访问前驱节点也能够访问后继节点,这大大提高了双链表的随机读取能力。但也是因为每个双链表节点都比单链表节点多出一个属性,这也倒置双链表要占据更大空间才能存储同样大小的数据。

小结

本章主要讲解了链表的基本构成,以及链表是怎么添加元素的。

天天学习,加速成长!

希望与各位一起变得越来越强!