本文將數據結構知識中重要知識點:數據元素,結點,數據類型,抽象數據類型,抽象數據類型的實現、以及對新定義的數據結構的應用等知識通過下述java代碼的形式串聯起來,以從宏觀上對數據結構有一個透徹的理解和認識。
我們要使用單鏈表這個數據結構來解決問題的前提是首先得創建一個單鏈表數據結構。創建單鏈表數據結構,就得自定義個單鏈表的抽象數據類型,抽象數據類型只是對數據結構定義一組邏輯操作,沒有具體的實現。在實際應用中,必須實現這個抽象數據類型,才能使用它們,而實現抽象數據類型依賴於數據存儲結構。
單鏈表
線性表的鏈式存儲是用若干地址分散的存儲單元存儲數據元素,邏輯上相鄰的數據元素在物理位置上不一定相鄰,必須採用附加信息表示數據元素之間的順序關係。因此,存儲一個數據元素的存儲單元至少包含兩部分——數據域和地址域,結構如下:
其中data存儲數據元素值,稱爲數據域;next存儲後繼元素的地址,稱爲地址域或鏈(link),上述結構通常稱爲結點(node)。一個結點表示一個數據元素。
根據上一博客日記中的ListInterface接口,實現單鏈表類LList,節點類Node在LList類中,代碼如下:
public class LList<T> implements ListInterface<T> {
private Node firstNode;
private int length;
public LList(){
clear();
}
public final void clear(){
firstNode = null;
length = 0;
}
public boolean add(T newEntry){
Node newNode = new Node(newEntry);
if(isEmpty())
firstNode = newNode;
else{//插入到非空線性表的末尾
Node lastNode = getNodeAt(length);
lastNode.next = newNode;//使最後一個結點的引用指向新結點
}
length++;
return true;
}
public boolean add(int newPosition,T newEntry){
boolean isSuccessful = true;
if((newPosition >=1)&&(newPosition <= length + 1)){
Node newNode = new Node(newEntry);
if(isEmpty()||(newPosition ==1)){//線性表爲空
newNode.next = firstNode;
firstNode = newNode;
}else {//線性表不爲空 newPosition>1
Node nodeBefore = getNodeAt(newPosition - 1);
Node nodeAfter = nodeBefore.next;
newNode.next = nodeAfter;
nodeBefore.next = newNode;
}
length++;
}else {
isSuccessful = false;
}
return isSuccessful;
}
public int getLength(){
return length;
}
private Node getNodeAt(int givenPosition){
Node currentNode = firstNode;
if((currentNode.next != null)||!isEmpty()){
for (int counter = 1;counter < givenPosition;counter++){
currentNode = currentNode.next;
}
}
return currentNode;
}
public boolean replace(int givenPosition,T newEntry){
boolean isSuccessful = true;
if(!isEmpty()&&(givenPosition >= 1)&&(givenPosition <= length)){
Node desiredNode = getNodeAt(givenPosition);
desiredNode.data = newEntry;
}else
isSuccessful = false;
return isSuccessful;
}
public T getEntry(int givenPosition){
T result = null;
if(!isEmpty()&&(givenPosition >= 1)&&(givenPosition <= length)){
result = getNodeAt(givenPosition).data;
}
return result;
}
public Object remove(int givenPosition){
Object result = null;
if(!isEmpty()&&(givenPosition >= 1)&&(givenPosition <= length)){
if(givenPosition == 1){
//刪除第一個元素
result = firstNode.data;
firstNode = firstNode.next;
}else {
//givenPosition > 1刪除中間或末尾的元素
Node nodeBefore = getNodeAt(givenPosition -1);
Node nodeToRemove = nodeBefore.next;
Node nodeAfter = nodeToRemove.next;
nodeBefore.next = nodeAfter;
result = nodeToRemove.data;
}
length--;
}
return result;
}
public void display(){
Node currentNode = firstNode;
while(currentNode != null){
System.out.println(currentNode.data);
currentNode = currentNode.next;
}
}
public boolean contains(T anEntry){
boolean found = false;
Node currentNode = firstNode;
while(!found && (currentNode != null)){
if(anEntry.equals(currentNode.data)){
found = true;
}else
currentNode = currentNode.next;
}
return found;
}
public boolean isFull(){return false;}
public boolean isEmpty(){return length == 0;} //判斷線性表是否爲空。
private class Node {
private T data;
private Node next;
private Node(T dataPortion){
data = dataPortion;
next = null;
}
private Node(T dataPortion,Node nextNode){
data = dataPortion;
next = nextNode;
}
}
}
鏈表實現線性表的優缺點:
1.可根據需要延長線性表;
2.在插入與刪除結點時不需要移動線性表中已存在的任何一個元素。但是,在使用鏈表時,必須從鏈表的始端起遍歷鏈表,以確定應該在何處插入或刪除
3.從鏈表中檢索一個已有的元素,需要類似的遍歷以查找想得到的元素。
4.鏈表比數組需要更多的內存。