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