Java 数据结构和算法 链表

本文深入探讨了Java中的链表数据结构,包括链结点、单链表的实现,以及查找和删除指定链结点的操作。文章还介绍了双端链表的概念,强调其与传统链表的区别,并提供了相关的代码实现。
摘要由CSDN通过智能技术生成

链表

本章将学习一种全新的数据结构,链表。
链表的 机制灵活,用途广泛,它适用于许多通用的数据库,它也可以取代数组,作为其他存储结构的基础,例如栈、队列等等。除非需要频繁的通过下标随机访问各个数据,否则在很多实用数组的地方都可以用链表代替。

链结点

在链表中,每个数据项被包含在链结点中,一个链结点是某个类的对象,这个类可以叫做 Link ,因为一个链表中有许多类似的链结点,所有有必要用一个不同于链表的类来表达链结点,每一个Link对象都包含对下一个链结点引用的字段,但是链表本身的对象有一个字段指向对第一个链结点的引用。

如下图所示:

这里写图片描述

对一个链结点的申明:

class Link
   {
   public int iData;              // data item
   public double dData;           // data item
   public Link next;              // next link in list
   } 

这种类定义有时叫做“自引用”式,因为它包含了一个和自己类型相同的字段。
链结点中仅包含两个数据项,一个 int型,一个 double型,但是真正的应用程序中可能包含更多的数据项,通常用这些数据的类对象来代替这些数据项。

单链表

代码实现:

class Link {
    public int iData;
    public double dData;
    public Link next;

    public Link(int id, double dd) {
        iData = id;
        dData = dd;
    }

    public void displayLink() {
        System.out.print("{" + iData + ", " + dData + "} ");
    }
}

class LinkList {
    private Link first; // ref to first link on list

    public LinkList() // constructor
    {
        first = null; // no links on list yet
    }

    public boolean isEmpty() // true if list is empty
    {
        return (first == null);
    }

    // insert at start of list
    public void insertFirst(int id, double dd) { // make new link
        Link newLink = new Link(id, dd);
        newLink.next = first; // newLink --> old first
        first = newLink; // first --> newLink
    }

    public Link deleteFirst() // delete first item
    { // (assumes list not empty)
        Link temp = first; // save reference to link
        first = first.next; // delete it: first-->old next
        return temp; // return deleted link
    }

    public void displayList() {
        System.out.print("List (first-->last): ");
        Link current = first; // start at beginning of list
        while (current != null) // until end of list,
        {
            current.displayLink(); // print data
            current = current.next; // move to next link
        }
        System.out.println("");
    }

}

class LinkListApp {
    public static void main(String[] args) {
        LinkList theList = new LinkList(); 

        theList.insertFirst(22, 2.99); // 插入数据
        theList.insertFirst(44, 4.99);
        theList.insertFirst(66, 6.99);
        theList.insertFirst(88, 8.99);

        theList.displayList(); // 输出

        while (!theList.isEmpty()) 
        {
            Link aLink = theList.deleteFirst(); 
            System.out.print("Deleted "); 
            aLink.displayLink();
            System.out.println("");
        }
        theList.displayList(); 
    }
}

这里详细介绍两个地方,一个是插入,一个是删除。
在初始化链表的时候,头结点初始化为null,插入新的数据时,新数据的next指向头结点,如果是第一个数据项,则可以看出第一个数据项的next指向null,然后将头结点重新指向当前数据项,如果下次再插入,则新插入的数据的next指向当前的头结点,以此类推。

删除数据时,首先创建一个link对象来保存将要删除的节点,然后将第一个结点后移,即完成删除。

查找和删除指定链结点

代码实现:

class Link
   {
   public int iData;              
   public double dData;          
   public Link next;              

   public Link(int id, double dd) 
      {
      iData = id;
      dData = dd;
      }

   public void displayLink()      // display ourself
      {
      System.out.print("{" + iData + ", " + dData + "} ");
      }
   } 

