Java模拟(单双向)循环链表图文说明,有源码有注释

单向循环链表

前面为了说明方便,有些是用的贴图,由于有些图片较大形成挤压,看不清点击看原图即可,源码会在后面给出,话不多说,开始吧!

  • 节点类Node
/**
 *  @author AmVilCresx
 * 节点类
 */
public class Node {
    Object element; //数据域
    Node next; // 后继指针域
    Node previor;// 前驱指针域

    //非头结点的构造方法
    public Node(Object element) {
        this.element = element;
    }
}
  • 插入链表的第一个元素
    FirstrNode

  • 在尾部插入节点元素
    insertRear

  • 在头部插入节点元素
    insrtHead
  • 在指定位置插入元素节点
    anyWhere

  • 删除指定位置的节点
    delete

  • 删除给定的元素节点(注释做了简单说明,其它操作跟上面删除类似)
    delByNode

  • 单向循环链表源码
    复制粘贴开发工具,修改你自己的包名即可运行
public class Node {
    Object element; //数据域
    Node next; // 后继指针域
    Node previor;// 前驱指针域

    //非头结点的构造方法
    public Node(Object element) {
        this.element = element;
    }
}
------------------------分割线------------------------------------
package com.avc.link;

/**
 * @author AmVilCresx
 * 模拟单向循环链表
 * */
public class CycleLinkList{

    Node head; //头指针
    Node rear; //尾节点
    Node currentPrior; 当前节点的前一个节点,下面的删除和插入要用
    int size; //节点个数

    /**
     * 对空链表第一个节点进行插入
     * */
    private void insertFirstNode(Node node) {
        head = node;    //头指针指向node
        rear = head;    // 尾指针指向head
        head.next = rear;   //链接成环状
        size++; //长度+1
    }   

    /**
     * 在末尾插入
     * */
    public void insertRear(Node node) {
        if(head == null) {
            insertFirstNode(node); // 插入链表的第一个元素
        }else {
            node.next = rear.next;  //将带插入节点的next指向原链表rear的next;
            rear.next = node;   // 将原链表的rear的next指向node
            rear = node;    // 改变rear的指向 为node
            size++;     //长度+1
        }   
    }

    /**
     * 头插法
     * 头插其实就是和末尾插入一样的,只不过尾插改变的是尾指针,头指针不变,头插改变头指针,尾指针不变
     * */
    public void insertHead(Node node) {
        if(head == null) {
            insertFirstNode(node);
        }else {
            node.next = rear.next; 
            rear.next=node;
            head=node; // 此处改变的是头指针head的指向
            size++;
        }
    }


    /**
     * 获取节点
     * */
    public Node get(int index){
        Node tmp = head;
        int j=0;
        if(index<0 || index>size-1) {
            return null;
        }
        while(j!=index) {
            tmp = tmp.next;
            j++;
        }
        return tmp;
    }

    /**
     * 定位到操作节点的前一个位置
     * */
    public void getLoation(int index) {
        currentPrior = head;
        int j=0;

        while(j<index-1) {//找到要插入的位置前一个位置
            currentPrior = currentPrior.next;
            j++;
        }
        if(index==0) { //如果是第一个节点,则它的前一个节点就是rear节点,上面的while没处理这种情况
            currentPrior=rear; //手动赋值
            head=head.next; //注意:一定要将head指向下一个节点,不然get的时候会出错
        }
    }

    /**
     * 在这指定位置进行插入
     * */
    public void insertAnyWhere(int index,Node node) {
        if(index<0 || index > size) {
            throw new RuntimeException("参数非法");
        }

        if(index == 0) { //第一个位置,说明是头插 
            this.insertHead(node);
        }else if(index == size) { //最后一个位置,说明是,尾插
            this.insertRear(node);
        }else {
            getLoation(index);  //定位到index的前一个位置
            node.next = currentPrior.next; // 将带插入节点的next指向当前节点(也就是当前节点的前一个节点的下一个节点)
            currentPrior.next=node; // 将前一个节点的next指向node,完成连接
            size++; // 长度+1
        }
    }

