- 循環鏈表的介紹
在單向鏈表和雙向鏈表中,都採用null作爲鏈表的結束,然而,循環鏈表沒有結束標誌。
注意 與單向鏈表不同,循環鏈表沒有next指針爲null的點,循環鏈表在某些情況下非常有用。 比如在進程的循環調度中。 - 循環鏈表的創建
public class Node<E> {
// 節點對象 對象應該包含儲蓄的數據和指向下一個節點對象
// 利用泛型 將儲存的數據類型交給使用者來選擇,大大提升靈活性
// 儲存的數據
private E data;
// 下一個節點
private Node<E> next;
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> next) {
this.next = next;
}
}
3.循環鏈表的插入
// 在鏈表表尾增加鏈表節點
public void add(E obj) {
Node<E> node = new Node<>();
node.setData(obj);
// 如果鏈表爲空 則首尾節點都指向第一個節點
if (headNode == null) {
headNode = node;
endNode = node;
//循環鏈表的尾節點指向頭結點
endNode.setNext(headNode);
} else {
// 不爲空 將尾節點指向新增節點
endNode.setNext(node);
//新增節點指向頭節點
node.setNext(headNode);
// 尾節點後移
endNode = node;
}
}
// 在指定中間位置增加節點
public void add(int index, E element) {
Node<E> node = new Node<>();
node.setData(element);
if (headNode == null) {
throw new NullPointerException("空鏈表");
}
// 判斷位置是否超出界限
else if ((index < 0) || (index > this.size())) {
throw new ArrayIndexOutOfBoundsException("超出範圍");
} else {
// 首節點插入
if (index == 0) {
node.setNext(headNode);
endNode.setNext(node);
headNode = node;
}
// 尾節點插入
else if (index == this.size()) {
endNode.setNext(node);
node.setNext(headNode);
endNode = node;
}
// 中間插入
else {
Node<E> hnode = headNode;
// 將首節點移動到插入節點的前一個節點
for (int i = 1; i <= index - 1; i++) {
hnode = hnode.getNext();
}
node.setNext(hnode.getNext());
hnode.setNext(node);
}
}
}
4.循環鏈表的刪除
// 移除此列表中指定位置上的元素
public void remove(int index) {
if (headNode == null) {
throw new NullPointerException("空鏈表");
} else if ((index < 0) || (index >= this.size())) {
throw new ArrayIndexOutOfBoundsException("超出範圍");
} else {
// 保護頭結點
Node<E> hnode = headNode;
// 刪除首節點
if (index == 0) {
//更新首節點
headNode = headNode.getNext();
//更新尾節點
endNode.setNext(headNode);
// System.out.println(index + "號:" + hnode.getData().toString()
// + "移除成功");
}
// 刪除尾節點
else if (index == (this.size() - 1)) {
while (hnode.getNext() != endNode) {
hnode = hnode.getNext();
}
hnode.setNext(headNode);
// System.out.println(index + "號:" + endNode.getData() + "
// 移除成功");
endNode = hnode;
}
// 刪除中間節點
else {
for (int i = 1; i < index; i++) {
hnode = hnode.getNext();
}
// E data = hnode.getNext().getData();
hnode.setNext(hnode.getNext().getNext());
// System.out.println(index + "號:" + data.toString() + " 移除成功");
}
}
}
5.循環鏈表的其他操作
// 返回此列表中指定位置上的元素。
public E get(int index) {
if (headNode == null) {
throw new NullPointerException("空鏈表");
} else {
// 遍歷不到尾節點
for (Node<E> node = headNode; node.getNext() != headNode; node = node.getNext()) {
if (index == 0) {
return node.getData();
}
index--;
}
// 尾節點單獨檢測 爲什麼是0因爲index多運行了一次
if (index == 0) {
return endNode.getData();
} else
throw new ArrayIndexOutOfBoundsException("超出範圍");
}
}
// 返回此列表的元素數。
public int size() {
//判斷是否爲空
if (headNode == null) {
return 0;
} else {
Node<E> node = headNode;
int count = 0;
//循環鏈表沒有節點next爲空
while (node.getNext() != headNode) {
node = node.getNext();
count++;
}
return count + 1;
}
}
// 用指定的元素替代此列表中指定位置上的元素。
public E set(int index, E element) {
// 刪除指定位置的元素
this.remove(index);
// 插入指定位置元素
this.add(index, element);
return element;
}
循環鏈表的基本操作就此結束