单向循环链表实现
Posted guardwhy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单向循环链表实现相关的知识,希望对你有一定的参考价值。
1.1 基本介绍
循环链表,顾名思义,链表整体要形成一个圆环状。在单向链表中,最后一个节点的指针为null
,不指向任何结点,因为没有下一个元素了。要实现循环链表,只需要让单向链表的最后一个节点的指针指向头结点即可。
1.2 添加操作
1、思路分析
链表为空的时候
让head
和tail
同时指向这个结点,让尾结点的下一跳指向头结点。
头部添加
先让要添加的元素指向head
,然后再将head
指针指向新结点。
最后让tail
指针下一跳重新指向头结点
尾部添加
直接让新结点的下一跳指向头结点
当前尾节点指向新节点
最后tail
指针移动到新节点
2、代码示例
接口类:List
package cn.linkedlist.demo02;
/***
* List接口
* @param <E>
*/
public interface List<E> extends Iterable<E>
void add(E element);
void add(int index, E element) ;
void remove(E element);
E remove(int index);
E get(int index);
E set(int index, E element) ;
int size();
int indexOf(E element) ;
boolean contains(E element);
boolean isEmpty();
void clear();
链表类:LinkedSinglyCircularList
package cn.linkedlist.demo02;
import java.util.Iterator;
// 单向循环链表
public class LinkedSinglyCircularList<E> implements List<E>
// 创建Node节点
private class Node
//数据域 用来存储数据的
public E data;
//指针域 用来存储下一个结点对象的地址
public Node next;
// 构造方法
public Node()
this(null, null);
public Node(E data)
this(data, null);
public Node(E data, Node next)
this.data = data;
this.next = next;
@Override
public String toString()
StringBuilder sb = new StringBuilder();
sb.append(data).append("->").append(next.data);
return sb.toString();
// 链表元素的数量
private int size;
//链表当中的头指针指向第一个结点对象
private Node head;
//链表当中的头指针指向最后一个结点对象
private Node tail;
// 初始化链表
public LinkedSinglyCircularList()
head = null;
tail = null;
size = 0;
public LinkedSinglyCircularList(E[] arr)
for (E e : arr)
add(e);
/***
* 在链表末尾添加新的元素e
* @param element
*/
@Override
public void add(E element)
add(size, element);
/***
* 根据链表的index位置添加新的元素e
* @param index
* @param element
*/
@Override
public void add(int index, E element)
if (index < 0|| index > size)
throw new ArrayIndexOutOfBoundsException("add index out of bounds");
// 创建新的结点对象
Node node = new Node(element);
if(isEmpty())
// 链表为空
head = node;
tail = node;
tail.next = head;
else if(index == 0)
// 在链表头部添加元素
node.next = head;
head = node;
tail.next = head;
else if(index == size)
node.next = tail.next;
// 在链表尾部添加元素
tail.next = node;
tail = node;
else
// 在链表中添加元素
Node prev = head;
for(int i=0; i < index -1; i++)
prev = prev.next;
node.next = prev.next;
prev.next = node;
size++;
/***
* 得链表的第index个位置的元素
* @param index
* @return
*/
@Override
public E get(int index)
if (index < 0|| index > size)
throw new ArrayIndexOutOfBoundsException("get index out of bounds");
// 获取头部
if(index == 0)
return head.data;
else if(index == size -1)
// 获取尾部
return tail.data;
else
// 获取中间
Node prev = head;
for (int i = 0; i < index; i++)
prev = prev.next;
return prev.data;
/***
* 修改链表中指定index的元素为element
* @param index
* @param element
* @return
*/
@Override
public E set(int index, E element)
if (index < 0|| index > size)
throw new ArrayIndexOutOfBoundsException("update index out of bounds");
// 定义返回值
E result = null;
if(index == 0)
// 修改头部
result= head.data;
head.data = element;
else if(index == size -1)
// 修改尾部
result = tail.data;
tail.data = element;
else
// 修改中间的元素
Node prev = head;
for (int i = 0; i < index; i++)
prev = prev.next;
result = prev.data;
prev.data = element;
return result;
@Override
public int size()
return size;
/***
* 查找元素在链表中第一次出现的索引
* @param element
* @return
*/
@Override
public int indexOf(E element)
// 判断链表是否为空
if(isEmpty())
return -1;
// 定义prev指针
Node prev = head;
// 定义索引值
int index = 0;
while (!prev.data.equals(element))
prev = prev.next;
index++;
// 如果没有找到,则返回-1
if(prev == null)
return -1;
return index;
/***
* 查找链表中是否有元素element
* @param element
* @return
*/
@Override
public boolean contains(E element)
return indexOf(element)!= -1;
/***
* 判断链表是否为空
* @return
*/
@Override
public boolean isEmpty()
return size == 0 && head == null && tail == null;
@Override
public void clear()
head = null;
tail = null;
size = 0;
/***
* 迭代器实现
* @return
*/
@Override
public Iterator<E> iterator()
return new LinkedSinglyCircularListIterator();
class LinkedSinglyCircularListIterator implements Iterator<E>
// 定义游标
private Node cur = head;
// 创建flag,表示还可以继续循环
private boolean flag = true;
@Override
public boolean hasNext()
if(isEmpty())
return false;
return flag;
@Override
public E next()
E ret = cur.data;
cur = cur.next;
// 再次判断,是否已经循环完一圈
if(cur == head)
flag = false;
return ret;
@Override
public String toString()
StringBuilder res = new StringBuilder();
res.append("size=").append(size).append(", [");
Node node = head;
for (int i = 0; i < size; i++)
if (i != 0)
res.append(", ");
res.append(node);
node = node.next;
res.append("]");
return res.toString();
测试类:LinkedSinglyCircularListDemo
package cn.linkedlist.demo02;
public class LinkedSinglyCircularListDemo
public static void main(String[] args)
LinkedSinglyCircularList<Integer> list1 = new LinkedSinglyCircularList<>();
System.out.println("===链表头部插入===");
list1.add(0,1);
list1.add(0,3);
list1.add(0,5);
list1.add(0,8);
System.out.println(list1);
System.out.println("==链表尾部插入==");
list1.add(12);
System.out.println(list1);
System.out.println("===链表中间插入===");
list1.add(2, 23);
System.out.println(list1);
2、执行结果
1.3 删除操作
1、思路分析
删除头结点
head
指向下一个结点
原头结点的下一跳置空,让尾指针的下一跳重新指向头结点。
删除成功!!!
删除尾节点
定义一个指针prev
,找到删除尾部节点的前驱。
让prev.next
直接指向头结点
最后让tail
指向新节点
删除成功!!!
2、代码示例
链表类:LinkedSinglyCircularList
/***
* 删除链表中指定的元素element
* @param element
*/
@Override
public void remove(E element)
int index = indexOf(element);
if(index != -1)
remove(index);
/***
* 删除链表中指定索引处index的元素
* @param index
* @return
*/
@Override
public E remove(int index)
if (index < 0|| index > size)
throw new ArrayIndexOutOfBoundsException("remove index out of bounds");
// 定义返回值
E result = null;
// 当链表只剩下一个元素
if(size == 1)
result = head.data;
head = null;
tail = null;
else if(index == 0)
// 删除链表头部
Node prev = head;
result = prev.data;
head = prev.next;
// 置空操作
prev.next = null;
tail.next = head;
else if(index == size -1)
// 删除链表尾部
Node prev = head;
while (prev.next != tail)
prev = prev.next;
result = tail.data;
// 修改操作
prev.next = tail.next;
tail = prev;
else
// 删除中间的某个元素
Node prev = head;
for (int i = 0; i < index -1; i++)
prev = prev.next;
Node deleteNode = prev.next;
result = deleteNode.data;
prev.next = deleteNode.next;
// 置空
deleteNode.next = null;
size --;
return result;
测试类:LinkedSinglyCircularListDemo
package cn.linkedlist.demo06;
public class SingleCircleLinkedListDemo
public static void main(String[] args)
SingleCircleLinkedList<Integer> singleLinkedList = new SingleCircleLinkedList<>();
singleLinkedList.add(0,1);
singleLinkedList.add(0,3);
singleLinkedList.add(0,5);
singleLinkedList.add(0,8);
singleLinkedList.add(12);
singleLinkedList.add(2, 23);
System.out.println("===删除链表节点前====");
System.out.println(singleLinkedList);
System.out.println("===删除链表节点后====");
// 根据链表index位置的元素, 返回删除的元素
singleLinkedList.remove(2);
System.out.println(singleLinkedList);
// 删除链表中的元素
singleLinkedList.removeElement(12);
System.out.println(singleLinkedList);
2、执行结果
以上是关于单向循环链表实现的主要内容,如果未能解决你的问题,请参考以下文章