Java数据结构之双向链表实现

链表数据结构简介

部分设计思想参考 https://blog.csdn.net/qq_33697094/article/details/121544972

  • 线性表:也叫顺序表,是多个元素的有序序列,他的元素与索引一一对应。线性表包含两大存储结构:顺序存储结构与链式存储结构

  • 数组:是线性表的顺序存储结构,指用地址中一段顺序存储单元依次存储数据元素

  • 链表:是线性表的链式存储结构,他的内存是不连续,每一个元素的地址由上一个元素来存储。

数组与链表的底层数据结构决定了他们自身的特点以及使用场景

  • 数组在顺序存储单元存储元素,当我们要进行搜索时,它可以直接根据下标来返回需要搜索元素,但当我们进行增删时,则需要来移动大量元素。
  • 链表的存储结构是不连续的,除头尾节点,每一个元素需要存储他的数据值以及上一个元素的节点对象,下一个元素的节点对象。 这一数据结构特点导致我们如果想要搜索链表时,每一次都需要从头或尾开始遍历链表。但当我们增加元素时,只需要将上一元素尾指针指向新元素头节点,将下一元素头指针指向新元素尾节点即可。

代码实现

  • 废话少说直接上代码

首先创建链表类 以及内部节点类

//链表类
public class DoubleLinkDemo<T> {
    
    

    private NodeDemo head;//头指针
    private NodeDemo tail;//尾指针
    private int length;//链表长度

    public DoubleLinkDemo(){
    
    
        this.length = 0;
    }
    public DoubleLinkDemo(T data){
    
    
        NodeDemo<T> tNodeDemo = new NodeDemo<>(data);//新建节点对象
        this.head = tNodeDemo;//将该节点对象赋值为头节点
        this.tail = head;//因为该链表只有一个节点,所以头尾指针指向相同节点
        length++;//链表长度+1
    }
}
//节点类
class NodeDemo<T>{
    
    
    T data; //节点存储 数据
    NodeDemo pre; //记录上一节点对象
    NodeDemo next;//记录下一节点对象

    public NodeDemo(){
    
    
        this(null,null,null);
    }
    public NodeDemo(T data){
    
    
        this(data,null,null);
    }
    public NodeDemo(T data,NodeDemo pre,NodeDemo next){
    
    
        this.data = data;
        this.pre =pre;
        this.next = next;
    }

}

链表类添加基本方法

  • 链表类基本方法包括
//是否为空
   public boolean isEmpty(){
    
    
    }
//长度
    public int length(){
    
    
    }
//头节点插入元素
    public void insertHead(T data){
    
    
    }
//尾节点插入元素
    public void insertTail(T data){
    
    
    }
//指定索引新增元素
    public void insertNode(T data,int index){
    
    
    }
//指定索引删除元素
    public void deleteNode(int index){
    
    
    }
//指定索引获取元素 
    public Object get(int index){
    
    
    }
//索引获取node对象 (此方法内部使用 为private)
    private NodeDemo getNode(int index) {
    
    
    }

基本方法实现

public class DoubleLinkDemo<T> {
    
    

  private NodeDemo head;//头指针
  private NodeDemo tail;//尾指针
  private int length;//链表长度

  public DoubleLinkDemo(){
    
    
      this.length = 0;
  }
  public DoubleLinkDemo(T data){
    
    
      NodeDemo<T> tNodeDemo = new NodeDemo<>(data);
      this.head = tNodeDemo;//新节点赋值为头节点
      this.tail = head;//由于链表只有一个元素 所以头尾指针都指向同一元素
      length++;//链表长度+1
  }
  //是否为空
  public boolean isEmpty() {
    
    
      return head == null;
  }

  //长度
  public int length() {
    
    
      return length;
  }


  //头插入
  public void insertHead(T data) {
    
    
      //为空
      if (isEmpty()) {
    
    
          NodeDemo<T> firstNode = new NodeDemo<>(data);
          head = firstNode;
          tail = head;
      } else {
    
    
          //链表不为空 则顺序插入
          NodeDemo<T> tNodeDemo = new NodeDemo<>(data);
          head.pre = tNodeDemo;//当前头节点前指针指向新元素
          tNodeDemo.next = head;//新元素尾指针指向当前头节点
          head = tNodeDemo;//将新元素赋值为头节点
      }
      length++;
  }


