Doubly linked list implementation of Java data structure

Introduction to Linked List Data Structure

Some design ideas refer to https://blog.csdn.net/qq_33697094/article/details/121544972

  • Linear table: also called sequential table, is an ordered sequence of multiple elements, and its elements correspond to indexes one by one. The linear table contains two storage structures: sequential storage structure and chain storage structure

  • Array: It is a sequential storage structure of a linear table, which refers to using a sequential storage unit in the address to store data elements in sequence

  • Linked list: It is a linked storage structure of a linear list. Its memory is discontinuous, and the address of each element is stored by the previous element.

The underlying data structures of arrays and linked lists determine their own characteristics and usage scenarios

  • The array stores elements in sequential storage units. When we want to search, it can directly return the elements to be searched according to the subscript, but when we add or delete, we need to move a large number of elements.
  • The storage structure of the linked list is discontinuous. Except for the head and tail nodes, each element needs to store its data value, the node object of the previous element, and the node object of the next element. This data structure feature causes us to traverse the linked list from the beginning or the end every time we want to search the linked list. But when we add elements, we only need to point the tail pointer of the previous element to the head node of the new element, and point the head pointer of the next element to the tail node of the new element.

Code

  • Cut the nonsense and go directly to the code

First create the linked list class and the internal node class

//链表类
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;
    }

}

Linked list class to add basic methods

  • The basic methods of the linked list class include
//是否为空
   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) {
    
    
    }

Basic method implementation

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;

  }

}


test linked list

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));
        
    }
}


output result

insert image description here

Guess you like

Origin blog.csdn.net/pgcdnameming/article/details/123125618