03java实现循环链表

本人git https://github.com/bigeyes-debug/Algorithm

一丶单向循环链表

  • 就是为尾节点指向头结点

二丶单向循环链表的接口设计

  • 比较单向链表,单向循环链表只需要修改添加节点,删除节点两个方法,也就是add和remove方法

三丶单向循环链表的实现

3.1添加节点

  • 相比于单向链表,单向循环链表只需要特别关注插入头结点的情况即可
  • 需要考虑的特殊情况是当链表的长度为0的时候的插入的情况

public void add(int index, E element) {
rangeCheckForAdd(index); if (index == 0) {
Node<E> newFirst = new Node<>(element, first);
// 拿到最后一个节点
Node<E> last = (size == 0) ? newFirst : node(size - 1);
last.next = newFirst;
first = newFirst;
} else {
Node<E> prev = node(index - 1);
prev.next = new Node<>(element, prev.next);
}
size++;
}

3.2删除节点

  • 如果删除的是头节点,删除后需让last指向新的头节点。
  • 当只有一个节点并删除时, first指向null。
public E remove(int index) {
rangeCheck(index); Node<E> node = first;
//删除头节点
if (index == 0) {
// 只有一个节点
if (size == 1) {
first = null;
} else {
Node<E> last = node(size - 1);
first = first.next;
last.next = first;
}
} else {
Node<E> prev = node(index - 1);
node = prev.next;
prev.next = node.next;
}
size--;
return node.element;
}

四、双向循环链表

五、双向循环链表接口设计

  • 相较于双向链表,双向循环链表需要重写插入节点、删除节点两个方法。

六丶双向循环链表接的实现

6.1插入节点

  • 需特殊处理添加第一个元素和添加到尾节点两种特殊情况。
public void add(int index, E element) {
rangeCheckForAdd(index);
// 如果 index == size, 说明添加的索引是最后位置
if (index == size) {
// 创建新节点, prev指向原链表的尾节点, next指向首节点
Node<E> node = new Node<>(last, element, first);
// 当原链表没有任何节点
if (size == 0) {
first = node;
last = node;
node.prev = node;
node.next = node;
}else {
// 原链表尾节点next指向node
last.next = node;
// 原链表头结点prev指向node
first.prev = node;
// last指向新的尾节点
last = node;
}
}else {
// 添加新节点后的下一个节点
Node<E> next = node(index);
// 添加新节点后的上一个节点
Node<E> prev = next.prev;
// 创建新节点, 新节点的上一个节点时prev, 新节点的下一个节点是next
Node<E> node = new Node<>(prev, element, next);
// next的上一个节点是新节点
next.prev = node;
// prev的下一个节点是新节点
prev.next = node;
// 当next == first时, 说明新添加节点的索引是0
if (next == first) {
first = node;
}
}
size++;
}

6.2删除节点

  • 删除节点,就是在环上去掉某一个节点,然后根据删除的节点是首节点或者尾节点来处理first和last。
  • 需要特殊处理只有一个节点的删除操作。
public E remove(int index) {
// 需要删除的节点
Node<E> node = node(index);
if (size == 1) {
first = null;
last = null;
}else {
// 删除节点的前一个节点
Node<E> prev = node.prev;
// 删除节点的后一个节点
Node<E> next = node.next;
next.prev = prev;
prev.next = next;
// 如果node == first, 说明删除的是第一个节点
if (node == first) {
first = next;
}
// 如果next == last, 说明删除的是最后一个节点
if (next == last) {
last = prev;
}
}
size--;
return node.element;
}

