鏈式存儲結構存儲線性表的方法是把存放數據元素的結點用指針域構造成鏈。指針是指向下一個節點的引用,由數據元素域和一個或若干個指針域組成的一個類稱之為結點。鏈式存儲結構的特點是數據元素間的邏輯關系表現在節點的鏈接關系上。
本例中實現的鏈表結構都是帶頭結點的。具體代碼如下:【詳見:SingleLinkedList.java】
package datastructure.linear.linked;
import datastructure.exception.StructureException;
import datastructure.linear.AbstractList;
/**
* @Description 單鏈表
* @author mastery
* @Date 2015年6月30日下午6:11:17
* @param <T>
*/
public class SingleLinkedList<T> extends AbstractList<T> {
class Node<T1> {
T1 element;
Node<T1> next;
public Node(Node<T1> next) {
super();
this.next = next;
}
public Node(T1 element, Node<T1> next) {
super();
this.element = element;
this.next = next;
}
@Override
public String toString() {
return element.toString();
}
}
/**
* 頭結點,該結點沒有參數值,只是指向第一個元素的結點
*/
private Node<T> head;
/**
* 當前的結點
*/
private Node<T> currentNode;
public SingleLinkedList() {
head = currentNode = new Node<T>(null);
size = 0;
}
/**
* 得到當前下標對應的結點
* @param index
* @throws StructureException
*/
public void indexNodeToCurrent(int index) throws StructureException {
currentNode = head;
if(index < -1 || index > size -1) {
throw new StructureException("index參數異常!");
}
if(index == -1) {
return ;
}
currentNode = head.next;
int j = 0 ;
while(currentNode != null && j < index) {
currentNode = currentNode.next;
j++;
}
}
@Override
public void insert(int index, T t) throws StructureException {
if(index < 0 || index > size) {
throw new StructureException("index參數異常!");
}
// 得到當前下標的上一個結點
indexNodeToCurrent(index-1);
// 將新元素生成結點插入到當前結點下
currentNode.next = new Node<T>(t , currentNode.next);
size++;
}
@Override
public void delete(int index) throws StructureException {
if(isEmpty()) {
throw new StructureException("鏈表為空");
}
if(index < 0 || index > size) {
throw new StructureException("index參數異常");
}
indexNodeToCurrent(index-1);
Node<T> twoNextNode = currentNode.next.next;
currentNode.next = twoNextNode;
size--;
}
@Override
public T get(int index) throws StructureException {
if(isEmpty()) {
throw new StructureException("鏈表為空");
}
if(index < 0 || index > size) {
throw new StructureException("index參數異常!");
}
indexNodeToCurrent(index);
return currentNode.element;
}
}
單鏈表的插入和刪除操作的時間效率分析方法和順序表的插入和刪除操作的時間效率分析方法類同,差別是單鏈表的插入和刪除操作不需移動數據元素,只需比較數據元素。
要說明的是,雖然單鏈表插入和刪除操作的時間復雜度與順序表插入和刪除操作的時間復雜度相同,但是,順序表插入和刪除操作的時間復雜度指的是移動數據元素的時間復雜度,當數據元素占據的內存空間比較大時,這要比單鏈表插入和刪除操作比較數據元素花費的時間大一個常數倍。另外,單鏈表求數據元素個數操作的時間復雜度為O(n).
與順序表相比,單鏈表的主要有點是不需要預先確定數據元素的最大個數,插入和刪除時不需要移動元素;主要缺點三每個結點中要有一個指針域,因此,空間單元利用效率不高。此外,單鏈表操作的算法比較復雜。
測試類如下:
package datastructure.linear.linked;
import static org.junit.Assert.*;
import org.junit.Test;
import datastructure.exception.StructureException;
import datastructure.linear.List;
import datastructure.linear.linked.SingleLinkedList;
public class SingleLinkedListTest {
@Test
public void testSingleLinkedList() throws StructureException {
List<Integer> list = new SingleLinkedList<Integer>();
for(int i = 0 ; i < 10 ; i ++) {
list.insert(i, i+1);
}
list.delete(0);
for(int i = 0 ; i < list.size() ; i++) {
System.out.print(list.get(i) + " ");
}
}
@Test
public void testIndexNodeToCurrent() {
fail("尚未實現");
}
@Test
public void testInsert() {
fail("尚未實現");
}
@Test
public void testDelete() {
fail("尚未實現");
}
@Test
public void testGet() {
fail("尚未實現");
}
}