Linear table of data structure in java

Linear table

Linear table is a very flexible data structure, its length can be increased or shortened according to the needs, that is to say, the data elements of linear table can not only be accessed, but also inserted and deleted

  • Linear table interface code
    interface List<T> {
    
        void destroyList();
        boolean listEmpty();
        void add(T dataElement);
        void traverse();
        void delete(int location);
        void insert(T dataElement, int location);
    }
    

Sequence table

The sequential representation of linear table refers to the storage of data elements of linear table with a group of storage units with continuous addresses, which is characterized by the same physical order of logically adjacent elements

  • Using array as storage container

  • Implementation code

    class SqList<T> implements List<T> {
    
       private final int MAX_SIZE = 100;
       private Object[] dataElements;
       private int length;
       
       public SqList() {
           // TODO Auto-generated constructor stub
           this.dataElements = new Object[MAX_SIZE];   //Generic T cannot be used as a modifier to create an array
           this.length = 0;
       }
    
       @Override
       public void destroyList() {
           // TODO Auto-generated method stub
           
           this.length = 0;
       }
    
       @Override
       public boolean listEmpty() {
           // TODO Auto-generated method stub
           if(this.length == 0)
               return true;
           else
               return false;
       }
    
       @Override
       public void add(T dataElement) {
           // TODO Auto-generated method stub
           this.dataElements[length++] = dataElement;
       }
    
       @Override
       public void traverse() {
           // TODO Auto-generated method stub
           for (int i = 0; i < this.length; i++) {
               System.out.print(dataElements[i] + " ");
           }
           System.out.println();
       }
    
       @Override
       public void delete(int location) {
           // TODO Auto-generated method stub
           for(int i = location; i < length ; i++) {  //To delete, move length location times
               
               dataElements[i-1] = dataElements[i];
           }
           dataElements[--length] = null; //Error prone: dataElements[length--] = null
       }
    
       @Override
       public void insert(T dataElement,int location) {
           // TODO Auto-generated method stub
           for(int i = length; i >= location ; i--) {  //Insert length location + 1 time
               
               dataElements[i] = dataElements[i - 1];
           }
           dataElements[location-1] = dataElement;
           length++;
       }  
    }
    
  • Code analysis

    • An array of type Object

      Because it is impossible to apply for an array of generic T type, an array of Object type is used instead. When adding data, the elements of generic T are added to the array (automatically up conversion), and the extracted elements are mandatory type conversion class output of generic T type
      
    • Number of moves during insert and delete operations

      • insert

          When inserting, it needs to move back from the specified location position (first from the end) to move (length location) + 1 time
        
      • delete

          When deleting, move forward from the last bit of the specified location position, and move the length location times (length location + 1 time is OK)
        

Chain list

Each independent storage cell is called a node. Each node is connected with the front and rear nodes by reference to form a linked list

Single chain table

