ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

单向循环链表实现

2021-12-15 17:06:36  阅读:103  来源: 互联网

标签:index head 单向 next 链表 循环 prev public


1.1 基本介绍

循环链表,顾名思义,链表整体要形成一个圆环状。在单向链表中,最后一个节点的指针为null,不指向任何结点,因为没有下一个元素了。要实现循环链表,只需要让单向链表的最后一个节点的指针指向头结点即可

1.2 添加操作

1、思路分析

链表为空的时候

headtail同时指向这个结点,让尾结点的下一跳指向头结点。

头部添加

先让要添加的元素指向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、执行结果

标签:index,head,单向,next,链表,循环,prev,public
来源: https://blog.csdn.net/hxy1625309592/article/details/121956476

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有