    /**
     * 删除指定位置的节点
     * */
    public Node delete(int index) {
        if(index<0 || index>size-1)
            throw new RuntimeException("参数非法");
        if(isEmpty()) {
            throw new RuntimeException("链表为空,操作失败");
        }
        Node delNode = null;
        getLoation(index); //定位到index的前一个位置
        delNode = currentPrior.next; //待删除的节点(当前节点)
        currentPrior.next=delNode.next; // 将当前节点的前驱节点的next指针指向当前节点的next域
        size--; //长度 -1
        return delNode;
    }


    /**
     * 删除给定的节点,这里为了测试方便,默认值相同则是相同的节点,并且不存在element相同的节点
     * */
    public Node deleteByNode(Node node) {
        Node delNode= null;
        if(isEmpty()) {
            throw new RuntimeException("链表为空,操作失败");
        }
        if(size==1 && node.element == head.element) {
            delete(0);
            head=null;
            return node;
        }
        Node tmp = head; //临时指针变量
        int count=size;
        while(count>0 && node.element!= tmp.next.element) {
            // 如果小于count,没走完一圈 或者下个节点的值不等于给定节点的值
            count--;
            tmp = tmp.next;
        }
        if(count==0) {
            throw new RuntimeException("元素不存在,无法删除");
        }else {
            delNode = tmp.next;
            if(delNode==head) { // 判断一下,不然get会出错
                head=delNode.next;
            }
            if(tmp.next==rear) {
                rear=tmp;
            }
            tmp.next=delNode.next; // 改变指针指向
            size--;
        }
        return delNode;
    }

    //链表大小
    public int size() {
        return this.size;
    }
    /**
     * 判断链表是否为空
     * */
    public boolean isEmpty() {
        return size==0;
    }

    public static void main(String[] args) {
        CycleLinkList list = new CycleLinkList();
        /*list.insertRear(new Node(1));
        list.insertRear(new Node(2));
        list.insertRear(new Node(3));
        System.out.println(list.get(1).getElement());*/
        list.insertHead(new Node(1));
        list.insertHead(new Node(2));
        list.insertHead(new Node(3));
        list.insertHead(new Node(4));
        Node ist = new Node(6);
        list.insertRear(ist);
    //  list.insertAnyWhere(1, new Node("insrt"));
        /*System.out.println(list.get(1).element);
        System.out.println("size----"+list.size());
        list.delete(1);
        System.out.println("size----"+list.size());
        System.out.println(list.get(1).element);
        System.out.println(list.get(1).next.element);*/
        System.out.println("size----"+list.size());
        System.out.println(list.get(3).element);
        System.out.println(list.deleteByNode(ist).element);
        System.out.println("size----"+list.size());
        System.out.println(list.get(3).element);

    }
}
双向循环链表
  • 在尾部插入节点元素
    Rear

  • 在头部插入元素节点
    Head

  • 在指定的位置插入节点
    any

  • 删除指定位置的节点元素
    del

  • 删除给定的节点元素
    del2

    • 双向循环链表源码
package com.avc.link;

/**
 * @author AmVilCresx
 * 模拟双向循环链表
 *
 */
public class CycleBothWayLinkList {

    Node head; //头指针
    Node rear; //尾节点
    Node current; //当前节点,下面的删除和插入要用
    int size=0; //节点个数

    /**
     * 插入整个链表的第一个节点
     * */
    private void insertFirstNode(Node node ) {
        head=node;
        rear=head;
        head.next=rear; 
        head.previor=rear;// 形成双向环状
        size++;
    }

    /**
     * 尾插法
     * */
    public void insertRear(Node node) {
        if(head == null) {
            insertFirstNode(node);
        }else {
            node.next=rear.next;    // 将带插入节点node的next指向rear的next
            node.previor=rear;  // 将node的前驱指向rear
            rear.next.previor=node; //将rear的next的前驱指向node
            rear.next=node; //将rear的next指向node
            rear=node; //将rear设置为node
            size++;
        }

    }

    /**
     * 头插法
     * */
    public void insertHead(Node node) {
        if(head == null) {
            insertFirstNode(node);
        }else {
            node.next=rear.next; // 将带插入节点node的next指向rear的next
            node.previor=rear; //将node的前驱指向rear
            rear.next.previor=node; //将原来rear的next节点的前驱设置为node
            rear.next=node; //则rear的next指向node
            head = node; // 改变head的指向
            size++;
        }
    }

