大话数据结构系列之循环链表(五)

定义

循环链表(circular linked list)是将单链表中终端节点的指针端由空指针改为指向头结点,就使整个单链表形成一个环。

实际含义:
存在循环的情景,例如录音机的循环播放,网易云的单曲循环功能(需要从 头 ——> 尾 )

代码实现(Java )

Java 语言

package com.example;

/*
 * 初始化时,含有头尾节点的单链表循环结构
 * 对比单向链表优势,寻找头尾节点的时间复杂度为O[1]
 * 在合并双向链表时,时间复杂度为O[1] 见 unionList方法
 */
public class LoopLinkList<T> {

    //是否可以泛型中嵌套泛型? 遗留
    @SuppressWarnings("hiding")
    class Node<T> {
    
        protected Node<T> next;
        
        protected T data;
        
        public Node(T data){
            this.data = data;
        }
    }
    /* 产生头结点 */
    public Node<T> head;
    
    /* 产生尾结点 */
    public Node<T> rear;
    
    /*线性表长度 */
    private int size;
    
    /* 初始化顺序线性表  头节点,只存储指针,末节点存值,顾算一个单位*/
    void initList(){
        this.head = new Node<T>(null);
        this.rear = new Node<T>(null);
        this.rear.next=this.head;
        this.head.next = this.rear;
        this.size = 2;
    }
    
    /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
    boolean listEmpty(){
        if(this.size==2 && this.head == null && this.rear == null)
            return true;
        else
            return false;
    }
    
    /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
    int clearList(LoopLinkList<T> list){
        //无法做到像C语言中的free(),直接放到内存空间
        list = new LoopLinkList<T>();
        return 1;
    }
    
    /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
    int listLength(){
        int i =1;
        Node<T> tempNode = this.head;
        while(tempNode.next != this.head){
            tempNode=tempNode.next;
            i++;
        }
        return i;
    }
    
    /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
    /* 操作结果:用e返回L中第i个数据元素的值 */
    T getElem(int index){
        T data;
        int position = 0;
        Node<T> current = this.head;
        if(index>=0 && index<this.size){
            while(position != index){
                current = current.next;
                position++;
            }
            data = (T)current.data;
        }else{
            throw new IndexOutOfBoundsException("超出链表长度");
        }
        return data;
    }
    
    /* 初始条件:顺序线性表L已存在 */
    /* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
    /* 若这样的数据元素不存在,则返回值为0 */
    int locateElem(T e){
        int temp =0;
        Node<T> tempNode = this.head;
        while(e != tempNode.data && temp < this.size-1){
            tempNode = tempNode.next;
            temp++;
        }
        if(e == tempNode.data){
            return temp;
        }else{
             System.out.println("未找到!");
             return -1;
        }
    }
    
    /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
    /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
    int listInsert(int index, T elem){
        Node<T> preNode = this.head;
        int position = 2;
        if(index<0 || index > this.size+1){
            throw new IndexOutOfBoundsException("index 位置不合法");
        }else if(index ==1){
                 if(head.data ==null){
                     this.head.data=elem;
                 }else{
                     addFromHead(elem);
                 }
        }else if(index == this.size){
                  this.rear.data=elem;
        }else if(index == this.size+1){
             addFromTail(elem);
        }else{
            while(position != index ){
                    preNode = preNode.next;
                    position++;
            }
            Node<T> newNode = new Node<T>(elem);
            newNode.next=preNode.next;
            preNode.next=newNode;
            this.size++;
        }
        return 1;
    }
    
    /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
    /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
    public void listDelete(int index){
        int position = 2;
        Node<T> preNode = this.head;
        if(index<0 || index > this.size){
            throw new IndexOutOfBoundsException("超出链表长度");
        }else{
            while(position != index){
                    preNode = preNode.next;
                    position++;
            }
            //剪到最后一位
            if(index == this.size){
                 if(this.rear.data == null){
                     System.out.println("size=1为最小,不能在减了!");
                     return;
                 }else{
                     preNode.next=head;
                     rear=preNode;
                 }
            }else{
                preNode.next=preNode.next.next;
            }
            
        }
        this.size--;
    }
    
