• java与数据结构(4)---java实现双向循环链表


    线性表之链式存储结构双向循环链表

    双向循环链表:每个结点包含了数据、直接前驱地址指针和直接后驱地址指针,头结点的直接前驱指向尾结点,尾结点的直接后驱指向头结点,头尾相连构成一个可正可反的圆环。可以形象的理解成一群孩子手拉手牵成一个圆圈,从头一个孩子开始可以从左往右报数,也可以从右往左开始报数。

    优点:双向循环链表可以迅速的获取当前数据的前驱数据,解决了单向循环链表从头开始遍历的麻烦。

    接口类

     1 package list;
     2 
     3 public interface Listable<T> {
     4     
     5     public void clear();
     6 
     7     public boolean isEmpty();
     8 
     9     public int Length();
    10 
    11     public T getElement(int index);
    12 
    13     public boolean add(T element);
    14 
    15     public boolean addHead(T element);
    16 
    17     public boolean addByIndex(int index, T element);
    18 
    19     public boolean add(Listable<T> list);
    20 
    21     public T remove(int index);
    22 
    23     public boolean removeAll();
    24 
    25     public T remove(T element);
    26 
    27     public T setElement(int index,T element);
    28 
    29 }
    View Code

    结点类

     1 //结点类
     2 class Node<T> {
     3     private Node<T> left,right;
     4     private T data;
     5 
     6     Node(T data) {
     7         this(data,null,null);
     8     }
     9 
    10     Node() {
    11         this(null,null,null);
    12     }
    13 
    14     Node(T data,Node<T> left,Node<T> right) {
    15         this.data = data;
    16         this.left = left;
    17         this.right = right;
    18     }
    19 
    20     public T getData() {
    21         return this.data;
    22     }
    23 
    24     public Node<T> getLeft() {
    25         return this.left;
    26     }
    27 
    28     public Node<T> getRight() {
    29         return this.right;
    30     }
    31 
    32     public void setData(T data) {
    33         this.data = data;
    34     }
    35 
    36     public void setRight(Node<T> right) {
    37         this.right = right;
    38     }
    39 
    40     public void setLeft(Node<T> left) {
    41         this.left = left;
    42     }
    43 
    44     public String toString() {
    45         return getData().toString();
    46     }
    47 }
    View Code

    接口实现类

      1 //接口实现类
      2 class DoubleLinkedList<T> implements Listable<T> {
      3     public Node<T> head;
      4     
      5     //建空表,带头结点
      6     DoubleLinkedList() {
      7         this(null);
      8     }
      9     
     10     //建表,带头结点,表中有一条数据元素
     11     DoubleLinkedList(T element) {
     12         if(element == null) {
     13             head = new Node<T>(element,null,null);
     14             head.setRight(head);
     15             head.setLeft(head);
     16         }else {
     17             Node<T> headRight = new Node<T>(element,null,null);
     18             head = new Node<T>(null,headRight,headRight);
     19             headRight.setLeft(head);
     20             headRight.setRight(head);
     21         }
     22     }
     23 
     24     //清空当前链表
     25     public void clear() {}
     26     
     27     //判空表
     28     public boolean isEmpty() {
     29         return head.getRight() == head;
     30     }
     31 
     32     //表长
     33     public int Length() {
     34         int len = 0;
     35         Node<T> temp = head;
     36         while(temp.getRight() != head) {
     37             len++;
     38             temp = temp.getRight();
     39         }
     40         return len;
     41     }
     42     
     43     //取下标index处的数据
     44     public T getElement(int index) {
     45         if(index <= 0) {
     46             return head.getRight().getData();
     47         }
     48         int len = Length();
     49         if(index >=  len) {
     50             return head.getLeft().getData();
     51         }
     52         T element = null;
     53         if(index > 0 && index < len) {
     54             int k = 0;
     55             Node<T> temp = head;
     56             //此处只能用while不能用if,用错好几次
     57             while(k <= index && temp.getRight() != head) {
     58                 k++;
     59                 temp = temp.getRight();
     60             }
     61             element = temp.getData();
     62         }
     63         return element;
     64     }
     65 
     66     //尾添
     67     public boolean add(T element) {
     68         if(element == null) return false;
     69         Node<T> node = new Node<T>(element,head.getLeft(),head);
     70         head.getLeft().setRight(node);
     71         head.setLeft(node);
     72         return true;
     73     }
     74     
     75     //首添
     76     public boolean addHead(T element) {
     77         if(element == null) return false;
     78         Node<T> node = new Node<T>(element,head,head.getRight());
     79         head.getRight().setLeft(node);
     80         head.setRight(node);
     81         return false;
     82     }
     83     
     84     //表index处,添加新数据element
     85     public boolean addByIndex(int index, T element) {
     86         if(index <= 0) {
     87             return addHead(element);
     88         }else if(index >= Length()) {
     89             return add(element);
     90         }else {
     91             int k = 0;
     92             Node<T> temp = head;
     93             //此处只能用while不能用if,用错好几次
     94             while(k <= index && temp.getRight() != head) {
     95                 k++;
     96                 temp = temp.getRight();
     97             }
     98             Node<T> node = new Node<T>(element,temp.getLeft(),temp);
     99             temp.getLeft().setRight(node);
    100             temp.setLeft(node);
    101         }
    102         return true;
    103     }
    104 
    105     //将参数中的链表添加到当前链表的尾部
    106     public boolean add(Listable<T> slist) {
    107         if(slist.isEmpty() || slist == null) return false;
    108         if(slist instanceof DoubleLinkedList) {
    109             DoubleLinkedList<T> list = (DoubleLinkedList<T>)slist;
    110             //以下操作影响到了添加的slist表,所以需要将slist表重新备份一个
    111             DoubleLinkedList<T> temp = new DoubleLinkedList<T>();
    112             for(int i = 0; i < list.Length(); i++) {
    113                 temp.add(list.getElement(i));
    114             }
    115             Node<T> node = temp.head;
    116             Node<T> nodeLeft = node.getLeft();
    117             Node<T> nodeRight = node.getRight();
    118             this.head.getLeft().setRight(node.getRight());
    119             nodeRight.setLeft(this.head.getLeft());
    120             nodeLeft.setRight(this.head);
    121             this.head.setLeft(node.getLeft());
    122             return true;
    123         }else {
    124             return false;
    125         }
    126     }
    127     
    128     //删除下标Index处的数据
    129     public T remove(int index) {
    130         if(isEmpty()) return null;
    131         if(index < 0) {
    132             index = 0;
    133         }
    134         int len =  Length();
    135         if(index >= len) {
    136             //当index大于或等于表长是,默认移走表的最后一个元素,即下标为len-1的数据
    137             index = len-1;
    138         }
    139         T element = null;
    140         if(index >= 0 && index < len) {
    141             Node<T> temp = head;
    142             int k = 0;
    143             while(k <= index && temp.getRight() != head) {
    144                 k++;
    145                 temp = temp.getRight();
    146             }
    147             element = temp.getData();
    148             temp.getRight().setLeft(temp.getLeft());
    149             temp.getLeft().setRight(temp.getRight());
    150             temp.setRight(null);
    151             temp.setLeft(null);
    152             temp = null;
    153         }
    154         return element;
    155     }
    156 
    157     //删除当前链表中所有的数据,只剩头结点
    158     public boolean removeAll() {
    159         if(isEmpty()) return false;
    160         Node<T> temp = head.getRight();
    161         while(temp != head) {
    162             head.setRight(temp.getRight());
    163             temp.getRight().setLeft(head);
    164             temp.setLeft(null);
    165             temp.setRight(null);
    166             temp = head.getRight();
    167         }
    168         return true;
    169     }
    170 
    171     //删除链表中从head开始的第一个element数据
    172     public T remove(T element) {
    173         if(isEmpty() || element == null) return null;
    174         //从表中第一个元素开始比较
    175         Node<T> temp = head.getRight();
    176         int k=0;
    177         while(temp != head) {
    178             if(element.equals(temp.getData())) {
    179                 remove(k);
    180                 return element;
    181             }else {
    182                 temp = temp.getRight();
    183                 k++;
    184             }
    185         }
    186         if(k == (Length()-1)) {
    187             System.out.println("该链表中没有该数据");
    188         }
    189         return element;
    190     }
    191 
    192     //修改下标index处的数据,并将原始数据返回
    193     public T setElement(int index,T element) {
    194         if(index < 0 || index >= Length()) return null;
    195         Node<T> temp = head;
    196         int k = 0;
    197         while(k < index && temp.getRight() != head) {
    198             k++;
    199             temp = temp.getRight();
    200         }
    201         T tempEle = temp.getData();
    202         temp.setData(element);
    203         return tempEle;
    204     }
    205     
    206     //重写父类toString方法,实际是给list做遍历后将数据打印出来
    207     public String toString() {
    208         StringBuffer sb = new StringBuffer();
    209         /*通过for循环遍历双向循环链表
    210         int length = Length();
    211         sb.append("[ ");
    212         for(int i = 0; i < length; i++) {
    213             sb.append(getElement(i)+" ");
    214         }
    215         sb.append("]");
    216         */
    217         //从表头开始遍历双向循环链表
    218         sb.append("[ ");
    219         Node<T> node = head;
    220         while(node.getRight() != head) {
    221             sb.append(node.getRight().getData()+" ");
    222             node = node.getRight();
    223         }
    224         sb.append("]");
    225         return sb.toString();
    226     }
    227 
    228 }
    View Code

    测试类

     1 package list;
     2 
     3 //************************************************
     4 //*双向循环链表-java实现(画图分析会容易理解得多)
     5 //************************************************
     6 
     7 public class TestDoubleLinkedList {
     8     public static void main(String[] args) {
     9         Listable<String> list = new DoubleLinkedList<String>("a");
    10         list.add("b");
    11         list.add("c");
    12         list.addByIndex(3,"e");
    13         list.addByIndex(3,"d");
    14         list.addByIndex(5,"f");
    15         System.out.println(list);
    16         list.addHead("A");
    17         System.out.println(list.Length());
    18         System.out.println(list);
    19         Listable<String> list1 = new DoubleLinkedList<String>("123456");
    20         list.add(list1);
    21         System.out.println(list);
    22         list.remove(100);
    23         list.add("123456");
    24         System.out.println("list="+list);
    25         System.out.println(list1);
    26         list1.removeAll();
    27         System.out.println(list1+"  list1 is Empty??"+list1.isEmpty());
    28         list.remove("123456");
    29         System.out.println("list="+list);
    30         System.out.println("remove item="+list.remove("A"));
    31         System.out.println("list="+list);
    32     }
    33 }
    View Code

    完整代码

      1 package list;
      2 
      3 //************************************************
      4 //*双向循环链表-java实现(画图分析会容易理解得多)
      5 //************************************************
      6 
      7 public class TestDoubleLinkedList {
      8     public static void main(String[] args) {
      9         Listable<String> list = new DoubleLinkedList<String>("a");
     10         list.add("b");
     11         list.add("c");
     12         list.addByIndex(3,"e");
     13         list.addByIndex(3,"d");
     14         list.addByIndex(5,"f");
     15         System.out.println(list);
     16         list.addHead("A");
     17         System.out.println(list.Length());
     18         System.out.println(list);
     19         Listable<String> list1 = new DoubleLinkedList<String>("123456");
     20         list.add(list1);
     21         System.out.println(list);
     22         list.remove(100);
     23         list.add("123456");
     24         System.out.println("list="+list);
     25         System.out.println(list1);
     26         list1.removeAll();
     27         System.out.println(list1+"  list1 is Empty??"+list1.isEmpty());
     28         list.remove("123456");
     29         System.out.println("list="+list);
     30         System.out.println("remove item="+list.remove("A"));
     31         System.out.println("list="+list);
     32     }
     33 }
     34 
     35 //结点类
     36 class Node<T> {
     37     private Node<T> left,right;
     38     private T data;
     39 
     40     Node(T data) {
     41         this(data,null,null);
     42     }
     43 
     44     Node() {
     45         this(null,null,null);
     46     }
     47 
     48     Node(T data,Node<T> left,Node<T> right) {
     49         this.data = data;
     50         this.left = left;
     51         this.right = right;
     52     }
     53 
     54     public T getData() {
     55         return this.data;
     56     }
     57 
     58     public Node<T> getLeft() {
     59         return this.left;
     60     }
     61 
     62     public Node<T> getRight() {
     63         return this.right;
     64     }
     65 
     66     public void setData(T data) {
     67         this.data = data;
     68     }
     69 
     70     public void setRight(Node<T> right) {
     71         this.right = right;
     72     }
     73 
     74     public void setLeft(Node<T> left) {
     75         this.left = left;
     76     }
     77 
     78     public String toString() {
     79         return getData().toString();
     80     }
     81 }
     82 
     83 //接口实现类
     84 class DoubleLinkedList<T> implements Listable<T> {
     85     public Node<T> head;
     86     
     87     //建空表,带头结点
     88     DoubleLinkedList() {
     89         this(null);
     90     }
     91     
     92     //建表,带头结点,表中有一条数据元素
     93     DoubleLinkedList(T element) {
     94         if(element == null) {
     95             head = new Node<T>(element,null,null);
     96             head.setRight(head);
     97             head.setLeft(head);
     98         }else {
     99             Node<T> headRight = new Node<T>(element,null,null);
    100             head = new Node<T>(null,headRight,headRight);
    101             headRight.setLeft(head);
    102             headRight.setRight(head);
    103         }
    104     }
    105 
    106     //清空当前链表
    107     public void clear() {}
    108     
    109     //判空表
    110     public boolean isEmpty() {
    111         return head.getRight() == head;
    112     }
    113 
    114     //表长
    115     public int Length() {
    116         int len = 0;
    117         Node<T> temp = head;
    118         while(temp.getRight() != head) {
    119             len++;
    120             temp = temp.getRight();
    121         }
    122         return len;
    123     }
    124     
    125     //取下标index处的数据
    126     public T getElement(int index) {
    127         if(index <= 0) {
    128             return head.getRight().getData();
    129         }
    130         int len = Length();
    131         if(index >=  len) {
    132             return head.getLeft().getData();
    133         }
    134         T element = null;
    135         if(index > 0 && index < len) {
    136             int k = 0;
    137             Node<T> temp = head;
    138             //此处只能用while不能用if,用错好几次
    139             while(k <= index && temp.getRight() != head) {
    140                 k++;
    141                 temp = temp.getRight();
    142             }
    143             element = temp.getData();
    144         }
    145         return element;
    146     }
    147 
    148     //尾添
    149     public boolean add(T element) {
    150         if(element == null) return false;
    151         Node<T> node = new Node<T>(element,head.getLeft(),head);
    152         head.getLeft().setRight(node);
    153         head.setLeft(node);
    154         return true;
    155     }
    156     
    157     //首添
    158     public boolean addHead(T element) {
    159         if(element == null) return false;
    160         Node<T> node = new Node<T>(element,head,head.getRight());
    161         head.getRight().setLeft(node);
    162         head.setRight(node);
    163         return false;
    164     }
    165     
    166     //表index处,添加新数据element
    167     public boolean addByIndex(int index, T element) {
    168         if(index <= 0) {
    169             return addHead(element);
    170         }else if(index >= Length()) {
    171             return add(element);
    172         }else {
    173             int k = 0;
    174             Node<T> temp = head;
    175             //此处只能用while不能用if,用错好几次
    176             while(k <= index && temp.getRight() != head) {
    177                 k++;
    178                 temp = temp.getRight();
    179             }
    180             Node<T> node = new Node<T>(element,temp.getLeft(),temp);
    181             temp.getLeft().setRight(node);
    182             temp.setLeft(node);
    183         }
    184         return true;
    185     }
    186 
    187     //将参数中的链表添加到当前链表的尾部
    188     public boolean add(Listable<T> slist) {
    189         if(slist.isEmpty() || slist == null) return false;
    190         if(slist instanceof DoubleLinkedList) {
    191             DoubleLinkedList<T> list = (DoubleLinkedList<T>)slist;
    192             //以下操作影响到了添加的slist表,所以需要将slist表重新备份一个
    193             DoubleLinkedList<T> temp = new DoubleLinkedList<T>();
    194             for(int i = 0; i < list.Length(); i++) {
    195                 temp.add(list.getElement(i));
    196             }
    197             Node<T> node = temp.head;
    198             Node<T> nodeLeft = node.getLeft();
    199             Node<T> nodeRight = node.getRight();
    200             this.head.getLeft().setRight(node.getRight());
    201             nodeRight.setLeft(this.head.getLeft());
    202             nodeLeft.setRight(this.head);
    203             this.head.setLeft(node.getLeft());
    204             return true;
    205         }else {
    206             return false;
    207         }
    208     }
    209     
    210     //删除下标Index处的数据
    211     public T remove(int index) {
    212         if(isEmpty()) return null;
    213         if(index < 0) {
    214             index = 0;
    215         }
    216         int len =  Length();
    217         if(index >= len) {
    218             //当index大于或等于表长是,默认移走表的最后一个元素,即下标为len-1的数据
    219             index = len-1;
    220         }
    221         T element = null;
    222         if(index >= 0 && index < len) {
    223             Node<T> temp = head;
    224             int k = 0;
    225             while(k <= index && temp.getRight() != head) {
    226                 k++;
    227                 temp = temp.getRight();
    228             }
    229             element = temp.getData();
    230             temp.getRight().setLeft(temp.getLeft());
    231             temp.getLeft().setRight(temp.getRight());
    232             temp.setRight(null);
    233             temp.setLeft(null);
    234             temp = null;
    235         }
    236         return element;
    237     }
    238 
    239     //删除当前链表中所有的数据,只剩头结点
    240     public boolean removeAll() {
    241         if(isEmpty()) return false;
    242         Node<T> temp = head.getRight();
    243         while(temp != head) {
    244             head.setRight(temp.getRight());
    245             temp.getRight().setLeft(head);
    246             temp.setLeft(null);
    247             temp.setRight(null);
    248             temp = head.getRight();
    249         }
    250         return true;
    251     }
    252 
    253     //删除链表中从head开始的第一个element数据
    254     public T remove(T element) {
    255         if(isEmpty() || element == null) return null;
    256         //从表中第一个元素开始比较
    257         Node<T> temp = head.getRight();
    258         int k=0;
    259         while(temp != head) {
    260             if(element.equals(temp.getData())) {
    261                 remove(k);
    262                 return element;
    263             }else {
    264                 temp = temp.getRight();
    265                 k++;
    266             }
    267         }
    268         if(k == (Length()-1)) {
    269             System.out.println("该链表中没有该数据");
    270         }
    271         return element;
    272     }
    273 
    274     //修改下标index处的数据,并将原始数据返回
    275     public T setElement(int index,T element) {
    276         if(index < 0 || index >= Length()) return null;
    277         Node<T> temp = head;
    278         int k = 0;
    279         while(k < index && temp.getRight() != head) {
    280             k++;
    281             temp = temp.getRight();
    282         }
    283         T tempEle = temp.getData();
    284         temp.setData(element);
    285         return tempEle;
    286     }
    287     
    288     //重写父类toString方法,实际是给list做遍历后将数据打印出来
    289     public String toString() {
    290         StringBuffer sb = new StringBuffer();
    291         /*通过for循环遍历双向循环链表
    292         int length = Length();
    293         sb.append("[ ");
    294         for(int i = 0; i < length; i++) {
    295             sb.append(getElement(i)+" ");
    296         }
    297         sb.append("]");
    298         */
    299         //从表头开始遍历双向循环链表
    300         sb.append("[ ");
    301         Node<T> node = head;
    302         while(node.getRight() != head) {
    303             sb.append(node.getRight().getData()+" ");
    304             node = node.getRight();
    305         }
    306         sb.append("]");
    307         return sb.toString();
    308     }
    309 
    310 }
    View Code

    后期会添加两个链表求交集等操作。

  • 相关阅读:
    认识ASP.NET 中的 AppDomain
    试验总结1 改变递归函数中的执行内容
    试验总结2 break与continue
    开篇的话
    01复杂度3 二分查找
    02线性结构2 一元多项式的乘法与加法运算
    01复杂度2 Maximum Subsequence Sum
    02线性结构4 Pop Sequence
    01复杂度1 最大子列和问题
    02线性结构1 两个有序链表序列的合并
  • 原文地址:https://www.cnblogs.com/nora-xie/p/3352909.html
Copyright © 2020-2023  润新知