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. }   
原文地址:https://www.cnblogs.com/xingege/p/4074039.html