The references in each node point to the successor nodes of the current node in one direction

  • code implementation

    class LinkList_BackUp<T> implements List<T> { //Creating linked list by interpolation
    
        private class Node{  //Node class
            
            private Node next;
            private T dataElement;
            
            public Node() {   //Construct head node
                // TODO Auto-generated constructor stub
                this.next = null;   //Next in node (connect next node)
                this.dataElement = null;
            }
            public Node(T dataElement) {  //Construct tail node
                // TODO Auto-generated constructor stub
                this.next = null;
                this.dataElement = dataElement;
            }
        }
        
        private int size;  //Number of nodes
        private Node headNode;
        private Node node; //Tail node
        
        public LinkList_BackUp(){
            this.size = 0;
            this.headNode = new Node();  //Initialize build header node
            node = headNode;  //Node start from the initial node and cascade the nodes step by step
        }
        
        @Override
        public void destroyList() {
            // TODO Auto-generated method stub
            headNode.next = null;
            node = headNode; //Reset node
            size = 0; //size reset
        }
    
        @Override
        public boolean listEmpty() {
            // TODO Auto-generated method stub
            if(size == 0)
                return true;
            else
                return false;
        }
    
        @Override
        public void add(T dataElement) {  //Add a new node at the end
            // TODO Auto-generated method stub
            Node newNode = new Node(dataElement);   //Temporary node
            //Determine whether the end node is deleted
            if(node == null) {   
                node = headNode;
                //When the end node is deleted, the previous node of the node will point to null, so the node will be discarded. When the node needs to be added again, it is necessary to relocate to the end node
                while(node.next != null) {
                    node = node.next;
                }
            }
            node.next = newNode;
            node = node.next;
            size++;
        }
    
        @Override
        public void traverse() {
            // TODO Auto-generated method stub
            Node tempNode = headNode.next;
            
            while(tempNode != null) {    //Judge whether the node is empty
                System.out.print(tempNode.dataElement + " ");
                tempNode = tempNode.next;
            }
            System.out.println();
        }
    
        @Override
        public void delete(int location) {
            // TODO Auto-generated method stub
            if(location > size)
                System.out.println("Cross border warning");
            
            Node tempNode = headNode;   //Temporary node as search node
            
            for(int i = 0; i < location - 1; i++) {  //Find the previous node of the corresponding node
                tempNode = tempNode.next;
            }
            //Delete the corresponding node
            tempNode.next = tempNode.next.next;
            
            if(location == size)//Set node to null when the end node is deleted
                node = null; //Equivalent to releasing the space of abandoned end nodes (GC will recycle automatically after dereference)
            
            size--;
            
        }
    
        @Override
        public void insert(T dataElement, int location) {
            // TODO Auto-generated method stub
            Node newNode = new Node(dataElement);
            Node tempNode = headNode;   //The temporary node is used as the search node
            
            for(int i = 0; i < location - 1; i++) {  //Find the previous node of the node corresponding to the location
                tempNode = tempNode.next;
            }
            newNode.next = tempNode.next;  //Connect the next of the new node to the node corresponding to localization
            tempNode.next = newNode; //Link the next of the previous node of the node corresponding to the location to the newNode
            size++;
        }    
    }
    
  • Code analysis

    • Node inner class

        The implementation class of each Node represents a Node, which includes data and references
      
    • How to deal with node nodes when adding elements again after deleting tail nodes

        When adding elements, the node node moves backward to link the new node to the tail node, so the node is always at the tail node. When the tail node is to be deleted, because the one-way linked list is not traceable, the node node is not the actual tail node, so the tail node needs to be relocated when adding again
      
    • Location location when inserting and deleting nodes

        When one-way nodes insert or delete, they need to find the previous node of the corresponding node to operate, and the bidirectional linked list is more flexible
      

Double linked list