    /**
     * 在任意位置插入
     * */
    public void insertAnyWhere(int index, Node node) {
        if(index<0 || index>size) {
            throw new RuntimeException("参数非法!");
        }
        if(index ==0) {
            insertHead(node);
        }else if(index==size) {
            insertRear(node);
        }else {
            getLoation(index); // 因为是双向链表,所以直接定位到要操作的节点
            node.next = current; //将待插入节点的next指向当期节点
            node.previor=current.previor; //将node的前驱节点设置为当前节点的前驱节点
            current.previor.next=node; // 再讲当前节点的前驱的next指向node
            current.previor=node; // 再将当前节点的前驱节点设置为node
            size++;
        }
    }

    /**
     * 删除指定位置的节点
     * */
    public Node deleteNode(int index) {
        if(index<0 || index>size-1)
            throw new RuntimeException("参数非法");
        if(isEmpty()) {
            throw new RuntimeException("链表为空,操作失败");
        }
        getLoation(index);//找到要插入的位置的当前节点(这里也可以找要操作的节点的前一个节点,因为这里有前驱指针,可不必)
        Node delNode = current;
        current.previor.next=current.next;
        current.next.previor=current.previor;
        size--;
        return delNode;
    }

    /**
     * 删除给定的节点,这里为了测试方便,默认值相同则是相同的节点,并且不存在element相同的节点
     * */
    public Node deleteByGiveNode(Node node) {
        Node delNode= null;
        if(isEmpty()) {
            throw new RuntimeException("链表为空,操作失败");
        }
        if(size==1 && node.element == head.element) {
            deleteNode(0);
            head=null;
            return node;
        }
        Node tmp = head;
        int count=size;
        while(count>0 && tmp.element != node.element) {
            count--;
            tmp=tmp.next;
        }
        if(count==0) {
            throw new RuntimeException("元素不存在,无法删除");
        }else {
            delNode = tmp;
            if(delNode==head) {
                head=delNode.next;
            }
            if(delNode==rear) {
                rear=delNode.previor;
            }
            tmp.previor.next=tmp.next;
            tmp.next.previor=tmp.previor;
            size--;
        }       
        return delNode;
    }

    //定位到指定位置
    public void getLoation(int index) {
        current = head;
        int j=0;
        while(j<index) {//找到要插入的位置前一个位置
            current = current.next;
            j++;
        }
        if(index ==0) {
            head = current.next; //改变head的指向
        }
    }

    /**
     * 获取节点
     * */
    public Node get(int index){
        Node tmp = head;
        int j=0;
        if(index<0 || index>size-1) {
            return null;
        }
        while(j!=index) {
            tmp = tmp.next;
            j++;
        }
        return tmp;
    }

    public boolean isEmpty() {
        return size==0;
    }
    //链表大小
    public int size() {
        return this.size;
    }

    /**
     * main函数测试
     * */
    public static void main(String[] args) {
        CycleBothWayLinkList cyl = new CycleBothWayLinkList();
        cyl.insertHead(new Node(1));
        cyl.insertHead(new Node(2));
        cyl.insertHead(new Node(3));
        cyl.insertHead(new Node(4));
        System.out.println("前驱:"+cyl.get(0).previor.element);
        System.out.println("自身:"+cyl.get(0).element);
        System.out.println("后继:"+cyl.get(0).next.element);
        System.out.println("---------------");
        cyl.insertAnyWhere(0, new Node("insrt"));
        System.out.println("前驱:"+cyl.get(0).previor.element);
        System.out.println("自身:"+cyl.get(0).element);
        System.out.println("后继:"+cyl.get(0).next.element);
        System.out.println("---------------");
        cyl.deleteNode(0);
        System.out.println("前驱:"+cyl.get(0).previor.element);
        System.out.println("自身:"+cyl.get(0).element);
        System.out.println("后继:"+cyl.get(0).next.element);
    }
}

有问题请大家留言,批评指正!共勉!!!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值