数据结构之链表

链表

  • 是一个物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的
  • 存储结构(和数组对比)
    • 数组需要连续内存
    • 链表不需要,也就是不需要整块内存,更适合有很多碎片内存的环境
  • 组成:由一个数据域(存储数据元素),一个指针域(存储下一个节点地址)
  • 类型
    • 单链表
      • 每个节点都有一个指向下一个的节点,尾部下一个指向的是null
    • 循环链表
      • 在单链表的基础上,把尾部的指针指向了头部
    • 双向链表
      • 每个节点都有两个指针,一个指向下一个节点,一个指向上一个节点,头部的上一个节点为null,尾部的下一个节点为null
    • 双向循环链表
      • 在双向链表的基础上,尾部的节点指向头部
  • 和数组性能对比
    • 网上都说数组的查询快,增删改慢,链表是增删改快,查询慢,但是如果先初始化list的话,越长的新增的话,链表是没有数组快的
 
 
  public static void main(String[] args) {

      long listBefore = System.currentTimeMillis();
      doAdd();
      long listAfter = System.currentTimeMillis();
      System.out.println("list add spend {}"+(listBefore -listAfter));
      long linkedBefore = System.currentTimeMillis();
      doLinkenAdd();
      long linkedAfter = System.currentTimeMillis();
      System.out.println("linkd add spend {}"+(linkedBefore -linkedAfter));

  }

  private static void doLinkenAdd() {
      LinkedList<Object> objects = new LinkedList<>();
      for(int i =0;i < 10000000 ;i++){
          objects.add(i);
      }
  }

  private static void doAdd() {
   List list =   new ArrayList<>(10000000);
   for(int i =0;i < 10000000 ;i++){
       list.add(i);
   }
  }

public class MyLinkedlist<E> {
 private Node head;
 private Node end;
 private int size;

 static class Node<E> {
     private Node<E> prv;
     private Node<E> next;
     E node;

     public Node() {
     }

     public Node(Node prv, Node next, E node) {
         this.next = next;
         this.node = node;
         this.prv = prv;
     }
 }

 public void add(E e) {
     if (head == null && end == null) {
         Node node = new Node<>(null, null, e);
         end = node;
         head = node;

     } else {
         //如果里面已经有数据的情况下,就只需要将自己挂在尾部
         Node<E> eNode = new Node<>(end, null, e);
         end.next = eNode;
         end = eNode;
     }
     size++;
 }

 public void remove(E e) {
     Node first = head;
     for (int i = 0; i < size; i++) {
         if (first.node.equals(e)) {
             removeNode(first);
         } else {
             first = first.next;
         }
     }
 }

 private void removeNode(Node first) {
     //判断是否只剩下一个节点
     if (size > 1) {
         //判断是否首尾节点,首节点的话,只需要把下一个节点的前置索引设置为null,再把head更新下
         if (first.prv == null) {
             Node node = first.next;
             node.prv = null;
             this.head = node;
             //如果是尾部节点,只需要上一个节点的后置索引设置为null,在把end更新
         } else if (first.next == null) {
             Node node = first.prv;
             node.next = null;
             end = node;
             //如果是中间节点,取前后两节点,相互建立关联
         } else {
             Node prvNode = first.prv;
             Node nextNode = first.next;
             prvNode.next = nextNode;
             nextNode.prv = nextNode;
         }
     }else{
         head = null;
         end = null;
     }
     size -- ;
 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值