  //尾插入节点
  public void insertTail(T data) {
    
    
      if (isEmpty()) {
    
    
          insertHead(data);
      } else {
    
    
          //不为空顺序插入
          NodeDemo<T> tNodeDemo = new NodeDemo<>(data);
          this.tail.next = tNodeDemo;//当前尾指针尾节点指向新增元素
          tNodeDemo.pre = this.tail;//新元素头节点指向尾节点
          tail = tNodeDemo; //新元素设置为尾节点
          length++;
      }
  }
  //索引获取node对象
  private NodeDemo getNode(int index) {
    
    
      if (index < 0 || index > length - 1) {
    
    
          throw new IndexOutOfBoundsException("数组越界");
      }
      NodeDemo<Object> targetNode = new NodeDemo<>();
      targetNode = head;
      int tar = 0;
      while (targetNode!= null) {
    
    
          if (tar++ == index) {
    
    
              return targetNode;
          }
          targetNode = targetNode.next;
      }
      return null;
  }
  //根据指定索引获取节点
  public Object get(int index){
    
    
      return getNode(index).data;
  }

  //根据指定索引添加数据
  public void insertNode(T data,int index){
    
    
      if(index<0||index>length-1){
    
    
          throw new IndexOutOfBoundsException("数组越绝");
      }else if(index==0){
    
    
          insertHead(data);
      }else if(index ==length-1){
    
    
          insertTail(data);
      }else {
    
    
          NodeDemo nowNode = getNode(index);
          NodeDemo preNode = getNode(index - 1);
          NodeDemo<T> insertNode = new NodeDemo<>(data);
          preNode.next = insertNode;//节点对象互相赋值
          insertNode.pre = preNode;
          insertNode.next = nowNode;
          nowNode.pre = insertNode;
      }
      length++;
  }

  //根据指定索引删除数据
  public void deleteNode(int index){
    
    
      if(index<0||index>length-1){
    
    
          throw new IndexOutOfBoundsException("数组越界");
      }else if(index==0){
    
    
          head.next.pre = null;
          head = head.next;
      }else if(index ==length-1){
    
    
          tail.pre.next = null;
          tail =tail.pre;
      }else {
    
    
          NodeDemo preNode = getNode(index - 1);
          NodeDemo nextNode = getNode(index + 1);
          preNode.next = nextNode;
          nextNode.pre = preNode;
      }
      length--;
  }

}

class NodeDemo<T>{
    
    
  T data;
  NodeDemo pre;
  NodeDemo next;

  public NodeDemo(){
    
    
      this(null,null,null);
  }

  public NodeDemo(T data){
    
    
      this(data,null,null);
  }
  public NodeDemo(T data,NodeDemo pre,NodeDemo next){
    
    
      this.data = data;
      this.pre =pre;
      this.next = next;

  }

}


测试链表

public class Test {
    
    

    public static void main(String[] args) {
    
    


        DoubleLinkDemo<Integer> doubleLinkDemo = new DoubleLinkDemo<>();
        System.out.println(doubleLinkDemo.isEmpty());
        doubleLinkDemo.insertTail(1);
        System.out.println(doubleLinkDemo.isEmpty());
        System.out.println(doubleLinkDemo.get(0));
        doubleLinkDemo.insertHead(0);
        System.out.println(doubleLinkDemo.get(0));
        doubleLinkDemo.insertTail(2);
        System.out.println(doubleLinkDemo.get(2));
        doubleLinkDemo.insertHead(123);
        System.out.println(doubleLinkDemo.get(0));
        doubleLinkDemo.insertTail(456);
        System.out.println(doubleLinkDemo.get(4));
        doubleLinkDemo.deleteNode(4);
        System.out.println(doubleLinkDemo.get(4));
        
    }
}


输出结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/pgcdnameming/article/details/123125618