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 } }
具体原理看代码实现。
特别注意:双端链表不是双向链表。
- Java数据结构和算法--链表
- Java数据结构和算法--链表
- Java数据结构和算法--链表
- Java 数据结构和算法 链表
- JAVA数据结构和算法
- Java 数据结构和算法
- java 数据结构和算法
- Java数据结构和算法
- java数据结构和算法
- Java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- java数据结构和算法
- Java数据结构和算法系列1--链表
- Java数据结构和算法(链表)
- Docker(2)--Docker常用命令
- Maven Perform a Release
- FWT板子
- Oracle 日期时间模糊查询
- gdb调试c++代码
- Java 数据结构和算法 链表
- oracle取时间最大的一条数据
- 模块化、高扩展的web验证功能
- Hive llap服务安装说明及测试
- 泛型(一)
- Java学习之线程组
- HTML元素的display属性
- Android 子线程和UI线程(主线程)的几种交互方式
- Node在Visual Studio Code 上运行