大话数据结构系列之双向链表(六)

定义

双向链表( double linked list )由单链表演化而来,在单链表的每个节点中,在设置一个指向其前驱节点的指针域。

实际含义:
我们不仅需要正向的循环播放,亦需要反向循环功能。
例如监控探头的倒带功能,以及很多设计软件的回溯功能。

代码实现( Java )

Java 语言

package com.example;

/*
 * 对比单向链表:需要插入一个节点的前驱指针
 * 改变了插入,删除的方法
 * 整体:用空间来换时间的操作
 */
public class DupleLoopLinkList<T> {

    @SuppressWarnings("hiding")
    class Node<T> {
    
        protected Node<T> next;
        
        protected Node<T> prior;
        
        protected T data;
        
        public Node(T data){
            this.data = data;
        }
    }
    /* 产生头结点 */
    public Node<T> head;
    
    /*线性表长度 */
    private int size;
    
    /* 初始化顺序线性表 */
    void initList(DupleLoopLinkList<T> list){
        list.head = new Node<T>(null);
        list.head.next=list.head;
        list.head.prior=list.head;
        list.size = 0;
    }
    
    /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
    boolean listEmpty(DupleLoopLinkList<T> list){
        if(list.size==0)
            return true;
        else
            return false;
    }
    
    //真正置空的模式儿
    int clearListAll(DupleLoopLinkList<T> list){
        Node<T> tempNode = head;
        while(tempNode != null){
            Node<T> replace = tempNode.next;
            tempNode.data = null;
            tempNode.next = null;
            tempNode.prior = null;
            tempNode = replace;
        }
        tempNode = null;
        size = 0;
        //重新初始化
        initList(list);
        return 1;
    }
    
    /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
    int clearList(DupleLoopLinkList<T> list){
        //无法做到像C语言中的free(),直接放到内存空间
        list = new DupleLoopLinkList<T>();
        return 1;
    }
    
    
    /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
    int listLength(DupleLoopLinkList<T> list){
        int i =0;
        Node<T> tempNode = list.head;
        while(tempNode.next != list.head){
            tempNode=tempNode.next;
            i++;
        }
        return i;
    }
    
    /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
    /* 操作结果:用e返回L中第i个数据元素的值 */
    T getElem(DupleLoopLinkList<T> list, int index){
        T data;
        int position = 0;
        Node<T> current = head;
        if(index>=0 && index<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(DupleLoopLinkList<T> list, T e){
        int temp =0;
        Node<T> tempNode = head;
        while(e != tempNode.data && temp < 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(DupleLoopLinkList<T> list, int index, T elem){
        Node<T> preNode = head;
        int position = 2;
        if(index<0 || index > size+1){
            throw new IndexOutOfBoundsException("index 位置不合法");
        }else if(index ==1){
             if(head.data ==null){
                 head.data=elem;
                 size++;
            }else{
                 addFromHead(elem);
             }
        }else if(list.size ==1){
            Node<T> newNode = new Node<T>(elem);
            head.next=newNode;
            head.prior=newNode;
            newNode.next=head;
            newNode.prior=head;
            size++;
        }else if(index == this.size+1){
             addFromTail(elem);
        }else{
            while(position != index ){
                    preNode = preNode.next;
                    position++;
            }
            Node<T> newNode = new Node<T>(elem);
            newNode.prior=preNode;
            newNode.next=preNode.next;
            preNode.next.prior=newNode;
            preNode.next=newNode;
            size++;
        }
        return 1;
    }
    
    /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
    /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
    public void listDelete(DupleLoopLinkList<T> list,int index){
        int position = 0;
        Node<T> preNode = list.head;
        if(index<0 || index > list.size+1){
            throw new IndexOutOfBoundsException("超出链表长度");
        }else{
            while(position != index-1){
                    preNode = preNode.next;
                    position++;
            }
            
            preNode.next=preNode.next.next;
            preNode.next.prior=preNode;
        }
        list.size--;
    }
    
    /* 初始条件:顺序线性表L已存在 */
    /* 操作结果:依次对L的每个数据元素输出 */
    void listTraverse(DupleLoopLinkList<T> list){
        int position = 0;
        Node<T> tempNode = head;
        while(position != size){
            System.out.println(tempNode.data);
            tempNode = tempNode.next;
            position++;
        }
    }
    
    //(尾插法)
     public void addFromTail(T data){
         Node<T> newNode = new Node<T>(data);
         newNode.next=head;
         newNode.prior=head.prior;
         head.prior.next=newNode;
         head.prior=newNode;
         size++;
     }
     
     //(头插法)
     public void addFromHead(T data){
         Node<T> newNode = new Node<T>(data);
         newNode.next=head;
         newNode.prior=head.prior;
         head.prior.next=newNode;
         head=newNode;
         size++;
     }
     
     public static int clearList3(DupleLoopLinkList<Integer> l){
            //无法做到像C语言中的free(),直接放到内存空间
            l = new DupleLoopLinkList<Integer>();
            return 1;
        }
     
     public static void main(String[] args){
            DupleLoopLinkList<Integer> L = new DupleLoopLinkList<Integer>();
            Integer e;
            int j,k;
            L.initList(L);
            System.out.println("初始化L后:ListLength(L)=%d\n"+L.listLength(L));
            for(j=1;j<=5;j++)
                    L.listInsert(L,j,j);
            System.out.println("在L的表头依次插入1~5后:L.data=");
            L.listTraverse(L); 
            
            System.out.println("ListLength(L)=%d \n"+L.listLength(L));
            System.out.println("L是否空:i=%d(1:是 0:否)\n"+L.listEmpty(L));
            L.clearListAll(L);
            
            /*L=L.clearList2(L);*/
            System.out.println("L是否空:i=%d(1:是 0:否)\n"+L.listEmpty(L));
            
            System.out.println("清空L后:ListLength(L)=%d\n"+L.listLength(L));
            

            for(j=1;j<=10;j++)
                    L.listInsert(L,j,j);
            System.out.println("在L的表尾依次插入1~10后:L.data=");
            L.listTraverse(L); 

            System.out.println("ListLength(L)=%d \n"+L.listLength(L));

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

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

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

            System.out.println("依次输出L的元素:");
            L.listTraverse(L); 
     }
}
发布了222 篇原创文章 · 获赞 54 · 访问量 9万+

猜你喜欢

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