一、簡介
1.1 概念
對於單鏈表而言,最後一個結點的地址爲空,如果表示最後一個結點的指針域指向頭結點,整個鏈表形成一個環,就構成了單循環鏈表。
與單鏈表相比,只是將原來判斷指針是否爲空變爲判斷是否是頭指針,沒有其他的變化。
訪問單循環鏈表某一結點,可以從任何一個結點開始,順序向後遍歷到達要訪問的結點。
1.2 優點
插入、刪除時,只要找到對應前驅結點,修改指針即可,無需移動元素;
採用動態存儲分配,不會造成內存浪費和溢出。
1.3 缺點
在有些高級語言中, 不支持指針,不容易實現;
需要用額外空間存儲線性表的關係,存儲密度小;
不能隨機訪問,查找時要從頭指針開始遍歷,查找元素的時間複雜度較大。
1.4 結構圖
二、簡單實現
public class CirLinkedList<E> {
Node front; // 循環鏈表表頭指針
Node rear; // 循環鏈表表尾指針
int length; // 表長度
private class Node {
public E e;
public Node next;
public Node() {
e = null;
next = null;
}
}
public CirLinkedList(){
this.rear = this.front = null;
this.length = 0;
}
/**
* 插入元素
* @param e 需要插入的元素
*/
public void insert(E e) {
Node node = new Node();
node.e = e;
if (this.length == 0) {
front = rear = node;
}else {
rear.next = node;
rear = node;
}
rear.next = front;
this.length = length + 1;
}
/**
* 查詢
* 1、在鏈表中查找某位置結點,則從鏈表頭結點位置開始不斷向下遍歷鏈表,直到查找到對應位置的結點結束
* 2、返回查找結點,否則結點不存在。
*
* @param i 要查詢的節點位置
* @return 要查詢的節點
*/
public Node query(int i) {
Node p = front;
if (i < 0 || i > length) {
return p;
}
if (i == 1) {
return p;
}
for (int j = 1; j <= i; j++) {
p = p.next;
}
return p;
}
/**
* 刪除結點
*
* 1、找到刪除結點直接前驅對應的位置,若存在則繼續,否則結束;
* 2、若要刪除的結點存在則繼續,否則繼續;
* 3、刪除對應位置結點,結束。
*
* @param i 要刪除節點的位置
*/
public Node delete(int i) {
Node node = new Node(); // 保存刪除的第i個結點
// 判斷刪除位置是否正確
if (i < 0 || i > length) {
System.out.println("刪除位置i無效");
return null;
}
// 查找要刪除結點的前一個元素
Node p = query(i - 1);
node = p.next;
p.next = node.next;
length--;
return node;
}
}
三、使用
public static void main(String[] args) {
CirLinkedList<String> cirLinkedList = new CirLinkedList<>();
cirLinkedList.insert("1");
cirLinkedList.insert("2");
cirLinkedList.insert("3");
System.out.println(cirLinkedList.query(1).e);
}