There are two references in each node, which point to the predecessor node and successor node of the current node respectively

  • code implementation

      class DuLinkList<T> implements List<T> {
    
          private class Node{  //Node class
              
              private Node prior; //Pointing to the precursor
              private Node next;  //Point to successor
              private T dataElement; //Node elements of generics
              
              public Node() {   //Construct head node
                  // TODO Auto-generated constructor stub
                  this.prior = this;  //The front and back references in the header node point to themselves
                  this.next = this;   //Next in node (connect next node)
                  this.dataElement = null;
              }
              public Node(T dataElement) {  //Construct storage node
                  // TODO Auto-generated constructor stub
                  this.prior = null;
                  this.next = null;
                  this.dataElement = dataElement;
              }
          }
          
          private int size;  //Number of nodes
          private Node headNode; //Head node
          private Node node; //Tail node
          
          public DuLinkList() {   //Initializing double linked list
              // TODO Auto-generated constructor stub
              size = 0;
              headNode = new Node();
              node = headNode;//Initial tail node is the head node
          }
          @Override
          public void destroyList() {//Reset double linked list
              // TODO Auto-generated method stub
              headNode.next = headNode;
              headNode.prior = headNode;
              node = headNode;
              size = 0;
          }
    
          @Override
          public boolean listEmpty() {
              // TODO Auto-generated method stub
              if(size == 0)
                  return true;
              else
                  return false;
          }
    
          @Override
          public void add(T dataElement) {//Add node
              // TODO Auto-generated method stub
              Node newNode = new Node(dataElement);
              
              node.next = newNode; //Add a new node to the end of the tail node
              headNode.prior = newNode; //The precursor node of the head node points to the new node, forming a cycle
              
              newNode.prior = node; //The precursor of the new node points to the tail node
              newNode.next = headNode;//The back drive of the new node points to the head node, forming a cycle
              
              node = node.next;//Take the newly added node as the tail node
              size++;
          }
    
          @Override
          public void traverse() {
              // TODO Auto-generated method stub
              Node tempNode = headNode.next;
              
              while(tempNode != headNode) {    //When the current node is the head node, the loop ends
                  System.out.print(tempNode.dataElement + " ");
                  tempNode = tempNode.next;
              }
              System.out.println();
          }
    
          @Override
          public void delete(int location) {
              // TODO Auto-generated method stub
              if(location > size)
                  System.out.println("Cross border warning");
              else {
                  Node tempNode = headNode;
                  for(int i = 0; i < location; i++) { //Find the node corresponding to the location location
                      tempNode = tempNode.next;
                  }
                  //Delete the corresponding node
                  tempNode.prior.next = tempNode.next;  //The successor node of the previous node of the deleted node points to the next node of the deleted node
                  tempNode.next.prior = tempNode.prior;//Point the predecessor node of the next node of the deleted node to the previous node of the deleted node
                  
                  if(location == size)  
                      node = node.prior;  //When the end node is deleted, the end node is updated to the previous node of the node
                                          //This makes it convenient to add new nodes to the actual tail nodes next time
                  size--;
              }
          }
    
          @Override
          public void insert(T dataElement, int location) {
              // TODO Auto-generated method stub
              Node newNode = new Node(dataElement);
              Node tempNode = headNode;   //Temporary node as search node
              
              for(int i = 0; i < location; i++) {  //Find the node corresponding to location
                  tempNode = tempNode.next;
              }
              //Insert complete
              newNode.next = tempNode;  //Point the successor node of the newly inserted node to the inserted node
              newNode.prior = tempNode.prior; //Point the predecessor node of the newly inserted node to the previous node of the inserted node
              tempNode.prior.next = newNode; //Points the successor node of the previous node to the new node
              tempNode.prior = newNode; //Point the predecessor node of the inserted node to the new node
              
              size++;
          }
      }
    
  • Code analysis

    • Head node of double linked list

        Both the preceding and subsequent references of a bidirectional node point to itself
      
    • Adding double linked list

        1. Add the new node to the end of the tail node
        2. The precursor of the head node points to the new node
        3. The precursor of the new node points to the tail node
        4. The following reference of the new node points to the head node
      
    • Insertion of double linked list

        1. Find the inserted node corresponding to location
        2. Point the successor node of the newly inserted node to the inserted node
        3. Point the precursor node of the new inserted node to the previous node of the inserted node
        4. Point the successor node of the previous node to the new node
        5. Point the precursor node of the inserted node to the new node
      
    • Deletion of double linked list

        1. Find the node corresponding to location
        2. Point the successor node of the previous node of the deleted node to the next node of the deleted node
        3. Point the precursor node of the next node of the deleted node to the previous node of the deleted node
      
    • How to deal with the node problem of adding new elements after deleting the tail node of bidirectional linked list

        The reason and processing method are the same as the one-way linked list, but the bidirectional linked list is more simple in processing. Because the bidirectional linked list can be traced back, when the deletion operation is judged to be the tail node, the node is reset to the precursor node of the node
      

summary

  • swot
    • The total capacity of the sequence table is fixed
    • The sequential table is more efficient in locating and searching, and the efficiency is not poor when inserting and deleting a large number of elements
    • The capacity of linked list is unlimited
    • Insertion and deletion of linked list is more efficient than sequential list
  • Fallibility
    • How to deal with the node of adding new element after deleting the tail node
    • On the order of the links of the nodes in the insertion of the double linked list
    • The conversion of array defined by Object type instead of generic T type in order table

Posted by OriginalSixRules on Mon, 29 Jun 2020 01:16:28 -0700