1.链表:链表是继数组之后第二种使用的最广泛的通用存储结构,它克服了数组的许多弊端:无序数组的查找慢问题,有序数组的插入慢问题,数组定义时的定长问题。它也可取代数组,作为其他数据结构的基础。
2.引用的概念补充:
3.单链表代码:
3.1.Link.java
1 package com.cn.linklist; 2 /** 3 * 单链表节点对象 4 * @author Administrator 5 * 6 */ 7 public class Link { 8 public int idata; 9 public double ddata; 10 public Link next; 11 12 public Link(int id,double dd){ 13 idata = id; 14 ddata = dd; 15 } 16 public void displaylink(){ 17 System.out.print("{"+idata+","+ddata+"}"); 18 } 19 }
3.2.LinkList.java
1 package com.cn.linklist; 2 3 /** 4 * 单链表对象 5 * @author Administrator 6 * 7 */ 8 public class LinkList { 9 private Link first; 10 public LinkList(){ 11 first = null; 12 } 13 public boolean isEmpty(){ 14 return (first == null); 15 } 16 public Link find(int key){ 17 Link current = first; 18 while (current.idata != key){ 19 if (current.next == null) 20 return null; 21 current = current.next; 22 } 23 return current; 24 } 25 public Link delete(int key){ 26 Link current = first; 27 Link previous = first; 28 while (current.idata != key){ 29 if (current.next == null) 30 return null; 31 previous = current; 32 current = current.next; 33 } 34 if (current == first) 35 first = first.next; 36 else 37 previous.next = current.next; 38 return current; 39 } 40 public void insertFirst(int id,double dd){ 41 Link newlink = new Link(id, dd); 42 newlink.next = first; 43 first = newlink; 44 } 45 public Link deleteFirst(){ 46 Link tmp = first; 47 first = first.next; 48 return tmp; 49 } 50 public void displaylist() throws InterruptedException{ 51 System.out.print("list(first--->last):"); 52 Link current = first; 53 while (current != null){ 54 current.displaylink(); 55 current = current.next; 56 } 57 System.out.println(""); 58 } 59 }
3.3.LLTest.java
1 package com.cn.linklist; 2 /** 3 * 单链表的测试代码 4 * @author Administrator 5 * 6 */ 7 public class LLTest { 8 public static void main(String[] args) throws InterruptedException { 9 LinkList list = new LinkList(); 10 list.insertFirst(0, 22); 11 list.insertFirst(1, 10); 12 list.insertFirst(2, 33); 13 list.displaylist(); 14 while (! list.isEmpty()){ 15 System.out.println(list.deleteFirst().idata); 16 } 17 } 18 }
4.双端链表:双端链表和单链表类似,但是它有一个新特性:即对最后一个链节点的引用,它使得链表可以像单链表一样在表添加一个链节点,可用双端链表作为队列的底层数据结构来实现。
5.双端链表代码:
5.1.LinkT.java
1 package com.cn.linklist; 2 /** 3 * 双端链表节点 4 * @author Administrator 5 * 6 */ 7 public class LinkT { 8 public long ddata; 9 public LinkT next; 10 public LinkT(long dd){ 11 ddata = dd; 12 } 13 public void displaylink(){ 14 System.out.print("{"+ddata+"}"); 15 } 16 }
5.2.LinkTList.java
1 package com.cn.linklist; 2 /** 3 * 双端链表实现 4 * @author Administrator 5 * 6 */ 7 public class LinkTList { 8 private LinkT first; 9 private LinkT last; 10 public LinkTList(){ 11 first = null; 12 last = null; 13 } 14 public boolean isEmpty(){ 15 return (first == null); 16 } 17 public void insertFirst(long dd){ 18 LinkT l = new LinkT(dd); 19 if (isEmpty()) 20 last = l; 21 l.next = first; 22 first = l; 23 } 24 public void insertLast(long dd){ 25 LinkT l = new LinkT(dd); 26 if (isEmpty()) 27 first = l; 28 else 29 last.next = l; 30 last = l; 31 } 32 public long deleteFirst(){ 33 long temp = first.ddata; 34 if (first.next == null) 35 last = null; 36 first = first.next; 37 return temp; 38 } 39 public void displaylinktlist(){ 40 System.out.print("list(first--->last):"); 41 LinkT current = first; 42 while (current != null){ 43 current.displaylink(); 44 current = current.next; 45 } 46 System.out.println(""); 47 } 48 49 }
5.3.LTLTest.java
1 package com.cn.linklist; 2 /** 3 * 双端链表测试代码 4 * @author Administrator 5 * 6 */ 7 public class LTLTest { 8 public static void main(String[] args) { 9 LinkTList list = new LinkTList(); 10 list.insertFirst(100); 11 list.insertLast(200); 12 list.insertFirst(300); 13 list.insertFirst(400); 14 list.insertLast(500); 15 list.displaylinktlist(); 16 while (! list.isEmpty()){ 17 System.out.print(list.deleteFirst()); 18 System.out.print(" "); 19 } 20 System.out.println(list.isEmpty()); 21 } 22 }
6.链表的效率:在表头添加和删除节点时间复杂度O(1),查找,删除,和在指定位置插入节点的平均时间复杂度为:O(N).与数组比较,链表在插入和删除时的效率要高得多,因为它可以成功的避开多次移动造成的时间浪费。另为,链表需要多少内存就可得到多少,是在定义时不需要指定大小的。
7.抽象数据类型(ADT):他是一种考虑数据结构的方式,着重与它做了什么,而忽略它是怎么做的。栈和队列就是典型的例子。
8.使用链表创建堆代码:
8.1.LinkX.java
1 package com.cn.linklist; 2 /** 3 * 用于创建堆的数据结构--》链表的节点对象生成类 4 * @author Administrator 5 * 6 */ 7 public class LinkX { 8 public long ddata; 9 public LinkX next; 10 public LinkX(long dd){ 11 ddata = dd; 12 } 13 public void displaylink(){ 14 System.out.print("{"+ddata+"}"); 15 } 16 }
8.2.LinkXList.java
1 package com.cn.linklist; 2 /** 3 * 用于创建堆的链表代码 4 * @author Administrator 5 * 6 */ 7 public class LinkXList { 8 private LinkX first; 9 public LinkXList(){ 10 first = null; 11 } 12 public boolean isEmpty(){ 13 return (first == null); 14 } 15 public void insertFirst(long dd){ 16 LinkX link = new LinkX(dd); 17 link.next = first; 18 first = link; 19 } 20 public long deleteFirst(){ 21 LinkX tmp = first; 22 first = first.next; 23 return tmp.ddata; 24 } 25 public void displaylist(){ 26 LinkX current = first; 27 while(current != null){ 28 current.displaylink(); 29 current =current.next; 30 } 31 System.out.println(""); 32 } 33 }
8.3.LinkXStack.java
1 package com.cn.linklist; 2 /** 3 * 利用链表实现的堆代码 4 * @author Administrator 5 * 6 */ 7 public class LinkXStack { 8 private LinkXList thelist; 9 public LinkXStack(){ 10 thelist = new LinkXList(); 11 } 12 public void push(long j){ 13 thelist.insertFirst(j); 14 } 15 public long pop(){ 16 return thelist.deleteFirst(); 17 } 18 public boolean isEmpty(){ 19 return (thelist.isEmpty()); 20 } 21 public void displaystack(){ 22 System.out.print("stack(top--->bottom):"); 23 thelist.displaylist(); 24 } 25 }
8.4.LXSTest.java
1 package com.cn.linklist; 2 /** 3 * 利用链表实现的堆测试代码 4 * @author Administrator 5 * 6 */ 7 public class LXLSTest { 8 public static void main(String[] args) { 9 LinkXStack stack = new LinkXStack(); 10 stack.push(100); 11 stack.push(200); 12 stack.push(300); 13 stack.push(400); 14 stack.push(500); 15 stack.push(600); 16 stack.displaystack(); 17 while (!stack.isEmpty()){ 18 System.out.print(stack.pop()); 19 System.out.print(" " ); 20 } 21 System.out.println(""); 22 System.out.println(stack.isEmpty()); 23 } 24 }
9.使用双端链表创建队列代码:
9.1.LinkT.java
1 package com.cn.linklist; 2 /** 3 * 双端链表节点 4 * @author Administrator 5 * 6 */ 7 public class LinkT { 8 public long ddata; 9 public LinkT next; 10 public LinkT(long dd){ 11 ddata = dd; 12 } 13 public void displaylink(){ 14 System.out.print("{"+ddata+"}"); 15 } 16 }
9.2.LinkTList.java
1 package com.cn.linklist; 2 /** 3 * 双端链表实现 4 * @author Administrator 5 * 6 */ 7 public class LinkTList { 8 private LinkT first; 9 private LinkT last; 10 public LinkTList(){ 11 first = null; 12 last = null; 13 } 14 public boolean isEmpty(){ 15 return (first == null); 16 } 17 public void insertFirst(long dd){ 18 LinkT l = new LinkT(dd); 19 if (isEmpty()) 20 last = l; 21 l.next = first; 22 first = l; 23 } 24 public void insertLast(long dd){ 25 LinkT l = new LinkT(dd); 26 if (isEmpty()) 27 first = l; 28 else 29 last.next = l; 30 last = l; 31 } 32 public long deleteFirst(){ 33 long temp = first.ddata; 34 if (first.next == null) 35 last = null; 36 first = first.next; 37 return temp; 38 } 39 public void displaylinktlist(){ 40 System.out.print("list(first--->last):"); 41 LinkT current = first; 42 while (current != null){ 43 current.displaylink(); 44 current = current.next; 45 } 46 System.out.println(""); 47 } 48 49 }
9.3.LinkTQueue.java
1 package com.cn.linklist; 2 /** 3 * 使用链表实现的队列代码 4 * @author Administrator 5 * 6 */ 7 public class LinkTQueue { 8 private LinkTList thelist; 9 public LinkTQueue(){ 10 thelist = new LinkTList(); 11 } 12 public boolean isEmpty(){ 13 return (thelist.isEmpty()); 14 } 15 public void insert(long j){ 16 thelist.insertLast(j); 17 } 18 public long remove(){ 19 return thelist.deleteFirst(); 20 } 21 public void displayqueue(){ 22 System.out.print("queue(front--->rear):"); 23 thelist.displaylinktlist(); 24 } 25 }
9.4.LTQTest.java
1 package com.cn.linklist; 2 3 public class LTQTest { 4 public static void main(String[] args) { 5 LinkTQueue queue = new LinkTQueue(); 6 queue.insert(10); 7 queue.insert(20); 8 queue.insert(30); 9 queue.insert(40); 10 queue.displayqueue(); 11 while(!queue.isEmpty()){ 12 System.out.print(queue.remove()); 13 System.out.print(" "); 14 } 15 System.out.println(""); 16 System.out.println(queue.isEmpty()); 17 18 } 19 }
10.有序链表:在有序链表中数据是按照关键值有序排列的,有序链表的删除常常只限于删除链表头部的最小(或最大)链节点。有序链表优与有序数组的地方是插入,因为它不需要移动数据项,且有序链表可以可扩展,而有序数组只能局限于一个固定的大小中,有序链表可以用于为数字排序,实现优先级队列。
11.有序链表代码:
11.1.LinkS.java
1 package com.cn.sortedlist; 2 /** 3 * 有序链表节点 4 * @author Administrator 5 * 6 */ 7 public class LinkS { 8 public long ddata; 9 public LinkS next; 10 public LinkS(long dd){ 11 ddata = dd; 12 } 13 public void displaylink(){ 14 System.out.print("{"+ddata+"}"); 15 } 16 }
11.2.SortedList.java
1 package com.cn.sortedlist; 2 /** 3 * 有序链表实现类 4 * @author Administrator 5 * 6 */ 7 public class SortedList { 8 private LinkS first; 9 public SortedList(){ 10 first = null; 11 } 12 public boolean isEmpty(){ 13 return (first == null); 14 } 15 public void insert(long j){ 16 LinkS link = new LinkS(j); 17 LinkS previous = null; 18 LinkS current = first; 19 while (current != null && j > current.ddata){ 20 previous = current; 21 current = current.next; 22 } 23 if (previous == null) 24 first = link; 25 else 26 previous.next = link; 27 link.next = current; 28 } 29 public long remove(){ 30 LinkS temp = first; 31 first = first.next; 32 return temp.ddata; 33 } 34 public void displaylist(){ 35 LinkS current = first; 36 System.out.print("list(first--->last):"); 37 while (current != null){ 38 current.displaylink(); 39 current = current.next; 40 } 41 System.out.println(""); 42 } 43 44 }
11.3SLTest.java
1 package com.cn.sortedlist; 2 /** 3 * 有序链表的测试类 4 * @author Administrator 5 * 6 */ 7 public class SLTest { 8 public static void main(String[] args) { 9 SortedList list = new SortedList(); 10 list.insert(10); 11 list.insert(20); 12 list.insert(30); 13 list.insert(80); 14 list.insert(50); 15 list.insert(60); 16 list.displaylist(); 17 while (! list.isEmpty()){ 18 System.out.print(list.remove()); 19 System.out.print(" "); 20 } 21 System.out.println(""); 22 System.out.println(list.isEmpty()); 23 } 24 }
12.有序链表的效率:有序链表插入,删除一个数据项最多需O(N)次比较,然而可以在O(1)的时间内找到或删除最小项,因为他总是在表头位置。
13.双向链表:即允许向前,也允许向后遍历整个链表。该链表的特点是:既有指向前一个节点的链表引用,又有指向后一个节点的引用。它的缺点是每次删除或插入一个链节点的时候,要处理四个链节点的引用。
14.双向链表代码:
14.1.LinkD.java
1 package com.cn.linklist; 2 /** 3 * 双向链表节点 4 * @author Administrator 5 * 6 */ 7 public class LinkD { 8 public long ddata; 9 public LinkD next; 10 public LinkD previous; 11 public LinkD(long dd){ 12 ddata = dd; 13 } 14 public void displaylink(){ 15 System.out.print("{"+ddata+"}"); 16 } 17 }
14.2.LinkDList.java
1 package com.cn.linklist; 2 /** 3 * 双向链表实现类 4 * @author Administrator 5 * 6 */ 7 public class LinkDList { 8 private LinkD first; 9 private LinkD last; 10 public LinkDList(){ 11 first = last = null; 12 } 13 public boolean isEmpty(){ 14 return (first == null); 15 } 16 public void insertFirst(long dd){ 17 LinkD link = new LinkD(dd); 18 if (isEmpty()) 19 last = link; 20 else 21 first.previous = link; 22 link.next = first; 23 first = link; 24 } 25 public void insertLast(long dd){ 26 LinkD link = new LinkD(dd); 27 if (isEmpty()) 28 first = link; 29 else{ 30 last.next = link; 31 link.previous = last; 32 } 33 last = link; 34 } 35 public LinkD deleteFirst(){ 36 LinkD temp = first; 37 if (first.next == null) 38 last = null; 39 else 40 first.next.previous = null; 41 first = first.next; 42 return temp; 43 } 44 public LinkD deleteLast(){ 45 LinkD temp = last; 46 if (first.next == null) 47 last = null; 48 else 49 last.previous.next= null; 50 last = last.previous; 51 return temp; 52 } 53 public boolean insertAfter(long key,long dd){ 54 LinkD current = first; 55 while (current.ddata != key){ 56 current = current.next; 57 if (current.next == null) 58 return false; 59 } 60 LinkD link = new LinkD(dd); 61 if (current == last){ 62 link.next = null; 63 last = link; 64 }else{ 65 link.next = current.next; 66 current.next.previous = link; 67 } 68 link.previous = current; 69 current.next = link; 70 return true; 71 } 72 public LinkD deletekey(long key){ 73 LinkD current = first; 74 while (current.ddata != key){ 75 current = current.next; 76 if (current.next == null) 77 return null; 78 } 79 if (current == first) 80 first = current.next; 81 else 82 current.previous.next = current.next; 83 if (current == last) 84 last = current.previous; 85 else 86 current.next.previous = current.previous; 87 return current; 88 } 89 public void displayBackward(){ 90 System.out.print("list(last--->first):"); 91 LinkD current = last; 92 while (current != null){ 93 current.displaylink(); 94 current = current.previous; 95 } 96 System.out.println(""); 97 } 98 public void displayForward(){ 99 System.out.print("list(first--->last):"); 100 LinkD current = first; 101 while (current != null){ 102 current.displaylink(); 103 current = current.next; 104 } 105 System.out.println(""); 106 } 107 108 }
14.3LDLTest.java
1 package com.cn.linklist; 2 /** 3 * 双向链表测试类 4 * @author Administrator 5 * 6 */ 7 public class LDLTest { 8 public static void main(String[] args) { 9 LinkDList list = new LinkDList(); 10 list.insertFirst(10); 11 list.insertLast(20); 12 list.insertAfter(10, 50); 13 list.displayForward(); 14 list.displayBackward(); 15 list.deletekey(50); 16 list.displayBackward(); 17 } 18 }
15.迭代器ListIterator.java
1 package com.cn.linklist; 2 /** 3 * 迭代器 4 * @author Administrator 5 * 6 */ 7 public class ListIterator { 8 private Link current; 9 private Link previous; 10 private LinkList ourlist; 11 public ListIterator(LinkList list){ 12 ourlist = list; 13 reset(); 14 } 15 public void reset(){ 16 current = ourlist.getFirst(); 17 previous = null; 18 } 19 public boolean atEnd(){ 20 return (current.next == null); 21 } 22 public Link getcurrent(){ 23 return current; 24 } 25 public void nextLink(){ 26 previous = current; 27 current = current.next; 28 } 29 public void insertAfter(int id,long dd){ 30 Link link = new Link(id, dd); 31 if (ourlist.isEmpty()){ 32 ourlist.setFirst(link); 33 current = link; 34 }else{ 35 link.next = current.next; 36 current.next = link; 37 nextLink(); 38 } 39 } 40 public void insertBefore(int id,long dd){ 41 Link link = new Link(id, dd); 42 if (previous == null){ 43 link.next = previous.next; 44 ourlist.setFirst(link); 45 reset(); 46 }else{ 47 link.next = previous.next; 48 previous.next = link; 49 current = link; 50 } 51 } 52 public double deleteCurrent(){ 53 double value = current.ddata; 54 if (previous == null){ 55 ourlist.setFirst(current.next); 56 reset(); 57 } 58 else{ 59 previous.next = current.next; 60 if (atEnd()) 61 reset(); 62 else 63 current = current.next; 64 } 65 return value; 66 } 67 }