03-java实现循环链表的更多相关文章

  1. java与数据结构(3)---java实现循环链表

    循环链表:将单链表中尾结点的指针由空指针改为指向头结点,就使整个单链表形成一个环,这种首尾相接的单链表称为单链表循环表,即循环链表. 循环链表与单链表最重要的区别是:尾结点的指针,不再是p->n ...

  2. java实现循环链表的增删功能

    java实现循环链表的增删功能,完整代码 package songyan.test.demo; public class Demo { // java 实现循环链表 public static voi ...

  3. Java-Runoob-高级教程-实例-方法:03. Java 实例 – 汉诺塔算法-un

    ylbtech-Java-Runoob-高级教程-实例-方法:03. Java 实例 – 汉诺塔算法 1.返回顶部 1. Java 实例 - 汉诺塔算法  Java 实例 汉诺塔(又称河内塔)问题是源 ...

  4. Java-Runoob-高级教程-实例-时间处理:03. Java 实例 - 获取年份、月份等

    ylbtech-Java-Runoob-高级教程-实例-时间处理:03. Java 实例 - 获取年份.月份等 1.返回顶部 1. Java 实例 - 获取年份.月份等  Java 实例 以下实例演示 ...

  5. Java-Runoob-高级教程-实例-数组:03. Java 实例 – 获取数组长度-*

    ylbtech-Java-Runoob-高级教程-实例-数组:03. Java 实例 – 获取数组长度 1.返回顶部 Java 实例 - 获取数组长度  Java 实例 本文我们将为大家介绍如何使用数 ...

  6. Java-Runoob-高级教程-实例-字符串:03. Java 实例 - 删除字符串中的一个字符

    ylbtech-Java-Runoob-高级教程-实例-字符串:03. Java 实例 - 删除字符串中的一个字符 1.返回顶部 1. Java 实例 - 删除字符串中的一个字符  Java 实例 以 ...

  7. [03]java中的方法以及控制语句

    00 Java中的语句块 语句块(有时叫做复合语句),是用花括号扩起的任意数量的简单Java语句.块确定了局部变量的作用域.块中的程序代码,作为一个整体,是要被一起执行的.块可以被嵌套在另一个块中,但 ...

  8. 033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结

    033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结 本文知识点:运算符和表达式知识点总结 前面学习的几篇文都是运算符和表达式相关的知 ...

  9. 032 01 Android 零基础入门 01 Java基础语法 03 Java运算符 12 运算符和if-else条件语句的综合案例——闰年问题

    032 01 Android 零基础入门 01 Java基础语法 03 Java运算符 12 运算符和if-else条件语句的综合案例--闰年问题 本文知识点:运算符和if-else条件语句的综合案例 ...

  10. 031 01 Android 零基础入门 01 Java基础语法 03 Java运算符 11 运算符的优先级

    031 01 Android 零基础入门 01 Java基础语法 03 Java运算符 11 运算符的优先级 本文知识点:Java中运算符的优先级 运算符的优先级问题 前面学习了很多的运算符,如果这些 ...

随机推荐

  1. 也来谈谈python编码

    一.coding:utf-8 让我们先来看一个示例,源码文件是utf-8格式: print('你好 python') 当使用python2执行该程序时会收到一下报错: File "./hel ...

  2. Python基础-类与对象

    类的基本使用 class Person(): def __init__(self,name,age): self.name = name self.age = age def info(self): ...

  3. elementui 使用Form表单 的 resetForm表单功能出现的问题

    代码因为在保密机上,这里只进行描述并截取elemen文档中的代码作为参考 今天在开发一个很简单需求的时候遇到的问题,在使用elementui的表单功能,将增和改的表单进行了复用,是在表单的父组件 dr ...

  4. Docker基础使用

    Docker篇 CentOS 安装Docker - 菜鸟教程 安装须知: 1.Docker支持以下的CentOS版本: CentOS 7 (64-bit) CentOS 6.5 (64-bit) 或更 ...

  5. Ubuntu安装Redis过程完整笔记

    在阿里云与百度云均已经安装成功~~ 下载文件 切换路径设置下载存放地址 cd /home 下载安装包(http://download.redis.io/releases建议下载最新稳定版本) sudo ...

  6. 【Nginx】如何使用Nginx实现MySQL数据库的负载均衡?看完我懂了!!

    写在前面 Nginx能够实现HTTP.HTTPS协议的负载均衡,也能够实现TCP协议的负载均衡.那么,问题来了,可不可以通过Nginx实现MySQL数据库的负载均衡呢?答案是:可以.接下来,就让我们一 ...

  7. 从LocalDateTime序列化探讨全局一致性序列化

    日拱一卒无有尽,功不唐捐终入海. 楔子 前两周发了三篇SpringSecurity和一篇征文,这周打算写点简单有用易上手的文章,换换脑子,休息一下. 今天要写的是这篇:从LocalDateTime序列 ...

  8. NoSQL数据库-MongoDB 学习(一)

    基本介绍 MongoDB 是为了快速开发互联网 Web 应用而设计的数据库系统 MongoDB 的设计目标是极简.灵活.作为 Web 应用栈的一部分 MongoDB 的数据模型是面向文档的,所谓文档是 ...

  9. 题解 洛谷 P4143 【采集矿石】

    对于一个固定的左端点,右端点向右移动时,其子串权值和不断增大,字典序降序排名不断减小,因此对于一个左端点,最多存在一个右端点使其满足条件. 所以可以枚举左端点,然后二分右端点的位置,权值和通过前缀和来 ...

  10. vue-methods三种调用的形势

    var btn = { template:`<button>组件add</button>` } var any = new Vue({ el: '#app', data:{ a ...