zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    第八章 多线程编程
    Linked List Cycle II
    Swap Nodes in Pairs
    Container With Most Water
    Best Time to Buy and Sell Stock III
    Best Time to Buy and Sell Stock II
    Linked List Cycle
    4Sum
    3Sum
    Integer to Roman
  • 原文地址:https://www.cnblogs.com/vi3nty/p/7543581.html
Copyright © 2011-2022 走看看