Java 数据结构和算法 链表

来源:互联网 发布:2016华语电影知乎 编辑:程序博客网 时间:2024/06/06 14:11

链表

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

链结点

在链表中,每个数据项被包含在链结点中,一个链结点是某个类的对象,这个类可以叫做 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      }     }  

这里写图片描述

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

原创粉丝点击