class LinkList
   {
   private Link first;          


   public LinkList()              
      {
      first = null;               
      }

   public void insertFirst(int id, double dd)
      {                           // make new link
      Link newLink = new Link(id, dd);
      newLink.next = first;       // it points to old first link
      first = newLink;            // now first points to this
      }
// -------------------------------------------------------------
   public Link find(int key)      // find link with given key
      {                           // (assumes non-empty list)
      Link current = first;              // start at 'first'
      while(current.iData != key)        // while no match,
         {
         if(current.next == null)        // if end of list,
            return null;                 // didn't find it
         else                            // not end of list,
            current = current.next;      // go to next link
         }
      return current;                    // found it
      }
// -------------------------------------------------------------
   public Link delete(int key)    // delete link with given key
      {                           // (assumes non-empty list)
      Link current = first;              // search for link
      Link previous = first;
      while(current.iData != key)
         {
         if(current.next == null)
            return null;                 // didn't find it
         else
            {
            previous = current;          // go to next link
            current = current.next;
            }
         }                               // found it
      if(current == first)               // if first link,
         first = first.next;             //    change first
      else                               // otherwise,
         previous.next = current.next;   //    bypass it
      return current;
      }
// -------------------------------------------------------------
   public void displayList()      // display the list
      {
      System.out.print("List (first-->last): ");
      Link current = first;       // start at beginning of list
      while(current != null)      // until end of list,
         {
         current.displayLink();   // print data
         current = current.next;  // move to next link
         }
      System.out.println("");
      }

   }  

class LinkList2App
   {
   public static void main(String[] args)
      {
      LinkList theList = new LinkList();  // make list

      theList.insertFirst(22, 2.99);      // insert 4 items
      theList.insertFirst(44, 4.99);
      theList.insertFirst(66, 6.99);
      theList.insertFirst(88, 8.99);

      theList.displayList();              // display list

      Link f = theList.find(44);          // find item
      if( f != null)
         System.out.println("Found link with key " + f.iData);
      else
         System.out.println("Can't find link");

      Link d = theList.delete(66);        // delete item
      if( d != null )
         System.out.println("Deleted link with key " + d.iData);
      else
         System.out.println("Can't delete link");

      theList.displayList();              
      }  
   }  

查找和删除时都是通过不断的向后移动节点,然后比较节点的关键字,不同的是,删除之后,需要对链表做相关的操作,防止链表断掉,如果删除当前节点,应该让前一个节点的next指向挡墙节点的next,而不是指向当前节点。

双端链表

双端链表与传统的链表非常相似,但它有一个新增的特性,对最后一个节点的引用就像对第一个节点的引用一样。

这里写图片描述

代码实现:

class Link
   {
   public long dData;               
   public Link next;               

   public Link(long d)              
      { dData = d; }

   public void displayLink()          
      { System.out.print(dData + " "); }

   }  

class FirstLastList
   {
   private Link first;               // ref to first link
   private Link last;                // ref to last link

   public FirstLastList()            // constructor
      {
      first = null;                  // no links on list yet
      last = null;
      }

   public boolean isEmpty()          // true if no links
      { return first==null; }

   public void insertFirst(long dd)  // insert at front of list
      {
      Link newLink = new Link(dd);   // make new link

      if( isEmpty() )                // if empty list,
         last = newLink;             // newLink <-- last
      newLink.next = first;          // newLink --> old first
      first = newLink;               // first --> newLink
      }

   public void insertLast(long dd)   // insert at end of list
      {
      Link newLink = new Link(dd);   // make new link
      if( isEmpty() )                // if empty list,
         first = newLink;            // first --> newLink
      else
         last.next = newLink;        // old last --> newLink
      last = newLink;                // newLink <-- last
      }

   public long deleteFirst()         // delete first link
      {                              // (assumes non-empty list)
      long temp = first.dData;
      if(first.next == null)         // if only one item
         last = null;                // null <-- last
      first = first.next;            // first --> old next
      return temp;
      }

   public void displayList()
      {
      System.out.print("List (first-->last): ");
      Link current = first;          // start at beginning
      while(current != null)         // until end of list,
         {
         current.displayLink();      // print data
         current = current.next;     // move to next link
         }
      System.out.println("");
      }
// -------------------------------------------------------------
   }  

class FirstLastApp
   {
   public static void main(String[] args)
      {                              // make a new list
      FirstLastList theList = new FirstLastList();

      theList.insertFirst(22);       // insert at front
      theList.insertFirst(44);
      theList.insertFirst(66);

      theList.insertLast(11);        // insert at rear
      theList.insertLast(33);
      theList.insertLast(55);

      theList.displayList();         // display the list

      theList.deleteFirst();         // delete first two items
      theList.deleteFirst();

      theList.displayList();         // display again
      }  
   }  

这里写图片描述

具体原理看代码实现。
特别注意:双端链表不是双向链表。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值