
循环链表就是把头尾接起来了。 有循环单链表和循环双链表,实现原理基本一致。
因此就用循环双链表举例吧。

创建节点类和初始化链表
public class CycleLinkedList {
public class Data{
int num;
Data last = null;
Data next = null;
public Data(int num){
this.num = num;
}
}
Data head = new Data(0);
Data tail = new Data(0);
public CycleLinkedList(){
head.next = tail;
tail.last = head;
}
}
插入数据,注意最后一个节点指向第一个节点,第一个节点指向最后一个节点,这样才能形成一个循环。
// 头插法
public void insertP(int num){
Data data = new Data(num);
data.next = head.next;
head.next.last = data;
head.next = data;
// 这里,插入节点的上一位不再指向头节点,而是指向最后的数据
// 同时把最后一个数据节点的下一位指向自己,形成一个循环
data.last = tail.last;
tail.last.next = data;
}
// 尾插法
public void insertE(int num){
Data data = new Data(num);
data.last = tail.last;
tail.last.next = data;
tail.last = data;
// 这里和上面一样的道理
data.next = head.next;
head.next.last = data;
}
// 查找
public void find(int num){
// 链表判空
if(head.next == tail){
return;
}
Data cur = head.next;
int i = 0;
do{
if(cur.num == num){
System.out.println("找到数字 " + num + ", 位于链表的第 " + i + " 个");
}
i++;
cur = cur.next;
} while(cur != head.next);
// 指针又回到了第一个节点,跳出循环
}
根据索引删除和替换,那怎么根据数值删除呢?结合一下查找函数和删除函数不久可以了嘛,之前几篇也有相关代码。
// 根据索引删除数据 (从0计数)
public void remove(int index){
if(head.next == tail){
return;
}
Data cur = head.next;
for(int i = 0; i < index+1; i++){
if(i == index){
cur.last.next = cur.next;
cur.next.last = cur.last;
if(cur == head.next){ // 如果是第一个节点
head.next = head.next.next;
} else if(cur == tail.last){ // 如果是最后一个节点
tail.last = tail.last.last;
}
break;
}
cur = cur.next;
if(cur == head.next){// 指针回到了开头
System.out.println("索引不存在");
break;
}
}
}
// 根据索引替换数据 (从0计数)
public void replace(int index, int num){
if(head.next == tail){
return;
}
Data cur = head.next;
for(int i = 0; i < index+1; i++){
if(i == index){
cur.num = num;
break;
}
cur = cur.next;
if(cur == head.next){// 指针回到了开头
System.out.println("索引不存在");
break;
}
}
}
补充一个之前没提到过的——加塞数据

