大话数据结构(三)——单向循环链表的java实现

首先,我们来说说什么是单向循环链表:

单向循环链表就是单链表的另外一种表现形式,其结构特点是最后一个指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环,就像将一根铁链子首尾连接形成一个铁链环一样。


在单链表中,由于每个结点只存储了向后的指针,到了尾标志就停止了向后链的操作,这样当中的某一结点就无法找到他的前驱结点了,即无法回到之前的结点。这就体现出了单链循环链表的劣势。

说了这么多,我们来看看单向循环链表的实现方法和测试程序吧~~


定义循环链表CycleLinkList

其中头结点为header,尾结点为tail,链表大小为size,类中包含有删除、插入、查找、清空等操作。

package CycleLinkList;

/**
 * Created by jiangxs on 17-5-22.
 */
public class CycleLinkList<T> {

    //定义一个内部类Node代表链表的节点
    private class Node{
        private T data;//保存数据
        private Node next;//指向下一个节点的引用

        //无参构造器
        public Node(){}

        //初始化全部属性的构造器
        public Node(T data,Node next){
            this.data = data;
            this.next = next;
        }
    }

    private Node header;//保存头结点
    private Node tail;//保存尾节点
    private int size;//保存已含有的结点数

    //创建空链表
    public CycleLinkList(){}

    //以指定数据元素创建链表,只有一个元素
    public CycleLinkList(T element){
        header = new Node(element,header);
        tail = header;
        size++;
    }

    //返回链表长度
    public int getSize(){
        return size;
    }

    //获取指定位置的结点
    public Node getNodeByIndex(int index){
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("获取位置超过了链表长度范围");
        Node current = header;//从链表表头开始遍历
        for (int i = 0;i<size && current.next != null;i++,current = current.next)
            if (i == index)
                return current;
        return null;
    }

    //获取指定索引处的元素
    public T get(int index){
        return this.getNodeByIndex(index).data;
    }

    //按值查找所在位置
    public int local(T element){
        Node current = header;

        for (int i = 0;i < size && current != null;i++,current = current.next)
            if (current.data.equals(element))
                return i;
        return -1;
    }

    //在尾部插入元素
    public void add(T element){
        //如果链表为空
        if (isEmpty()){
            header = new Node(element,header);
            tail = header;//空链表中头结点和尾结点相同
        }
        else {
            //创建新结点
            Node newNode = new Node(element,null);
            //让尾结点指向新结点
            tail.next = newNode;
            //让新结点指向头结点
            newNode.next = header;
            //将新结点作为尾结点
            tail = newNode;
        }
        size++;
    }

    //在头部插入
    public void addHeader(T element){
        //如果链表为空
        if (isEmpty()) {
            header = new Node(element,header);
            tail = header;
        }
        else {
            //创建新结点
            Node newNode = new Node(element, null);
            //让新结点指向header
            newNode.next = header;
            //然后让新结点作为header
            header = newNode;
            //将尾结点指向头结点
            tail.next = header;
        }
        size++;
    }

    /**
     * 在指定位置插入元素
     * @param element 要插入的元素
     * @param index 要插入的位置
     */
    public void insert(T element,int index){
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("插入位置超出链表范围");
        //如果链表为空
        if (header == null)
            add(element);
        else {
            //如果插入位置为0
            if (index == 0)
                addHeader(element);
            else {
                //获取插入位置的前一个结点
                Node prev = getNodeByIndex(index-1);
                //让prev指向新的结点,新结点指向原prev结点的下一个结点
                prev.next = new Node(element,prev.next);
                size++;
            }
        }
    }

    /**
     * 删除索引处的元素
     * @param index
     * 输入要删除的位置
     */
    public T delete(int index){
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("删除位置超出链表范围");
        Node del = null;
        //如果删除的是头结点
        if (index == 0){
            del = header;
            header = header.next;
            del.next = null;
            tail.next = header;
        }
        //如果删除的是尾结点
        else if (index == size-1){
            Node prevT = getNodeByIndex(index-1);
            del = tail;
            tail = prevT;
            del.next = null;
            tail.next = header;
        }
        //如果删除的是中间结点
        else if (index > 0 && index < size-1){
            Node prev = getNodeByIndex(index-1);
            del = prev.next;
            prev.next = del.next;
            del.next = null;
        }
        size--;
        return del.data;
    }

    //删除最后一个元素
    public T remove(){
        return delete(size-1);
    }

    //判断链表是否为空
    public boolean isEmpty(){
        return size == 0;
    }

    //清空线性表
    public void clear(){
        //将头结点和尾结点设为空
        header = null;
        tail = null;
        size = 0;
    }

    public String toString(){
        if (isEmpty())
            return "[]";
        else {
            StringBuilder sb = new StringBuilder("[");
            sb.append(header.data+"->").toString();
            for (Node current = header.next;current != header;current = current.next)
                sb.append(current.data+"->").toString();
            int len = sb.length();
            return sb.delete(len-2,len).append("]").toString();
        }
    }
}

测试代码

package CycleLinkList;

/**
 * Created by jiangxs on 17-5-22.
 */
public class CycleLinkListTest {
    public static void main(String[] args) {
        CycleLinkList<String> ll = new CycleLinkList<String>();
        //在链表尾添加元素
        ll.add("haha");
        ll.add("hehe");
        ll.add("xixi");
        System.out.println("原有循环链表中的元素: ");
        System.out.println(ll);
        //在链表头插入元素
        ll.addHeader("hiahia");
        System.out.println("循环链表头结点插入后链表中的元素: ");
        System.out.println(ll);
        //在循环链表中位置2处插入元素
        ll.insert("heihei",2);
        System.out.println("循环链表2处插入元素后链表中的元素: ");
        System.out.println(ll);
        //删除循环链表中位置2的元素
        ll.delete(2);
        System.out.println("循环链表2处删除元素后链表中的元素: ");
        System.out.println(ll);
        //删除循环链表中尾结点
        ll.remove();
        System.out.println("循环链表末尾处删除元素后链表中的元素: ");
        System.out.println(ll);
        System.out.println("循环链表中元素haha的位置: "+ll.local("haha"));
        System.out.println("循环链表中位置1的元素: "+ll.get(1));
        System.out.println("循环链表的长度为: "+ll.getSize());
    }
}

测试结果

原有循环链表中的元素: 
[haha->hehe->xixi]
循环链表头结点插入后链表中的元素: 
[hiahia->haha->hehe->xixi]
循环链表2处插入元素后链表中的元素: 
[hiahia->haha->heihei->hehe->xixi]
循环链表2处删除元素后链表中的元素: 
[hiahia->haha->hehe->xixi]
循环链表末尾处删除元素后链表中的元素: 
[hiahia->haha->hehe]
循环链表中元素haha的位置: 1
循环链表中位置1的元素: haha
循环链表的长度为: 3

Process finished with exit code 0

参考:《大话数据结构》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值