.線性表鏈式存儲結構:將采用一組地址的任意的存儲單元存放線性表中的數據元素。
鏈表又可分為:
-
單鏈表:每個節點只保留一個引用,該引用指向當前節點的下一個節點,沒有引用指向頭結點,尾節點的next引用為null。
-
循環鏈表:一種首尾相連的鏈表。
-
雙向鏈表:每個節點有兩個引用,一個指向當前節點的上一個節點,另外一個指向當前節點的下一個節點。
下面給出線性表雙向鏈表的實現:java中LinkedList是線性表的鏈式實現,是一個雙向鏈表。
import java.util.NoSuchElementException;
//線性表雙向鏈表存儲結構
public class DuLinkList<T> {
//定義一個內部類Node,Node實例代表鏈表的節點
private class Node{
//保存節點的數據
private T data;
//指向上一個節點的引用
private Node prev;
//指向下一個節點的引用
private Node next;
//無參數的構造器
public Node(){
}
//初始化全部屬性的構造器
public Node(T data, Node prev, Node next){
this.data = data;
this.prev = prev;
this.next = next;
}
}
//保存該鏈表的頭結點
private Node header;
//保存該鏈表的尾節點
private Node tail;
//保存該鏈表中已包含的節點數
private int size;
//創建空鏈表
public DuLinkList(){
//空鏈表,header與tail都是null
header = null;
tail = null;
}
//以指定數據元素來創建鏈表,該鏈表只有一個元素
public DuLinkList(T element){
header = new Node(element, null, null);
tail = header;
size++;
}
//判斷鏈式線性表是否為空鏈表
public boolean empty(){
return size == 0;
}
//清空線性表
public void clear(){
for(Node current = header; current != null;){
Node next = header.next;
current.data = null;
current.prev = null;
current.next = null;
current = next;
}
header = null;
tail = null;
size = 0;
}
//獲取鏈式線性表中索引為index處的元素
public T get(int index){
return getNodeByIndex(index).data;
}
//根據索引index獲取指定位置的節點
private Node getNodeByIndex(int index){
if(index < 0 || index > size -1){
throw new IndexOutOfBoundsException("線性表索引越界");
}
if(index < (size >> 1)){
//從header節點開始遍歷
Node current = header;
for(int i=0; i < index; i++){
current = current.next;
}
return current;
}else{
Node current = tail;
for(int i = size - 1; i > index; i--){
current = current.prev;
}
return current;
}
}
//查找鏈式線性表中指定元素的索引
public int locate(T element){
Node current = header;
for(int i=0;i<size && current != null;i++, current = current.next){
if(current.data.equals(element)){
return i;
}
}
return -1;
}
//返回鏈表的長度
public int length(){
return size;
}
//向線性鏈表的表頭插入一個元素
public void addFirst(T element){
linkFirst(element);
}
//在線性鏈表表頭插入一個元素
public void linkFirst(T element){
Node f = header;
Node newNode = new Node(element,null,f);
header = newNode;
if(f == null){
tail = newNode;
}else{
f.prev = newNode;
}
size++;
}
//向線性鏈表的表尾插入一個元素
public void addTail(T element){
linkTail(element);
}
//在線性鏈表的表尾插入一個元素
public void linkTail(T element){
Node t = tail;
Node newNode = new Node(element, t, null);
tail = newNode;
if(t == null){
header = newNode;
}else{
t.next = newNode;
}
size++;
}
//在線性表中某個元素前面插入一個節點
public void linkBefore(T element, Node node){
Node pre = node.prev;
Node newNode = new Node(element, pre, node);
node.prev = newNode;
if(pre == null){
header = newNode;
}else{
pre.next = newNode;
}
size++;
}
//向線性鏈表中的指定位置插入一個元素
public void insert(T element, int index){
if(index < 0 || index > size){
throw new IndexOutOfBoundsException("線性表索引越界");
}
if(index == size){
addTail(element);
}else{
linkBefore(element,getNodeByIndex(index));
}
}
//移走線性鏈表的頭結點
public void removeFirst(){
Node first = header;
if(first == null)
throw new NoSuchElementException("此節點不存在");
unlinkFirst(first);
}
//刪除頭結點
public void unlinkFirst(Node node){
Node next = node.next;
node.data = null;
node.next = null;
header = next;
if(next == null){
tail = null;
}else{
next.prev = null;
}
size--;
}
//移走線性鏈表的尾節點
public void removeTail(){
Node last = tail;
if(last == null)
throw new NoSuchElementException("此節點不存在");
unlinkLast(last);
}
//刪除尾節點
public void unlinkLast(Node node){
Node pre = node.prev;
node.data = null;
node.prev = null;
tail = pre;
if(pre == null){
header = null;
}else{
pre.next = null;
}
size--;
}
//移走線性表中的任意一個節點
public void remove(int index){
if(index < 0 || index >size - 1){
throw new IndexOutOfBoundsException("線性表越界");
}
unlink(getNodeByIndex(index));
}
//刪除線性表中任意一個元素
public void unlink(Node node){
Node pre = node.prev;
Node next = node.next;
node.data = null;
if(pre == null){
header = next;
}else{
pre.next = next;
node.prev = null;
}
if(next == null){
tail = pre;
}else{
next.prev = pre;
node.next = null;
}
size--;
}
}