Lava連結串列(雙向連結串列---介面實現)
阿新 • • 發佈:2018-12-19
在Java中連標配的結點需要用類來封裝,下面的簡單的雙向連結串列實現:
class Node { private Object data; private Node next; public Node(Object data) { this.data = data; } public Object getData() { return data; } public Node getNext() { return next; } public void setData(Object data) { this.data = data; } public void setNext(Node next) { this.next = next; } } public class Link { public static void main(String[] args) { Node head=new Node("世界"); Node first1=new Node("pick"); Node first2=new Node(1019); Node tail=new Node("happy"); head.setNext(first1); //在主類中進行連結串列的連結和插入 first1.setNext(first2); first2.setNext(tail); print(head); } public static void print(Node node) { if(node==null) return ; System.out.println(node.getData()); node=node.getNext(); print(node); } }
以上程式碼是在客戶端中進行連結串列的連結,而客戶端中並不用看到具體的連結過程,只需要插入資料或者其他具體操作,所以需要用一個類來進行Node類資料的儲存和連結串列之間的連結;但是客戶端只需要進行插入資料等,並不關心是通過何種資料結構實現,但是對於客戶端需求有很多資料結構實現,為了操作標準化,定義一個介面。程式碼如下:
package CODE; import javafx.beans.binding.ObjectBinding; import jdk.nashorn.internal.ir.UnaryNode; import org.omg.CORBA.OBJ_ADAPTER; import javax.management.ObjectName; ////雙向連結串列 interface Ilink { boolean add(Object data); //新增 boolean remove(Object data); //刪除資料為data的結點 void printLink(); //遍歷該連結串列 int size(); //結點個數 Object set(int index ,Object newdata);// 把索引index所在位置元素替換為newdata,返回原來資料 int contains(Object data);//判斷data是否在連結串列中 Object get(int index);//根據下標返回結點內容 void clear();//銷燬 Object[] toArray();//將連結串列轉為陣列 } class LinkImpl implements Ilink { private Node head;//頭結點 private Node tail; //尾結點 private int size; //結點個數 private class Node //定義為內部類是一種封裝 //將每個結點定義為私有內部類,目的內部類和外部類可以訪問彼此的私有屬性,而且客戶端不知道每個結點具體情況, { Node prev; private Object data; Node next; public Node(Node prev, Object data,Node next) //結點的構造方法 { this.prev=prev; this.data=data; this.next=next; } } public boolean add(Object data) { //利用尾插 Node prev=this.tail; Node newnode=new Node(this.tail,data,null); if(this.head==null) //第一次插入時頭為為空,將頭尾都指向newnode this.head=newnode; else { prev.next=newnode; } this.tail=newnode; this.size++; return true; } public boolean remove(Object data) { if(data==null) //很有可能這個節點資料為null,但是對於資料不是null的節點,比較用的是equals,所以需要分開判斷 { for (Node tmp = head; tmp != null; tmp = tmp.next) { if(tmp.data==null) //找到該節點 { if(Unlink(tmp)) //刪除該節點 return true; } } return false; } else { for (Node tmp = head; tmp != null; tmp = tmp.next) { if (data.equals(tmp.data)) { if (Unlink(tmp)) return true; } } return false; } } public Object set(int index, Object newdata) //替換資料 { if(isIndex(index)) //首先下標是合法的 { Node tmp=getNode(index); Object olddata=tmp.data; tmp.data=newdata; return olddata; } return null; } public int contains(Object data) { if(data==null) { int i=0; for(Node tmp=head;tmp!=null;tmp=tmp.next) { if (tmp.data == null) return i; else i++; } } else { int i=0; for(Node tmp=head;tmp!=null;tmp=tmp.next) { if(data.equals(tmp.data)) return i; else i++; } } return -1; } private boolean Unlink(Node node)//刪除node結點 { //既然要刪除一個結點,是將prev和next連結在一起,那麼對prev 是否為空進行操作,next是否為空進行操作 Node prev=node.prev; Node next=node.next; if(prev==null) { this.head=next; //head.prev=null; //不能有該語句,如果next為空 } else { prev.next=next; node.prev=null; //相當於清除該節點的prev } if(next==null) //刪除尾結點 如果刪除的僅有結點,即既是頭結點也是為節點,會走這一句 { this.tail=prev; } else { next.prev=prev; node.next=null; //相當於清除該節點的next } node.data=null; //將該節點資料置空 this.size--; return true; } public Object get(int index) //返回索引為index的資料 { if(isIndex(index)) { Node tmp=getNode(index); return tmp.data; } System.out.println("下標不合法"); return null; } public void printLink() //遍歷連結串列 { for(Node tmp=head;tmp!=null;tmp=tmp.next) { System.out.println(tmp.data); } } public void clear() //銷燬連結串列 { for(Node tmp=head;tmp!=null;) { Node next=tmp.next; tmp.next=null; tmp.prev=null; tmp.data=null; tmp=null; tmp=next; size--; } head=tail=null; } public int size() { return size; } public Object[] toArray() //將連結串列轉為陣列 { if(size!=0) { Object[] linkArray=new Object[this.size]; int index=0; for(Node tmp=head;tmp!=null;tmp=tmp.next) { linkArray[index]=tmp.data; index++; } return linkArray; } return null; } private boolean isIndex(int index) //判斷下標是否合法 { return index>=0 && index<size; } private Node getNode(int index) //返回下標所在的結點 { if(index<size/2) //元素的一半,從head向尾找 { Node start=head; for(int i=0;i<index;i++) { start=start.next; } return start; } else { Node end=tail; for(int i=size-1;i>index;i--) { end=end.prev; } return end; } } } class factory //一個工廠專門生產物件,這樣在客戶端就不用new物件 { public static LinkImpl getLink() { return new LinkImpl(); } } public class DoubleLink { public static void main(String[] args) { Ilink l=factory.getLink(); l.add("pick"); l.add("hello"); l.add(null); System.out.println(l.set(2,19)); l.printLink(); System.out.println("*************"+l.size()); l.remove("pick"); l.remove(null); l.printLink(); System.out.println(l.get(1)); System.out.println("*************"); l.clear(); l.printLink(); System.out.println(l.size()); } }