// 加塞数据
public void add(int index, int num){
if(head.next == tail){
return;
}
// 在0处插入,调用头插函数
if(index == 0){
insertP(num);
return;
}
// 中间插入的情况
Data cur = head.next;
for(int i = 0; i < index+1; i++){
if(i == index){
Data data = new Data(num);
data.next = cur;
data.last = cur.last;
cur.last.next = data;
cur.last = data;
break;
}
cur = cur.next;
if(cur == head.next){
// 在回到头部时,i 为总元素个数
// 如果index等于i+1,则调用尾插法
if(index == i+1){
insertE(num);
break;
}
break;
}
}
}
显示和反向显示,双链表就是这么方便。
反向显示就是顺序倒过来了。
// 显示
public void display(){
if(head.next == tail){
return;
}
Data cur = head.next;
do{
System.out.print(cur.num + " ");
cur = cur.next;
} while( cur != head.next);
System.out.println("\n");
}
// 反向显示 和正向道理是一样的
public void antiDisplay(){
if(head.next == tail){
return;
}
Data cur = tail.last;
do{
System.out.print(cur.num + " ");
cur = cur.last;
} while(cur != tail.last);
System.out.println("\n");
}
测试测试~
public static void main(String[] args){
CycleLinkedList cll = new CycleLinkedList();
System.out.println("尾插法插入 1 5 3 5 5 6");
cll.insertE(1);
cll.insertE(5);
cll.insertE(3);
cll.insertE(5);
cll.insertE(5);
cll.insertE(6);
cll.display();
System.out.println("反向显示");
cll.antiDisplay();
System.out.println("查找 5");
cll.find(5);
System.out.println("\n把8插入到第0位,把2插入到第5位,把7插入到第100位");
cll.add(0, 8);
cll.add(5, 2);
cll.add(100, 7);
cll.display();
System.out.println("删除第5个元素和第0个元素");
cll.remove(5);
cll.remove(0);
cll.display();
System.out.println("反向显示");
cll.antiDisplay();
}
输出结果
尾插法插入 1 5 3 5 5 6
1 5 3 5 5 6
反向显示
6 5 5 3 5 1
查找 5
找到数字 5, 位于链表的第 1 个
找到数字 5, 位于链表的第 3 个
找到数字 5, 位于链表的第 4 个
把8插入到第0位,把2插入到第5位,把7插入到第100位
8 1 5 3 5 2 5 6
删除第5个元素和第0个元素
1 5 3 5 5 6
反向显示
6 5 5 3 5 1
完整代码
public class CycleLinkedList {
public class Data{
int num;
Data last = null;
Data next = null;
public Data(int num){
this.num = num;
}
}
Data head = new Data(0);
Data tail = new Data(0);
public CycleLinkedList(){
head.next = tail;
tail.last = head;
}
// 头插法
public void insertP(int num){
Data data = new Data(num);
data.next = head.next;
head.next.last = data;
head.next = data;
// 这里,插入节点的上一位不再指向头节点,而是指向最后的数据
// 同时把最后一个数据节点的下一位指向自己,形成一个循环
data.last = tail.last;
tail.last.next = data;
}
// 尾插法
public void insertE(int num){
Data data = new Data(num);
data.last = tail.last;
tail.last.next = data;
tail.last = data;
// 这里和上面一样的道理
data.next = head.next;
head.next.last = data;
}
// 根据索引删除数据 (从0计数)
public void remove(int index){
if(head.next == tail){
return;
}
Data cur = head.next;
for(int i = 0; i < index+1; i++){
if(i == index){
cur.last.next = cur.next;
cur.next.last = cur.last;
if(cur == head.next){ // 如果是第一个节点
head.next = head.next.next;
} else if(cur == tail.last){ // 如果是最后一个节点
tail.last = tail.last.last;
}
break;
}
cur = cur.next;
if(cur == head.next){// 指针回到了开头
System.out.println("索引不存在");
break;
}
}
}
// 根据索引替换数据 (从0计数)
public void replace(int index, int num){
if(head.next == tail){
return;
}
Data cur = head.next;
for(int i = 0; i < index+1; i++){
if(i == index){
cur.num = num;
break;
}
cur = cur.next;
if(cur == head.next){// 指针回到了开头
System.out.println("索引不存在");
break;
}
}
}
// 加塞数据
public void add(int index, int num){
if(head.next == tail){
return;
}
// 在0处插入,调用头插函数
if(index == 0){
insertP(num);
return;
}
// 中间插入的情况
Data cur = head.next;
for(int i = 0; i < index+1; i++){
if(i == index){
Data data = new Data(num);
data.next = cur;
data.last = cur.last;
cur.last.next = data;
cur.last = data;
break;
}
cur = cur.next;
if(cur == head.next){
// 在回到头部时,i 为总元素个数
// 如果index等于i+1,则调用尾插法
if(index == i+1){
insertE(num);
break;
}
break;
}
}
}
// 查找
public void find(int num){
// 链表判空
if(head.next == tail){
return;
}
Data cur = head.next;
int i = 0;
do{
if(cur.num == num){
System.out.println("找到数字 " + num + ", 位于链表的第 " + i + " 个");
}
i++;
cur = cur.next;
} while(cur != head.next);
// 指针又回到了第一个节点,跳出循环
}
// 显示
public void display(){
if(head.next == tail){
return;
}
Data cur = head.next;
do{
System.out.print(cur.num + " ");
cur = cur.next;
} while( cur != head.next);
System.out.println("\n");
}
// 反向显示 和正向道理是一样的
public void antiDisplay(){
if(head.next == tail){
return;
}
Data cur = tail.last;
do{
System.out.print(cur.num + " ");
cur = cur.last;
} while(cur != tail.last);
System.out.println("\n");
}
public static void main(String[] args){
CycleLinkedList cll = new CycleLinkedList();
System.out.println("尾插法插入 1 5 3 5 5 6");
cll.insertE(1);
cll.insertE(5);
cll.insertE(3);
cll.insertE(5);
cll.insertE(5);
cll.insertE(6);
cll.display();
System.out.println("反向显示");
cll.antiDisplay();
System.out.println("查找 5");
cll.find(5);
System.out.println("\n把8插入到第0位,把2插入到第5位,把7插入到第100位");
cll.add(0, 8);
cll.add(5, 2);
cll.add(100, 7);
cll.display();
System.out.println("删除第5个元素和第0个元素");
cll.remove(5);
cll.remove(0);
cll.display();
System.out.println("反向显示");
cll.antiDisplay();
}
}