雙鏈表—Java迭代器和泛型的拓展
雙鏈表作為基礎的資料結構和單鏈表的唯一區別就是有前驅和後繼兩個指標,使用JavaAPI定義好的Iterator介面可以簡易實現迭代器功能,泛型是java語言一個特殊的地方,可以理解指代型別的形參,代指任意型別,具體使用方法可以參考如下java程式碼
import java.util.Iterator;
/**
* 定義列表的介面,所有列表該實現的約定
* 增刪改查
* @author Administrator
*
*/
public interface MyList<T> extends Iterator<T>{//<T> 代指任意型別,即泛型的使用
/**
* 增加一個元素
* @param element
*/
void add(T element);
/**
* 根據值,刪除一個元素
* @param element
*/
void delete(T element);
/**
* 根據下標刪除一個元素
* @param index
*/
void delete(int index);
/**
* 根據下標更新一個元素
* @param index
* @param element
*/
void update(int index, T element);
/**
* 判斷線性表中是否包含該元素
* 返回布林型
* @param element
* @return
*/
boolean contains(T element);
/**
* 返回線性表中與該元素相等的值的下標
* 如果沒有返回-1
* @param element
* @return
*/
int index(T element);
}
public class _03DoubleLinkedList<T> implements MyList<T>{
ListNode head = new ListNode(null);
/**
* 頭結點_亞元
*/
ListNode tail = new ListNode(null);
/**
* 尾節點_亞元
*/
int size;
/**
* 節點數目
*/
public _03DoubleLinkedList() {
head.next = tail;
tail.pre = head;
}
@Override
public void add(T element) {
//尾部插入新節點的正確姿勢四部
ListNode newNode = new ListNode(element);
tail.pre.next = newNode;//斷開由前一個節點指向尾部的指標,指向新插入的節點
newNode.next = tail;//連線新節點指向尾節點
newNode.pre = tail.pre;//尾節點原來的前驅為新節點的前驅
tail.pre = newNode;//更新尾節點的前驅為新插入的節點
size++;
}
@Override
public void delete(T element) {
ListNode p = head.next;
while(p != tail) {
if(p.data.equals(element)) {
p.pre.next = p.next;//當前要刪除節點的前一個節點的後繼指向該節點的下一個節點
p.next.pre = p.pre;//當前節點的前驅指向當前要刪除節點的後一個節點的前驅
size--;
break;
}
p = p.next;
}
}
@Override
public void delete(int index) {
if(index < 0 ||index >= size)
return;
int i = 0;
ListNode p = head.next;
while(p != tail) {
if(i == index) {
p.pre.next = p.next;
p.next.pre = p.pre;
size--;
break;
}
p = p.next;
i++;
}
}
@Override
public void update(int index, T element) {
if(index < 0||index >= size)
return;
int i = 0;
ListNode p = head.next;
while(p != tail) {
if(i == index) {
p.data = element;
break;
}
p = p.next;
}
}
@Override
public boolean contains(T element) {
ListNode p = head.next;
while(p != tail) {
if(p.data.equals(element))
return true;
p = p.next;
}
return false;
}
@Override
public int index(T element) {
int i = 0;
ListNode p = head.next;
while(p != tail) {
if(p.data.equals(element))
return i;
p = p.next;
i++;
}
return -1;
}
@Override
public String toString() {//頭指標和尾指標都為亞元不需要輸出
StringBuilder sb = new StringBuilder("[");
ListNode p = head.next;
while(p != tail) {
if(p.next != tail) {
sb.append(p.data + " , ");
}else
sb.append(p.data + "]");
p = p.next;
}
return sb.toString();
}
private ListNode now = head;
@Override
public boolean hasNext() {//判斷是否還有下一個值
return now.next != tail;
}
@SuppressWarnings("unchecked")
@Override
public T next() {//每次取下一個值
ListNode next = now.next;
now = now.next;
return (T) next.data;
}
}
測試程式碼截圖:
