zoukankan      html  css  js  c++  java
  • java实现单项链表(复制,自己总结的在下一篇)

    1. 一、单向链表的结构。  
    2.   
    3.      (1)、首先节点的结构,其中包含本节点内容,以及需要指向下一个节点。   
    4.   
    5.   
    6. Java代码    
    7. private static class Entry<E>{     
    8.         E e;     
    9.         Entry<E> nextEntry;     
    10.               
    11.         public Entry(E e,Entry<E> nextEntry){     
    12.             this.e=e;     
    13.             this.nextEntry=nextEntry;     
    14.         }     
    15.     }    
    16.   
    17. private static class Entry<E>{  
    18.         E e;  
    19.         Entry<E> nextEntry;  
    20.            
    21.         public Entry(E e,Entry<E> nextEntry){  
    22.             this.e=e;  
    23.             this.nextEntry=nextEntry;  
    24.         }  
    25.     }Java代码    
    26.     
    27.   
    28.   
    29. Java代码    
    30.     
    31.   
    32.  其中e则指向本节点的对象,而nextEntry则指向下一个节点。  
    33.   
    34.    
    35.   
    36.      (2)、任何时候都需要知道表头在哪里。毕竟是单向链表嘛,因为只有一个方向,找到了表头就能找到全部。          
    37.   
    38. Java代码    
    39. private  Entry<E> head;    
    40.   
    41. private  Entry<E> head;   
    42.   
    43.      (3)、还可以记录链表中总共有多少个节点。它是在某些判断时为了提高效率而存在的。不是绝对需要的。毕竟知道表头后,一个一个按顺序去寻找就好了。  
    44.   
    45.   
    46. Java代码    
    47. private  int size;     
    48.     
    49. public int size(){     
    50.         return this.size;     
    51.     }    
    52.   
    53. private  int size;  
    54.   
    55. public int size(){  
    56.         return this.size;  
    57.     }  
    58. Java代码    
    59.     
    60.   
    61.     好了有这三样,就足够了。就看我们如何用他们了。  
    62.   
    63.    
    64.   
    65. 二、内部实现。  
    66.   
    67.     (1)、第一次向链表中插入。此时链表中节点为null,第一次插入,无非就是把节点头插入而已。   
    68.   
    69. 可以看出就是把链表头初始化了,并且链表大小涨1。其中modCount记录整个链表修改的次数,链表的增加和删除它都会增加。毕竟第一次插入相对外调用是透明的,所以应该是私有的咯。(透明就是不可见,这里只得是外部没必要知道它的存在)  
    70.   
    71. Java代码    
    72. private void addFirst(E e){     
    73.         head=new Entry<E>(e,null);     
    74.         size++;     
    75.         modCount++;     
    76.     }    
    77.   
    78. private void addFirst(E e){  
    79.         head=new Entry<E>(e,null);  
    80.         size++;  
    81.         modCount++;  
    82.     }   
    83.   
    84.     (2)、表头插入。在链表的头前插入一个元素,新增的元素变成新的表头。这个插入是效率最高的,毕竟你时刻知道链表的头在哪里。  
    85.   
    86. Java代码    
    87. public void addHead(E e){     
    88.         if(head==null){     
    89.             this.addFirst(e);     
    90.         }else{     
    91.             Entry<EnewEntry=new Entry<E>(e,head);     
    92.             head=newEntry;     
    93.             size++;     
    94.             modCount++;     
    95.         }     
    96.     }    
    97.   
    98. public void addHead(E e){  
    99.         if(head==null){  
    100.             this.addFirst(e);  
    101.         }else{  
    102.             Entry<EnewEntry=new Entry<E>(e,head);  
    103.             head=newEntry;  
    104.             size++;  
    105.             modCount++;  
    106.         }  
    107.     }可以看出头为null的时候,则表明链表中没值,只需调用第一次插入。否则对给定的元素创新增一个节点,新增节点的下一个指向头节点,当然此时自己已经变成头结点了,索引要更新头节点的引用。(可以看出想要清空链表,只需要将头置为null就好了)  
    108.   
    109.    
    110.   
    111.    (3)、指定节点插入(插队)。在链表的指定节点插入一个元素,效率非常低。由于规则上你只能从队伍第一个开始往后找,找到你要插队位置的前一个,并将你插入其中,你先要告诉你身前人你在他身后,并且你自己要清楚你身后是谁。反正够麻烦的。  
    112.   
    113.   
    114. Java代码    
    115. public void addSpecifyIndex(E e,int index){     
    116.         if(index<0||index>size||size==0){     
    117.             throw new NoSuchElementException();     
    118.         }     
    119.         if(index==0){     
    120.             this.addHead(e);     
    121.             return;     
    122.         }     
    123.         int count=0;     
    124.         for (Entry<Ep=head; p!=null;p=p.nextEntry) {     
    125.             if(count+1==index){     
    126.                 Entry<EnewEntry=new Entry<E>(e,p.nextEntry);     
    127.                 p.nextEntry=newEntry;     
    128.                 size++;     
    129.                 modCount++;     
    130.                 return;     
    131.             }     
    132.             count++;     
    133.         }     
    134.     }    
    135.   
    136. public void addSpecifyIndex(E e,int index){  
    137.         if(index<0||index>size||size==0){  
    138.             throw new NoSuchElementException();  
    139.         }  
    140.         if(index==0){  
    141.             this.addHead(e);  
    142.             return;  
    143.         }  
    144.         int count=0;  
    145.         for (Entry<Ep=head; p!=null;p=p.nextEntry) {  
    146.             if(count+1==index){  
    147.                 Entry<EnewEntry=new Entry<E>(e,p.nextEntry);  
    148.                 p.nextEntry=newEntry;  
    149.                 size++;  
    150.                 modCount++;  
    151.                 return;  
    152.             }  
    153.             count++;  
    154.         }  
    155.     }  
    156. Java代码    
    157.     
    158.   
    159. 先进行判断index是否正确,规定不能插入null链表。而且不能跳着走,毕竟链表要连起来。由于要找到前一个,但是表头的前一个是没有的,所以index==0时要单独判断。后面则用count进行计数,找到其index-1节点,然后进行插队处理。  
    160.   
    161.    
    162.   
    163.     (4)、尾插入。其实也是插队了,只是总是需要插到最后一个之后。  
    164.   
    165. Java代码    
    166. public void add(E e){     
    167.         if(head==null){     
    168.             this.addFirst(e);     
    169.         }else{     
    170.             this.addSpecifyIndex(e, size);     
    171.         }     
    172.     }    
    173.   
    174. public void add(E e){  
    175.         if(head==null){  
    176.             this.addFirst(e);  
    177.         }else{  
    178.             this.addSpecifyIndex(e, size);  
    179.         }  
    180.     }   
    181.   
    182.     (5)、指定节点获取元素。效率低,同样从头开始找到指定的节点把其中元素取出  
    183.   
    184.   
    185. Java代码    
    186. public E get(int index){     
    187.         if(index<0||index>=size){     
    188.             throw new NoSuchElementException();     
    189.         }     
    190.         E result=null;     
    191.         int count=0;     
    192.         for (Entry<Ep=head;p!=null;p=p.nextEntry) {     
    193.             if(count==index){     
    194.                 result=p.e;     
    195.             }     
    196.             count++;     
    197.         }     
    198.         return result;     
    199.     }    
    200.   
    201. public E get(int index){  
    202.         if(index<0||index>=size){  
    203.             throw new NoSuchElementException();  
    204.         }  
    205.         E result=null;  
    206.         int count=0;  
    207.         for (Entry<Ep=head;p!=null;p=p.nextEntry) {  
    208.             if(count==index){  
    209.                 result=p.e;  
    210.             }  
    211.             count++;  
    212.         }  
    213.         return result;  
    214.     }  
    215. Java代码    
    216.     
    217.   
    218.    
    219.   
    220.     (6)、指定节点删除。效率低,同样需要找到指定节点前一节点,直接把指定节点跳过就好了。  
    221.   
    222. Java代码    
    223. public void remove(int index){     
    224.         if(index<0||index>=size){     
    225.             throw new NoSuchElementException();     
    226.         }     
    227.         if(index==0){     
    228.             head=head.nextEntry;     
    229.             size--;     
    230.             modCount++;     
    231.             return;     
    232.         }     
    233.         int count=0;     
    234.         for (Entry<Ep=head;p.nextEntry!=null;p=p.nextEntry) {     
    235.             if(count+1==index){     
    236.                 p.nextEntry=p.nextEntry.nextEntry;     
    237.                 size--;     
    238.                 modCount++;     
    239.                 break;     
    240.             }     
    241.             count++;     
    242.         }     
    243.     }    
    244.   
    245. public void remove(int index){  
    246.         if(index<0||index>=size){  
    247.             throw new NoSuchElementException();  
    248.         }  
    249.         if(index==0){  
    250.             head=head.nextEntry;  
    251.             size--;  
    252.             modCount++;  
    253.             return;  
    254.         }  
    255.         int count=0;  
    256.         for (Entry<Ep=head;p.nextEntry!=null;p=p.nextEntry) {  
    257.             if(count+1==index){  
    258.                 p.nextEntry=p.nextEntry.nextEntry;  
    259.                 size--;  
    260.                 modCount++;  
    261.                 break;  
    262.             }  
    263.             count++;  
    264.         }  
    265.     }   
    266.   
    267.    (7)、循环。为了好进行遍历演示,下面的就是循环遍历所用的了,大家随意看一下就好了。  
    268.   
    269.    
    270.   
    271. Java代码    
    272. private transient Entry<E> current;     
    273.     
    274. public void setCursor(int index){     
    275.         if(index<0||index>=size){     
    276.             throw new NoSuchElementException();     
    277.         }     
    278.         int count=0;     
    279.         for (Entry<Ep=head;p!=null;p=p.nextEntry) {     
    280.             if(count==index){     
    281.                 current=p;     
    282.                 break;     
    283.             }     
    284.             count++;     
    285.         }     
    286.     }     
    287.          
    288.     public boolean hasNext(){     
    289.         return current!=null;     
    290.     }     
    291.          
    292.     public E next(){     
    293.         E result=current.e;     
    294.         current=current.nextEntry;     
    295.         return result;     
    296.     }    
    297.   
    298. private transient Entry<E> current;  
    299.   
    300. public void setCursor(int index){  
    301.         if(index<0||index>=size){  
    302.             throw new NoSuchElementException();  
    303.         }  
    304.         int count=0;  
    305.         for (Entry<Ep=head;p!=null;p=p.nextEntry) {  
    306.             if(count==index){  
    307.                 current=p;  
    308.                 break;  
    309.             }  
    310.             count++;  
    311.         }  
    312.     }  
    313.       
    314.     public boolean hasNext(){  
    315.         return current!=null;  
    316.     }  
    317.       
    318.     public E next(){  
    319.         E result=current.e;  
    320.         current=current.nextEntry;  
    321.         return result;  
    322.     }   
    323.   
    324. 三、测试。。一个main方法,测试一下。  
    325.   
    326. Java代码    
    327. public static void main(String[] args) {     
    328.         SingleChain<StringsingleChain=new SingleChain<String>();     
    329.         for (int i = 0; i 4; i++) {     
    330.             singleChain.add(i+"");     
    331.         }     
    332.         //头插入     
    333. //      singleChain.addHead("head");     
    334.         //尾插入     
    335. //      singleChain.add("tail");     
    336.         //指定节点插入     
    337. //      singleChain.addSpecifyIndex("Specify", 1);     
    338.         //指定节点删除     
    339. //      singleChain.remove(3);     
    340.         //设置循环的初始节点     
    341.         singleChain.setCursor(0);     
    342.         int count=0;     
    343.         System.out.println("######SIZE"+singleChain.size()+"#######");     
    344.         while(singleChain.hasNext()){     
    345.             System.out.println("index:"+count+",entry:"+singleChain.next());     
    346.             count++;     
    347.         }     
    348.              
    349.         System.out.println(singleChain.get(singleChain.size()-1));     
    350.     }    
    351.   
    352. public static void main(String[] args) {  
    353.         SingleChain<StringsingleChain=new SingleChain<String>();  
    354.         for (int i = 0; i 4; i++) {  
    355.             singleChain.add(i+"");  
    356.         }  
    357.         //头插入  
    358. //      singleChain.addHead("head");  
    359.         //尾插入  
    360. //      singleChain.add("tail");  
    361.         //指定节点插入  
    362. //      singleChain.addSpecifyIndex("Specify", 1);  
    363.         //指定节点删除  
    364. //      singleChain.remove(3);  
    365.         //设置循环的初始节点  
    366.         singleChain.setCursor(0);  
    367.         int count=0;  
    368.         System.out.println("######SIZE"+singleChain.size()+"#######");  
    369.         while(singleChain.hasNext()){  
    370.             System.out.println("index:"+count+",entry:"+singleChain.next());  
    371.             count++;  
    372.         }  
    373.           
    374.         System.out.println(singleChain.get(singleChain.size()-1));  
    375.     }   
    376.   
    377.    
    378.   
    379. 四、全部代码  
    380.   
    381.    
    382.   
    383. Java代码    
    384. package paladin.chain;     
    385.     
    386. import java.util.NoSuchElementException;     
    387.     
    388. public class SingleChain<E> implements Chain<E>{     
    389.          
    390.     private  Entry<E> head;     
    391.          
    392.     private transient Entry<E> current;     
    393.          
    394.     private  int size;     
    395.          
    396.     private  int modCount;     
    397.          
    398.          
    399.     private void addFirst(E e){     
    400.         head=new Entry<E>(e,null);     
    401.         size++;     
    402.         modCount++;     
    403.     }     
    404.          
    405.     public void addHead(E e){     
    406.         if(head==null){     
    407.             this.addFirst(e);     
    408.         }else{     
    409.             Entry<EnewEntry=new Entry<E>(e,head);     
    410.             head=newEntry;     
    411.             size++;     
    412.             modCount++;     
    413.         }     
    414.     }     
    415.          
    416.     public void addSpecifyIndex(E e,int index){     
    417.         if(index<0||index>size||size==0){     
    418.             throw new NoSuchElementException();     
    419.         }     
    420.         if(index==0){     
    421.             this.addHead(e);     
    422.             return;     
    423.         }     
    424.         int count=0;     
    425.         for (Entry<Ep=head; p!=null;p=p.nextEntry) {     
    426.             if(count+1==index){     
    427.                 Entry<EnewEntry=new Entry<E>(e,p.nextEntry);     
    428.                 p.nextEntry=newEntry;     
    429.                 size++;     
    430.                 modCount++;     
    431.                 return;     
    432.             }     
    433.             count++;     
    434.         }     
    435.     }     
    436.          
    437.     public void add(E e){     
    438.         if(head==null){     
    439.             this.addFirst(e);     
    440.         }else{     
    441.             this.addSpecifyIndex(e, size);     
    442.         }     
    443.     }     
    444.          
    445.     public E get(int index){     
    446.         if(index<0||index>=size){     
    447.             throw new NoSuchElementException();     
    448.         }     
    449.         E result=null;     
    450.         int count=0;     
    451.         for (Entry<Ep=head;p!=null;p=p.nextEntry) {     
    452.             if(count==index){     
    453.                 result=p.e;     
    454.             }     
    455.             count++;     
    456.         }     
    457.         return result;     
    458.     }     
    459.          
    460.     public void remove(int index){     
    461.         if(index<0||index>=size){     
    462.             throw new NoSuchElementException();     
    463.         }     
    464.         if(index==0){     
    465.             head=head.nextEntry;     
    466.             size--;     
    467.             modCount++;     
    468.             return;     
    469.         }     
    470.         int count=0;     
    471.         for (Entry<Ep=head;p.nextEntry!=null;p=p.nextEntry) {     
    472.             if(count+1==index){     
    473.                 p.nextEntry=p.nextEntry.nextEntry;     
    474.                 size--;     
    475.                 modCount++;     
    476.                 break;     
    477.             }     
    478.             count++;     
    479.         }     
    480.     }     
    481.          
    482.     public void setCursor(int index){     
    483.         if(index<0||index>=size){     
    484.             throw new NoSuchElementException();     
    485.         }     
    486.         int count=0;     
    487.         for (Entry<Ep=head;p!=null;p=p.nextEntry) {     
    488.             if(count==index){     
    489.                 current=p;     
    490.                 break;     
    491.             }     
    492.             count++;     
    493.         }     
    494.     }     
    495.          
    496.     public boolean hasNext(){     
    497.         return current!=null;     
    498.     }     
    499.          
    500.     public E next(){     
    501.         E result=current.e;     
    502.         current=current.nextEntry;     
    503.         return result;     
    504.     }     
    505.          
    506.     public int size(){     
    507.         return this.size;     
    508.     }     
    509.          
    510.     public static void main(String[] args) {     
    511.         SingleChain<StringsingleChain=new SingleChain<String>();     
    512.         for (int i = 0; i 4; i++) {     
    513.             singleChain.add(i+"");     
    514.         }     
    515.         //头插入     
    516. //      singleChain.addHead("head");     
    517.         //尾插入     
    518. //      singleChain.add("tail");     
    519.         //指定节点插入     
    520. //      singleChain.addSpecifyIndex("Specify", 1);     
    521.         //指定节点删除     
    522. //      singleChain.remove(3);     
    523.         //设置循环的初始节点     
    524.         singleChain.setCursor(0);     
    525.         int count=0;     
    526.         System.out.println("######SIZE"+singleChain.size()+"#######");     
    527.         while(singleChain.hasNext()){     
    528.             System.out.println("index:"+count+",entry:"+singleChain.next());     
    529.             count++;     
    530.         }     
    531.              
    532.         System.out.println(singleChain.get(singleChain.size()-1));     
    533.     }     
    534.          
    535.     private static class Entry<E>{     
    536.         E e;     
    537.         Entry<E> nextEntry;     
    538.               
    539.         public Entry(E e,Entry<E> nextEntry){     
    540.             this.e=e;     
    541.             this.nextEntry=nextEntry;     
    542.         }     
    543.     }     
    544. }   
  • 相关阅读:
    机器学习之KNN算法学习笔记
    机器学习之决策树算法学习笔记
    RNN神经网络
    深度学习笔记-Tensorflow(一)
    CNN卷积神经网络-tensorflow
    个人喜欢的网址
    CSP2020游记
    题解 GDFZOJ 2020普转提十连测day5
    讲义 GDFZOJ 【38】 动态规划基础3
    题解 GDFZOJ 【2314】 东风谷早苗
  • 原文地址:https://www.cnblogs.com/xingege/p/4074039.html
Copyright © 2011-2022 走看看