• JAVA数据结构--LinkedList双向链表


    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
     
     
     
    本文是按照《数据结构与算法分析》一书实现的双向链表的内容,个人认为链表的难点在于插入和删除的操作,但这点也是链表的优势之处。
      1 package DataStructures;
      2 
      3 import java.util.ConcurrentModificationException;
      4 import java.util.Iterator;
      5 import java.util.NoSuchElementException;
      6 
      7 public class MyLinkedList<AnyType> implements Iterable<AnyType> {
      8     /*
      9      * data当前节点的值
     10      * prev当前节点的前缀节点
     11      * next当前节点的后缀节点
     12      * */
     13     private static class Node<AnyType>{
     14         public Node(AnyType d,Node<AnyType> p,Node<AnyType> n){
     15             data=d;
     16             prev=p;
     17             next=n;
     18         }
     19         public AnyType data;
     20         public Node<AnyType> prev;
     21         public Node<AnyType> next;
     22     }
     23     public MyLinkedList() {
     24         doClear();
     25         // TODO Auto-generated constructor stub
     26     }
     27     public void clear(){
     28         doClear();
     29     }
     30     /* doClear()
     31      * 将头结点置空
     32      * 尾节点的前缀置为头节点
     33      * 头结点的后缀为尾节点
     34      * */
     35     private void doClear(){
     36         beginMarker=new Node<AnyType>(null, null, null);
     37         endMarker=new Node<AnyType>(null, beginMarker, null);
     38         beginMarker.next=endMarker;
     39         theSize=0;
     40         modCount++;
     41     }
     42 
     43     public int size(){
     44         return theSize;
     45     }
     46     public boolean isEmpty(){
     47         return size()==0;
     48     }
     49     /*
     50      * 在链表尾部插入新节点
     51      * */
     52     public boolean add(AnyType x){
     53         add(size(), x);
     54         return true;
     55     }
     56     /*
     57      * 在链表中插入新节点
     58      * */
     59     public void add(int idx,AnyType x){
     60         addBefore(getNode(idx,0,size()),x);
     61     }
     62     public AnyType get(int idx){
     63         return getNode(idx).data;
     64     }
     65     /*
     66      * 修改某个节点的值
     67      * */
     68     public AnyType set(int idx,AnyType newVal){
     69         Node<AnyType> p=getNode(idx);//p为需要修改的节点
     70         AnyType oldVal=p.data;
     71         p.data=newVal;
     72         return oldVal;
     73     }
     74     public AnyType remove(int idx){
     75         return remove(getNode(idx));
     76     }
     77     
     78     /*
     79      * 在p节点前插入新的节点
     80      * */
     81     private void addBefore(Node<AnyType> p,AnyType x){
     82         Node<AnyType> newNode=new Node<>(x, p.prev, p);//新节点的前缀为p的前缀,后缀为p
     83         newNode.prev.next=newNode;//新节点的前缀的后缀为新节点
     84         p.prev=newNode;//p节点的前缀为p
     85         theSize++;
     86         modCount++;
     87     }
     88     private AnyType remove(Node<AnyType> p){
     89         p.next.prev=p.prev;
     90         p.prev.next=p.next;
     91         theSize--;
     92         modCount++;
     93         return p.data;
     94     }
     95     private Node<AnyType> getNode(int idx){
     96         return getNode(idx,0,size()-1);
     97     }
     98     /*
     99      * 获得某个节点
    100      * */
    101     private Node<AnyType> getNode(int idx,int lower,int upper){
    102         Node<AnyType> p;
    103         if(idx<lower||idx>upper)
    104             throw new IndexOutOfBoundsException();
    105         if(idx<size()/2){//如果节点在前半部分,将从头结点向后开始遍历
    106             p=beginMarker.next;
    107             for(int i=0;i<idx;i++)
    108                 p=p.next;
    109         }
    110         else {//如果节点在后半部分,将从尾节点向前遍历
    111             p=endMarker;
    112             for(int i=size();i>idx;i--)
    113                 p=p.prev;
    114         }
    115         return p;
    116     }
    117     @Override
    118     public Iterator<AnyType> iterator() {
    119         // TODO Auto-generated method stub
    120         return new LinkedListIterator();
    121     }
    122     private class LinkedListIterator implements Iterator<AnyType>{
    123         private Node<AnyType> current=beginMarker;
    124         private int expectedModCount=modCount;
    125         private boolean okToRemove=false;
    126         public boolean hasNext(){
    127             return current!=endMarker;
    128         } 
    129         public AnyType next(){ 
    130             if(modCount!=expectedModCount)
    131                 throw new ConcurrentModificationException();
    132             if(!hasNext())
    133                 throw new NoSuchElementException();
    134             AnyType nextItem=current.data;
    135             current=current.next;
    136             okToRemove=true;
    137             return nextItem;
    138         }
    139         public void remove(){
    140             if(modCount!=expectedModCount)
    141                 throw new ConcurrentModificationException();
    142             if(!okToRemove)
    143                 throw new IllegalStateException();
    144             MyLinkedList.this.remove(current.prev);
    145             expectedModCount++;
    146             okToRemove=false;
    147         }
    148     }
    149     
    150     private int theSize;//链表的长度
    151     private int modCount;//链表改动的次数
    152     private Node<AnyType> beginMarker;//头结点
    153     private Node<AnyType> endMarker;//尾节点
    154 }
  • 相关阅读:
    正则表达式
    javascript if(条件)------------条件中可以使用的值
    maven配置
    获取中文日期
    Oracle无安装客户端安装方法
    Eclipse org.eclipse.compare plug-in
    Differences or similarities between Java and C++
    Java Programming Guidelines
    Native Method
    Object in Java same as pointer
  • 原文地址:https://www.cnblogs.com/xpang0/p/7543581.html
Copyright © 2020-2023  润新知