    /* 初始条件:顺序线性表L已存在 */
    /* 操作结果:依次对L的每个数据元素输出 */
    void listTraverse(){
        int position = 0;
        Node<T> tempNode = this.head;
        while(position != this.size){
            System.out.println(tempNode.data);
            tempNode = tempNode.next;
            position++;
        }
    }
    
    /*(尾插法)*/
     public void addFromTail(T data){
         Node<T> newNode = new Node<T>(data);
         rear.next=newNode;
         newNode.next=head;
         rear = newNode;
         size++;
     }
     
     /*(头插法)*/
     public void addFromHead(T data){
         Node<T> newNode = new Node<T>(data);
         newNode.next=head;
         head=newNode;
         rear.next=head;
         size++;
     }
     
     public void unionList(LoopLinkList<T> list){
         //头尾节点相连
         this.rear.next=list.head;
         list.rear.next=this.head;
         this.size=this.size+list.size;
     }
     
     public static void main(String[] args){
            LoopLinkList<Integer> L = new LoopLinkList<Integer>();
            Integer e;
            int j,k;
            L.initList();
            System.out.println("初始化L后:ListLength(L)=%d\n"+L.listLength());
            for(j=1;j<=5;j++)
                    L.listInsert(j,j);
            System.out.println("在L的表头依次插入1~5后:L.data=");
            L.listTraverse(); 
            //
            System.out.println("ListLength(L)=%d \n"+L.listLength());
            System.out.println("L是否空:i=%d(1:是 0:否)\n"+L.listEmpty());

            L.clearList(L);
            System.out.println("清空L后:ListLength(L)=%d\n"+L.listLength());
            System.out.println("L是否空:i=%d(1:是 0:否)\n"+L.listEmpty());
            
            L.listInsert(1,0);
            System.out.println("在L的表头插入0后:L.data=");
            L.listTraverse(); 
            System.out.println("ListLength(L)=%d \n"+L.listLength());

            e = L.getElem(5);
            System.out.println("第5个元素的值为:%d\n"+e);
            for(j=3;j<=4;j++)
            {
                    k=L.locateElem(j);
                     System.out.println("第%d个元素的值为%d\n"+k);
            }
            
            k=L.listLength(); /* k为表长 */
            for(j=k;j>=k;j--)
            {       
                    //在删除元素时,需要判断链表长度
                    System.out.println("正在删除k:"+k);
                    L.listDelete(j); /* 删除第j个数据 */
            }
            System.out.println("依次输出L的元素:");
            L.listTraverse(); 

            j=4;
            L.listDelete(j); /* 删除第4个数据 */
            System.out.println("删除第%d个的元素值为:%d\n"+j+e);

            System.out.println("依次输出L的元素:");
            L.listTraverse(); 

            L.clearList(L);
            System.out.println("\n清空L后:ListLength(L)=%d\n"+L.listLength());
            L.addFromHead(20);
            System.out.println("整体创建L的元素(头插法):");
            L.listTraverse(); 
            
            L.clearList(L);
            System.out.println("\n删除L后:ListLength(L)=%d\n"+L.listLength());
            L.addFromTail(20);
            
            /*
             * 使用尾部插入时报错,最后一个元素的next 没有指向的值???
             * Exception in thread "main" java.lang.NullPointerException
                at com.roncoo.example.LoopLinkList.listTraverse(LoopLinkList.java:139)
                at com.roncoo.example.LoopLinkList.main(LoopLinkList.java:224)
             */
            
            System.out.println("整体创建L的元素(尾插法):");
            L.listTraverse(); 
            
            LoopLinkList<Integer> LB = new LoopLinkList<Integer>();
            LB.initList();
            System.out.println("初始化L后:ListLength(L)=%d\n"+LB.listLength());
            for(j=1;j<=5;j++)
                LB.listInsert(j,j);
            LB.listTraverse();
            L.unionList(LB);
            System.out.println("整体合并LB的元素后:");
            L.listTraverse();
     }
}
发布了222 篇原创文章 · 获赞 54 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/weixin_39966065/article/details/104041516