• 双向链表的实现


       链表一般有单向链表,双向链表和双向循环链表三种

      双向链表的每一个结点有着三个主要部分:1,存储数据的数据域   2,存储前指针的指针域   3,存储后指针的指针域 

      

      

      1.MyList接口定义功能

     1 public interface MyList<T>{
     2     //新增一个元素
     3     void add(T element);
     4     //删除与输入元素相同的元素
     5     void delete(T element);
     6     //根据索引删除元素
     7     void delete(int index);
     8     //更新元素
     9     void update(int index,T newelement);
    10     //查询1
    11     boolean contains(T element);
    12     
    13     T at(int index);
    14     
    15     int indexOf(T element);
    16 }

      2.ListNode结点类

     1 public class ListNode<T> {
     2       T data;    
     3       ListNode pre; //前驱结点
     4       ListNode next; //后驱结点
     5     
     6     public ListNode()
     7     {
     8         
     9     }
    10     public ListNode(T element)
    11     {
    12         this.data=element;
    13     }
    14     
    15     
    16 }

      3.DoubleLinkedList类

      1 public class DoubleLinkedList<T> implements MyList<T>{
      2     private ListNode<T> first=new ListNode<T>(); //头结点哑元
      3     private ListNode<T> last=new ListNode<T>(); //尾结点哑元
      4     private int size=0; //记录添加的个数
      5     
      6     public DoubleLinkedList()
      7     {
      8         first.next=last;
      9         last.pre=first;
     10     }
     11     
     12     @Override
     13     public void add(T element) {
     14         ListNode<T> newNode=new ListNode<T>(element);
     15         //注意添加结点的顺序
     16         last.pre.next=newNode;
     17         newNode.pre=last.pre;
     18         newNode.next=last;
     19         last.pre=newNode;
     20         size++;
     21     }
     22 
     23     @Override
     24     public void delete(T element) {
     25         ListNode<T> p=first.next; //复制一个头结点,以免后面操作影响头结点
     26         while(p!=null)
     27         {
     28             if(p.data.equals(element))
     29             {
     30                 p.pre.next=p.next;
     31                 p.next.pre=p.pre;
     32                 size--;
     33                 return ;
     34             }
     35             p=p.next;
     36         }
     37         
     38     }
     39 
     40     @Override
     41     public void delete(int index) {
     42         int i=0;
     43         ListNode<T> p=first.next;
     44         while(p!=last)
     45         {
     46             if(i==index)
     47             {
     48                 p.pre.next=p.next;
     49                 p.next.pre=p.pre;
     50                 p.pre=null;
     51                 p.next=null;
     52                 size--;
     53                 return ;
     54             }
     55             p=p.next;
     56             i++;
     57         }
     58         
     59     }
     60 
     61     @Override
     62     public void update(int index, T newelement) {
     63         int i=0;
     64         ListNode<T> p=first.next;
     65         while(p!=null)
     66         {
     67             if(i==index)
     68             {
     69                 p.data=newelement;
     70             }
     71             p=p.next;
     72             i++;
     73         }
     74         
     75         
     76     }
     77 
     78     @Override
     79     public boolean contains(T element) {
     80         return indexOf(element)>=0;
     81     }
     82 
     83     @Override
     84     public T at(int index) {
     85         int i=0;
     86         ListNode<T> p=first.next;
     87         while(p!=null)
     88         {
     89             if(i==index)
     90             {
     91                 return (T) p.data;
     92             }
     93             p=p.next;
     94             i++;
     95         }
     96         return null;
     97     }
     98 
     99     @Override
    100     public int indexOf(T element) {
    101         int i=0;
    102         ListNode<T> p=first.next;
    103         while(p!=null)
    104         {
    105             if(p.data.equals(element))
    106             {
    107                 return i;
    108             }
    109             p=p.next;
    110             i++;
    111         }
    112         return -1;
    113     }
    114     
    115     @Override
    116     public String toString()
    117     {
    118         StringBuilder sb=new StringBuilder("[");
    119         ListNode<T> p=first.next;
    120         while(p!=last)
    121         {
    122             sb.append(p.data+(p.next!=last?",":""));
    123             
    124             p=p.next;
    125         }
    126         sb.append("]");
    127         return sb.toString();
    128     }
    129 
    130     public int getSize()
    131     {
    132         return this.size;
    133     }
    134     
    135 
    136 }

    单向链表:只有一个指向下一个节点的指针。

    优点:单向链表增加删除节点简单。遍历时候不会死循环;

    缺点:只能从头到尾遍历。只能找到后继,无法找到前驱,也就是只能前进。

    适用于节点的增加删除。

    双向链表:有两个指针,一个指向前一个节点,一个后一个节点。

    优点:可以找到前驱和后继,可进可退;

    缺点:增加删除节点复杂,多需要分配一个指针存储空间。

    适用于需要双向查找节点值的情况。

  • 相关阅读:
    Veritca 简单安装配置过程
    本地环回,引发的血案
    Centos8的网络管理
    在做自动化测试之前你需要知道的什么是自动化测?
    APP移动测试用例总结
    Appium做Android功能自动化测试
    Selenium Webdriver模拟鼠标键盘操作
    线程锁 创建两个线程,其中一个输出152,另外一个输出AZ。要求使用线程锁,使输出为: 12A 34B 56C 78D Y
    Win10安装MongoDb Y
    linux下Docker安装 Y
  • 原文地址:https://www.cnblogs.com/LgxBoKeYuan/p/10176433.html
Copyright © 2020-2023  润新知