文章目录
定义
循环链表(circular linked list)是将单链表中终端节点的指针端由空指针改为指向头结点,就使整个单链表形成一个环。
实际含义:
存在循环的情景,例如录音机的循环播放,网易云的单曲循环功能(需要从 头 ——> 尾 )
代码实现(Java )
Java 语言
package com.example;
/*
* 初始化时,含有头尾节点的单链表循环结构
* 对比单向链表优势,寻找头尾节点的时间复杂度为O[1]
* 在合并双向链表时,时间复杂度为O[1] 见 unionList方法
*/
public class LoopLinkList<T> {
//是否可以泛型中嵌套泛型? 遗留
@SuppressWarnings("hiding")
class Node<T> {
protected Node<T> next;
protected T data;
public Node(T data){
this.data = data;
}
}
/* 产生头结点 */
public Node<T> head;
/* 产生尾结点 */
public Node<T> rear;
/*线性表长度 */
private int size;
/* 初始化顺序线性表 头节点,只存储指针,末节点存值,顾算一个单位*/
void initList(){
this.head = new Node<T>(null);
this.rear = new Node<T>(null);
this.rear.next=this.head;
this.head.next = this.rear;
this.size = 2;
}
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
boolean listEmpty(){
if(this.size==2 && this.head == null && this.rear == null)
return true;
else
return false;
}
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
int clearList(LoopLinkList<T> list){
//无法做到像C语言中的free(),直接放到内存空间
list = new LoopLinkList<T>();
return 1;
}
/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
int listLength(){
int i =1;
Node<T> tempNode = this.head;
while(tempNode.next != this.head){
tempNode=tempNode.next;
i++;
}
return i;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值 */
T getElem(int index){
T data;
int position = 0;
Node<T> current = this.head;
if(index>=0 && index<this.size){
while(position != index){
current = current.next;
position++;
}
data = (T)current.data;
}else{
throw new IndexOutOfBoundsException("超出链表长度");
}
return data;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int locateElem(T e){
int temp =0;
Node<T> tempNode = this.head;
while(e != tempNode.data && temp < this.size-1){
tempNode = tempNode.next;
temp++;
}
if(e == tempNode.data){
return temp;
}else{
System.out.println("未找到!");
return -1;
}
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
int listInsert(int index, T elem){
Node<T> preNode = this.head;
int position = 2;
if(index<0 || index > this.size+1){
throw new IndexOutOfBoundsException("index 位置不合法");
}else if(index ==1){
if(head.data ==null){
this.head.data=elem;
}else{
addFromHead(elem);
}
}else if(index == this.size){
this.rear.data=elem;
}else if(index == this.size+1){
addFromTail(elem);
}else{
while(position != index ){
preNode = preNode.next;
position++;
}
Node<T> newNode = new Node<T>(elem);
newNode.next=preNode.next;
preNode.next=newNode;
this.size++;
}
return 1;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
public void listDelete(int index){
int position = 2;
Node<T> preNode = this.head;
if(index<0 || index > this.size){
throw new IndexOutOfBoundsException("超出链表长度");
}else{
while(position != index){
preNode = preNode.next;
position++;
}
//剪到最后一位
if(index == this.size){
if(this.rear.data == null){
System.out.println("size=1为最小,不能在减了!");
return;
}else{
preNode.next=head;
rear=preNode;
}
}else{
preNode.next=preNode.next.next;
}
}
this.size--;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
void listTraverse(){
int position = 0;
Node<T> tempNode = this.head;
while(position != this.size){
System.out.println(tempNode.data);
tempNode = tempNode.next;
position++;
}
}
/*(尾插法)*/
public void addFromTail(T data){
Node<T> newNode = new Node<T>(data);
rear.next=newNode;
newNode.next=head;
rear = newNode;
size++;
}
/*(头插法)*/
public void addFromHead(T data){
Node<T> newNode = new Node<T>(data);
newNode.next=head;
head=newNode;
rear.next=head;
size++;
}
public void unionList(LoopLinkList<T> list){
//头尾节点相连
this.rear.next=list.head;
list.rear.next=this.head;
this.size=this.size+list.size;
}
public static void main(String[] args){
LoopLinkList<Integer> L = new LoopLinkList<Integer>();
Integer e;
int j,k;
L.initList();
System.out.println("初始化L后:ListLength(L)=%d\n"+L.listLength());
for(j=1;j<=5;j++)
L.listInsert(j,j);
System.out.println("在L的表头依次插入1~5后:L.data=");
L.listTraverse();
//
System.out.println("ListLength(L)=%d \n"+L.listLength());
System.out.println("L是否空:i=%d(1:是 0:否)\n"+L.listEmpty());
L.clearList(L);
System.out.println("清空L后:ListLength(L)=%d\n"+L.listLength());
System.out.println("L是否空:i=%d(1:是 0:否)\n"+L.listEmpty());
L.listInsert(1,0);
System.out.println("在L的表头插入0后:L.data=");
L.listTraverse();
System.out.println("ListLength(L)=%d \n"+L.listLength());
e = L.getElem(5);
System.out.println("第5个元素的值为:%d\n"+e);
for(j=3;j<=4;j++)
{
k=L.locateElem(j);
System.out.println("第%d个元素的值为%d\n"+k);
}
k=L.listLength(); /* k为表长 */
for(j=k;j>=k;j--)
{
//在删除元素时,需要判断链表长度
System.out.println("正在删除k:"+k);
L.listDelete(j); /* 删除第j个数据 */
}
System.out.println("依次输出L的元素:");
L.listTraverse();
j=4;
L.listDelete(j); /* 删除第4个数据 */
System.out.println("删除第%d个的元素值为:%d\n"+j+e);
System.out.println("依次输出L的元素:");
L.listTraverse();
L.clearList(L);
System.out.println("\n清空L后:ListLength(L)=%d\n"+L.listLength());
L.addFromHead(20);
System.out.println("整体创建L的元素(头插法):");
L.listTraverse();
L.clearList(L);
System.out.println("\n删除L后:ListLength(L)=%d\n"+L.listLength());
L.addFromTail(20);
/*
* 使用尾部插入时报错,最后一个元素的next 没有指向的值???
* Exception in thread "main" java.lang.NullPointerException
at com.roncoo.example.LoopLinkList.listTraverse(LoopLinkList.java:139)
at com.roncoo.example.LoopLinkList.main(LoopLinkList.java:224)
*/
System.out.println("整体创建L的元素(尾插法):");
L.listTraverse();
LoopLinkList<Integer> LB = new LoopLinkList<Integer>();
LB.initList();
System.out.println("初始化L后:ListLength(L)=%d\n"+LB.listLength());
for(j=1;j<=5;j++)
LB.listInsert(j,j);
LB.listTraverse();
L.unionList(LB);
System.out.println("整体合并LB的元素后:");
L.listTraverse();
}
}