阅读 111

数据结构之双向链表详细(java版)

前言

链表是一种线性表,常见的线性表还有栈、队列,本篇主要是分析双向链表的数据结构,以及如何使用java自己实现一个双向链表。在分析双向链表前,有必要先看看单向链表的数据结构图,方便对比双向链表数据结构。

1、单向链表

百度百科:单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始;链表是使用指针进行构造的列表;又称为结点列表,因为链表是由一个个结点组装起来的;其中每个结点都有指针成员变量指向列表中的下一个结点。 在这里插入图片描述 删除操作后: 在这里插入图片描述

2、双向链表

百度百科:双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。 在这里插入图片描述 删除操作后: 在这里插入图片描述

3、手写实现

public class CoolList<T> {     //节点个数     public int size;     //头节点     private SummerNode<T> first;     //尾节点     private SummerNode<T> last;     //定义节点类型     private static class SummerNode<T> {         //节点元素         T t;         //前一个节点地址         SummerNode<T> pre;         //后一个节点地址         SummerNode<T> next;         SummerNode(SummerNode<T> pre,T t,SummerNode<T> next){             this.t = t;             this.pre = pre;             this.next = next;         }     }     /**      * 更新指定位置的元素      * @param index 位置      * @param t 元素      * @return 返回旧值      */     public T replace(int index,T t){         //检查节点是否存在         checkExistNode(index);         //获取指定位置节点         SummerNode<T> exist = node(index);         T oldValue = exist.t;         //替换新值         exist.t = t;         return oldValue;     }     /**      * 在指定位置之前插入元素      * @param index      * @param t      * @return 成功返回true      */     public boolean beforeIndexInsert(int index,T t){         //检查节点是否存在         checkExistNode(index);         //获取节点         SummerNode<T> node = node(index);         //前一个节点         SummerNode<T> pre = node.pre;         //插入的节点在pre节点和node节点之间         final SummerNode<T> newNode = new SummerNode<>(pre, t, node);         node.pre = newNode;         if(pre == null){             //如果插入的位置是第一个节点前             first = newNode;         } else {             pre.next = newNode;         }         //元素+1         size++;         return true;     }     //在末尾插入     public boolean lastInsert(T t){         final SummerNode<T> l = last;         final SummerNode<T> newNode = new SummerNode<>(l, t, null);         last = newNode;         if(l == null){             //如果是首次插入元素,设置为第一个节点             first = newNode;         } else {             l.next = newNode;         }         size++;         return true;     }     private void checkExistNode(int index){         if(index < 0 || index > size){             throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size+";");         }     }     /**      * 获取指定位置节点元素      * @param index      * @return      */     public T get(int index){         checkExistNode(index);         return node(index).t;     }     /**      * 获取指定位置的节点      * @param index      * @return      */     SummerNode<T> node(int index){         //二分法查找,小于size/2,则顺序查找         if(index < (size >> 1)){             SummerNode<T> x = first;             for(int i=0; i<index; i++){                 x = x.next;             }             return x;         } else {             SummerNode<T> x = last;             //倒序查找             for (int i = size-1; i > index; i--){                 x = x.pre;             }             return x;         }     }     /**      * 移除指定位置的节点      * @param index      * @return      */     public T remove(int index){         //查找节点是否存在         checkExistNode(index);         //删除节点         return unlink(node(index));     }     /**      * 移除指定元素的节点      * @param t      * @return      */     public boolean remove(T t){         //为空         if(t == null){             for(SummerNode<T> x=first; x!=null; x=x.next){                 //查出为空的元素,再删除                 if(x.t == null){                     unlink(x);                     return true;                 }             }         } else {             //不为空,查出不为空的元素,然后删除             for(SummerNode<T> x=first; x!=null; x=x.next){                 if(t.equals(x.t)){                     unlink(x);                     return true;                 }             }         }         return false;     }     /**      * 删除节点      * @param node      * @return      */     private T unlink(SummerNode<T> node){         final T type = node.t;         //删除节点的前一个节点         final SummerNode<T> pre = node.pre;         //删除节点的后一个节点         final SummerNode<T> next = node.next;         //头结点         if(pre == null){             first = next;         } else {             pre.next = next;             node.pre = null;         }         //尾结点         if(next == null){             last = pre;         } else {             next.pre = pre;             node.next = null;         }         node.t = null;         size--;         return type;     } } 复制代码

测试代码:

public class CoolListTest {     public static void main(String[] args) {         CoolList<String> coolList = new CoolList<>();         //增加         coolList.lastInsert("cool");         coolList.lastInsert("moon");         coolList.lastInsert("单向链表");         coolList.lastInsert("的");         coolList.lastInsert("单向链表");         //删除         coolList.remove(2);         //修改         coolList.replace(coolList.size - 1,"双向链表");         //插入         coolList.beforeIndexInsert(1,"summer");         StringBuffer sb = new StringBuffer();         for (int i=0; i<coolList.size; i++){             //查找             sb.append(coolList.get(i)).append(" ");         }         System.out.println(sb);     } } 复制代码

控制台输出:

cool summer moon 的 双向链表


作者:夏夜凉月
链接:https://juejin.cn/post/7027750954711662605


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